From 67c6a4d1dccb62159b9d9b2dea4e2f487446e276 Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Fri, 26 Apr 2024 06:05:56 +0200 Subject: Adding upstream version 9.5.1+dfsg. Signed-off-by: Daniel Baumann --- CHANGELOG-v9.md | 1549 +++-- CHANGELOG-v9.rst | 621 +- PKG-INFO | 4 +- ansible.egg-info/PKG-INFO | 4 +- ansible.egg-info/SOURCES.txt | 675 ++- ansible.egg-info/requires.txt | 2 +- .../amazon/aws/.github/workflows/docs-pr.yml | 1 + ansible_collections/amazon/aws/CHANGELOG.rst | 28 +- ansible_collections/amazon/aws/FILES.json | 61 +- ansible_collections/amazon/aws/MANIFEST.json | 4 +- .../amazon/aws/changelogs/changelog.yaml | 27 +- .../amazon/aws/docs/docsite/rst/CHANGELOG.rst | 28 +- .../amazon/aws/plugins/module_utils/common.py | 2 +- .../amazon/aws/plugins/module_utils/iam.py | 191 +- .../aws/plugins/module_utils/transformation.py | 96 + .../modules/cloudwatchlogs_log_group_info.py | 17 +- .../amazon/aws/plugins/modules/iam_user_info.py | 19 +- .../amazon/aws/plugins/modules/s3_object.py | 9 +- .../amazon/aws/plugins/plugin_utils/inventory.py | 36 +- .../integration/targets/ec2_ami/tasks/main.yml | 4 +- .../tasks/multi_nested_target.yml | 18 +- .../playbooks/create_inventory_config.yml | 5 + .../inventory_aws_ec2/templates/config.ini.j2 | 3 + .../templates/inventory_with_template.yml.j2 | 2 +- .../tests/integration/targets/s3_object/aliases | 1 + .../targets/s3_object/tasks/copy_object.yml | 71 +- .../integration/targets/s3_object/tasks/main.yml | 4 +- .../iam/test_iam_resource_transforms.py | 583 ++ .../test_boto3_resource_to_ansible_dict.py | 140 + .../plugin_utils/inventory/test_inventory_base.py | 131 + .../tests/unit/plugins/inventory/test_aws_ec2.py | 1 + ansible_collections/ansible_community.py | 2 +- ansible_collections/ansible_release.py | 2 +- .../cisco/aci/.github/workflows/ansible-test.yml | 21 +- .../aci/.github/workflows/galaxy-importer.cfg | 2 +- ansible_collections/cisco/aci/CHANGELOG.rst | 78 + ansible_collections/cisco/aci/FILES.json | 4700 +++++++++++---- ansible_collections/cisco/aci/MANIFEST.json | 4 +- ansible_collections/cisco/aci/README.md | 2 +- .../cisco/aci/changelogs/.plugin-cache.yaml | 462 +- .../cisco/aci/changelogs/changelog.yaml | 98 + ansible_collections/cisco/aci/meta/runtime.yml | 65 +- .../cisco/aci/plugins/doc_fragments/aci.py | 10 + .../cisco/aci/plugins/filter/listify.py | 295 + .../cisco/aci/plugins/httpapi/aci.py | 13 - .../cisco/aci/plugins/module_utils/aci.py | 203 +- .../plugins/module_utils/annotation_unsupported.py | 853 +++ .../cisco/aci/plugins/module_utils/constants.py | 338 +- .../modules/aci_aaa_certificate_authority.py | 290 + .../cisco/aci/plugins/modules/aci_aaa_key_ring.py | 339 ++ .../modules/aci_aaa_security_default_settings.py | 531 ++ .../cisco/aci/plugins/modules/aci_aaa_ssh_auth.py | 4 +- .../aci_access_port_block_to_access_port.py | 158 +- ...access_port_to_interface_policy_leaf_profile.py | 2 +- .../modules/aci_access_spine_interface_profile.py | 279 + ...ne_interface_profile_to_spine_switch_profile.py | 292 + .../modules/aci_access_spine_interface_selector.py | 326 ++ .../modules/aci_access_spine_switch_profile.py | 277 + .../modules/aci_access_spine_switch_selector.py | 321 ++ .../aci_access_sub_port_block_to_access_port.py | 2 +- .../modules/aci_access_switch_policy_group.py | 600 ++ .../aci_action_rule_additional_communities.py | 304 + .../plugins/modules/aci_action_rule_set_as_path.py | 304 + .../modules/aci_action_rule_set_as_path_asn.py | 312 + .../cisco/aci/plugins/modules/aci_aep.py | 2 +- .../cisco/aci/plugins/modules/aci_aep_to_epg.py | 2 +- .../cisco/aci/plugins/modules/aci_bd.py | 238 +- .../plugins/modules/aci_bd_rogue_exception_mac.py | 299 + .../modules/aci_bd_to_netflow_monitor_policy.py | 292 + .../modules/aci_bfd_multihop_node_policy.py | 320 ++ .../aci_bgp_address_family_context_policy.py | 382 ++ .../plugins/modules/aci_bgp_best_path_policy.py | 12 +- .../plugins/modules/aci_bgp_peer_prefix_policy.py | 322 ++ .../modules/aci_bgp_route_summarization_policy.py | 310 + .../cisco/aci/plugins/modules/aci_bgp_rr_asn.py | 6 +- .../cisco/aci/plugins/modules/aci_bgp_rr_node.py | 6 +- .../aci/plugins/modules/aci_bgp_timers_policy.py | 12 +- .../cisco/aci/plugins/modules/aci_cloud_subnet.py | 53 +- .../aci/plugins/modules/aci_config_snapshot.py | 2 +- .../aci_contract_subject_to_service_graph.py | 2 +- .../cisco/aci/plugins/modules/aci_dhcp_option.py | 306 + .../aci/plugins/modules/aci_dhcp_option_policy.py | 276 + .../cisco/aci/plugins/modules/aci_dhcp_relay.py | 6 +- .../aci/plugins/modules/aci_dhcp_relay_provider.py | 6 +- .../cisco/aci/plugins/modules/aci_dns_domain.py | 4 +- .../cisco/aci/plugins/modules/aci_dns_profile.py | 4 +- .../cisco/aci/plugins/modules/aci_dns_provider.py | 2 +- .../cisco/aci/plugins/modules/aci_domain.py | 2 +- .../cisco/aci/plugins/modules/aci_encap_pool.py | 2 +- .../aci/plugins/modules/aci_encap_pool_range.py | 2 +- .../cisco/aci/plugins/modules/aci_epg.py | 71 +- .../aci/plugins/modules/aci_epg_to_contract.py | 74 +- .../modules/aci_epg_to_contract_interface.py | 2 +- .../cisco/aci/plugins/modules/aci_epg_to_domain.py | 4 +- .../aci_epg_useg_attribute_block_statement.py | 348 ++ .../aci_epg_useg_attribute_simple_statement.py | 436 ++ .../plugins/modules/aci_esg_ip_subnet_selector.py | 2 +- .../aci_fabric_external_connection_profile.py | 311 + .../modules/aci_fabric_external_routing_profile.py | 315 + .../modules/aci_fabric_interface_policy_group.py | 2 +- .../aci/plugins/modules/aci_fabric_leaf_profile.py | 2 +- .../modules/aci_fabric_management_access.py | 700 +++ .../aci_fabric_management_access_https_cipher.py | 282 + .../cisco/aci/plugins/modules/aci_fabric_pod.py | 292 + .../modules/aci_fabric_pod_connectivity_profile.py | 336 ++ .../plugins/modules/aci_fabric_pod_external_tep.py | 321 ++ .../aci/plugins/modules/aci_fabric_pod_profile.py | 267 + .../plugins/modules/aci_fabric_pod_remote_pool.py | 294 + .../aci/plugins/modules/aci_fabric_pod_selector.py | 4 +- .../plugins/modules/aci_fabric_spine_profile.py | 2 +- .../modules/aci_fabric_spine_switch_assoc.py | 2 +- .../aci/plugins/modules/aci_fabric_switch_block.py | 2 +- .../modules/aci_fabric_switch_policy_group.py | 32 +- .../plugins/modules/aci_fabric_wide_settings.py | 6 +- .../plugins/modules/aci_igmp_interface_policy.py | 4 +- .../aci/plugins/modules/aci_interface_blacklist.py | 6 +- .../plugins/modules/aci_interface_description.py | 6 +- .../plugins/modules/aci_interface_policy_bfd.py | 318 + .../modules/aci_interface_policy_bfd_multihop.py | 318 + .../plugins/modules/aci_interface_policy_eigrp.py | 371 ++ .../plugins/modules/aci_interface_policy_hsrp.py | 310 + .../aci_interface_policy_leaf_fc_policy_group.py | 2 +- .../aci_interface_policy_leaf_policy_group.py | 85 +- .../modules/aci_interface_policy_link_level.py | 5 +- .../plugins/modules/aci_interface_policy_pim.py | 444 ++ .../modules/aci_interface_policy_storm_control.py | 434 ++ .../cisco/aci/plugins/modules/aci_key_policy.py | 325 ++ .../aci/plugins/modules/aci_keychain_policy.py | 276 + .../cisco/aci/plugins/modules/aci_l2out.py | 4 +- .../cisco/aci/plugins/modules/aci_l2out_extepg.py | 6 +- .../modules/aci_l2out_extepg_to_contract.py | 4 +- .../modules/aci_l2out_logical_interface_path.py | 4 +- .../modules/aci_l2out_logical_interface_profile.py | 2 +- .../modules/aci_l2out_logical_node_profile.py | 2 +- .../cisco/aci/plugins/modules/aci_l3out.py | 88 +- .../modules/aci_l3out_bfd_interface_profile.py | 367 ++ .../aci_l3out_bfd_multihop_interface_profile.py | 366 ++ .../aci/plugins/modules/aci_l3out_bgp_peer.py | 163 +- .../plugins/modules/aci_l3out_dhcp_relay_label.py | 354 ++ .../modules/aci_l3out_eigrp_interface_profile.py | 392 ++ .../cisco/aci/plugins/modules/aci_l3out_extepg.py | 4 +- .../modules/aci_l3out_extepg_to_contract.py | 99 +- .../aci/plugins/modules/aci_l3out_extsubnet.py | 6 +- .../aci/plugins/modules/aci_l3out_floating_svi.py | 475 ++ .../plugins/modules/aci_l3out_floating_svi_path.py | 491 ++ .../aci_l3out_floating_svi_path_secondary_ip.py | 398 ++ .../modules/aci_l3out_floating_svi_secondary_ip.py | 362 ++ .../aci/plugins/modules/aci_l3out_hsrp_group.py | 393 ++ .../modules/aci_l3out_hsrp_interface_profile.py | 320 ++ .../modules/aci_l3out_hsrp_secondary_vip.py | 344 ++ .../aci/plugins/modules/aci_l3out_interface.py | 121 +- .../modules/aci_l3out_interface_secondary_ip.py | 6 +- .../modules/aci_l3out_logical_interface_profile.py | 202 +- ..._l3out_logical_interface_profile_ospf_policy.py | 19 +- .../aci_l3out_logical_interface_vpc_member.py | 2 +- .../aci/plugins/modules/aci_l3out_logical_node.py | 48 +- .../modules/aci_l3out_logical_node_profile.py | 40 +- .../aci/plugins/modules/aci_l3out_static_routes.py | 4 +- .../modules/aci_l3out_static_routes_nexthop.py | 2 +- .../modules/aci_l3out_to_sr_mpls_infra_l3out.py | 355 ++ .../plugins/modules/aci_maintenance_group_node.py | 2 +- .../plugins/modules/aci_match_route_destination.py | 2 +- .../plugins/modules/aci_netflow_exporter_policy.py | 490 ++ .../plugins/modules/aci_netflow_monitor_policy.py | 300 + .../modules/aci_netflow_monitor_to_exporter.py | 290 + .../plugins/modules/aci_netflow_record_policy.py | 313 + .../cisco/aci/plugins/modules/aci_node_block.py | 390 ++ .../cisco/aci/plugins/modules/aci_node_mgmt_epg.py | 6 +- .../cisco/aci/plugins/modules/aci_ntp_policy.py | 6 +- .../cisco/aci/plugins/modules/aci_ntp_server.py | 4 +- .../aci/plugins/modules/aci_pim_route_map_entry.py | 329 ++ .../plugins/modules/aci_pim_route_map_policy.py | 276 + .../aci/plugins/modules/aci_qos_custom_policy.py | 284 + .../aci/plugins/modules/aci_qos_dot1p_class.py | 355 ++ .../aci/plugins/modules/aci_qos_dscp_class.py | 356 ++ .../cisco/aci/plugins/modules/aci_rest.py | 48 +- .../cisco/aci/plugins/modules/aci_snmp_client.py | 2 +- .../aci/plugins/modules/aci_snmp_client_group.py | 2 +- .../plugins/modules/aci_snmp_community_policy.py | 2 +- .../cisco/aci/plugins/modules/aci_snmp_policy.py | 4 +- .../cisco/aci/plugins/modules/aci_snmp_user.py | 4 +- .../modules/aci_static_node_mgmt_address.py | 6 +- .../cisco/aci/plugins/modules/aci_subject_label.py | 746 +++ .../plugins/modules/aci_switch_leaf_selector.py | 30 +- .../aci_switch_policy_vpc_protection_group.py | 2 +- .../cisco/aci/plugins/modules/aci_syslog_group.py | 6 +- .../aci/plugins/modules/aci_syslog_remote_dest.py | 5 +- .../cisco/aci/plugins/modules/aci_syslog_source.py | 2 +- .../cisco/aci/plugins/modules/aci_system.py | 9 +- .../cisco/aci/plugins/modules/aci_tag.py | 6 +- .../modules/aci_tenant_action_rule_profile.py | 232 +- .../aci/plugins/modules/aci_vmm_controller.py | 22 +- .../aci/plugins/modules/aci_vmm_vswitch_policy.py | 4 +- .../cisco/aci/plugins/modules/aci_vrf_multicast.py | 702 +++ .../aci/plugins/modules/aci_vzany_to_contract.py | 4 +- .../aci/tests/integration/inventory.networking | 6 +- .../targets/aci_aaa_certificate_authority/aliases | 2 + .../aci_aaa_certificate_authority/pki/admin.crt | 14 + .../aci_aaa_certificate_authority/tasks/main.yml | 305 + .../aci_aaa_custom_privilege/tasks/main.yml | 28 +- .../targets/aci_aaa_domain/tasks/main.yml | 36 +- .../integration/targets/aci_aaa_key_ring/aliases | 2 + .../targets/aci_aaa_key_ring/pki/admin.crt | 14 + .../targets/aci_aaa_key_ring/pki/admin.key | 16 + .../targets/aci_aaa_key_ring/tasks/main.yml | 364 ++ .../targets/aci_aaa_role/tasks/main.yml | 34 +- .../aci_aaa_security_default_settings/aliases | 2 + .../tasks/main.yml | 235 + .../targets/aci_aaa_ssh_auth/tasks/main.yml | 12 +- .../targets/aci_aaa_user/tasks/main.yml | 14 +- .../aci_aaa_user_certificate/tasks/main.yml | 18 +- .../targets/aci_aaa_user_domain/tasks/main.yml | 24 +- .../targets/aci_aaa_user_role/tasks/main.yml | 32 +- .../tasks/main.yml | 152 +- .../tasks/main.yml | 74 +- .../aci_access_span_dst_group/tasks/main.yml | 2 +- .../aci_access_span_filter_group/tasks/main.yml | 4 +- .../tasks/main.yml | 4 +- .../aci_access_span_src_group/tasks/main.yml | 6 +- .../aci_access_span_src_group_src/tasks/main.yml | 6 +- .../tasks/main.yml | 4 +- .../aci_access_spine_interface_profile/aliases | 2 + .../tasks/main.yml | 183 + .../aliases | 2 + .../tasks/main.yml | 176 + .../aci_access_spine_interface_selector/aliases | 2 + .../tasks/main.yml | 204 + .../aci_access_spine_switch_profile/aliases | 2 + .../aci_access_spine_switch_profile/tasks/main.yml | 183 + .../aci_access_spine_switch_selector/aliases | 2 + .../tasks/main.yml | 193 + .../tasks/main.yml | 10 +- .../targets/aci_access_switch_policy_group/aliases | 2 + .../aci_access_switch_policy_group/tasks/main.yml | 1122 ++++ .../aci_action_rule_additional_communities/aliases | 2 + .../tasks/main.yml | 147 + .../targets/aci_action_rule_set_as_path/aliases | 2 + .../aci_action_rule_set_as_path/tasks/main.yml | 148 + .../aci_action_rule_set_as_path_asn/aliases | 2 + .../aci_action_rule_set_as_path_asn/tasks/main.yml | 156 + .../integration/targets/aci_aep/tasks/main.yml | 96 +- .../targets/aci_aep_to_domain/tasks/main.yml | 20 +- .../targets/aci_aep_to_epg/tasks/main.yml | 22 +- .../integration/targets/aci_ap/tasks/main.yml | 80 +- .../integration/targets/aci_bd/tasks/main.yml | 442 +- .../targets/aci_bd_dhcp_label/tasks/main.yml | 38 +- .../targets/aci_bd_rogue_exception_mac/aliases | 2 + .../aci_bd_rogue_exception_mac/tasks/main.yml | 186 + .../targets/aci_bd_subnet/tasks/main.yml | 18 +- .../targets/aci_bd_to_l3out/tasks/main.yml | 22 +- .../aci_bd_to_netflow_monitor_policy/aliases | 2 + .../tasks/main.yml | 191 + .../targets/aci_bfd_multihop_node_policy/aliases | 2 + .../aci_bfd_multihop_node_policy/tasks/main.yml | 245 + .../aci_bgp_address_family_context_policy/aliases | 2 + .../tasks/main.yml | 244 + .../aci_bgp_best_path_policy/tasks/main.yml | 36 +- .../targets/aci_bgp_peer_prefix_policy/aliases | 2 + .../aci_bgp_peer_prefix_policy/tasks/main.yml | 151 + .../aci_bgp_route_summarization_policy/aliases | 2 + .../tasks/main.yml | 255 + .../targets/aci_bgp_rr_asn/tasks/main.yml | 12 +- .../targets/aci_bgp_rr_node/tasks/main.yml | 16 +- .../targets/aci_bgp_timers_policy/tasks/main.yml | 36 +- .../aci_bulk_static_binding_to_epg/tasks/main.yml | 62 +- .../targets/aci_cloud_ap/tasks/main.yml | 10 +- .../targets/aci_cloud_aws_provider/tasks/main.yml | 8 +- .../targets/aci_cloud_bgp_asn/tasks/main.yml | 30 +- .../targets/aci_cloud_cidr/tasks/main.yml | 66 +- .../targets/aci_cloud_ctx_profile/tasks/main.yml | 54 +- .../targets/aci_cloud_epg/tasks/main.yml | 14 +- .../targets/aci_cloud_epg_selector/tasks/main.yml | 14 +- .../targets/aci_cloud_external_epg/tasks/main.yml | 16 +- .../aci_cloud_external_epg_selector/tasks/main.yml | 14 +- .../targets/aci_cloud_provider/tasks/main.yml | 14 +- .../targets/aci_cloud_region/tasks/main.yml | 18 +- .../targets/aci_cloud_subnet/tasks/main.yml | 312 +- .../targets/aci_cloud_vpn_gateway/tasks/main.yml | 28 +- .../targets/aci_cloud_zone/tasks/main.yml | 22 +- .../aci_config_export_policy/tasks/main.yml | 2 +- .../targets/aci_config_rollback/tasks/main.yml | 10 +- .../targets/aci_config_snapshot/tasks/main.yml | 20 +- .../targets/aci_contract/tasks/main.yml | 8 +- .../targets/aci_contract_export/tasks/main.yml | 14 +- .../targets/aci_contract_subject/tasks/main.yml | 16 +- .../aci_contract_subject_to_filter/tasks/main.yml | 18 +- .../tasks/main.yml | 8 +- .../integration/targets/aci_dhcp_option/aliases | 2 + .../targets/aci_dhcp_option/tasks/main.yml | 188 + .../targets/aci_dhcp_option_policy/aliases | 2 + .../targets/aci_dhcp_option_policy/tasks/main.yml | 139 + .../targets/aci_dhcp_relay/tasks/main.yml | 32 +- .../targets/aci_dhcp_relay_provider/tasks/main.yml | 30 +- .../targets/aci_dns_domain/tasks/main.yml | 18 +- .../targets/aci_dns_profile/tasks/main.yml | 16 +- .../targets/aci_dns_provider/tasks/main.yml | 18 +- .../integration/targets/aci_domain/tasks/fc.yml | 16 +- .../integration/targets/aci_domain/tasks/l2dom.yml | 16 +- .../integration/targets/aci_domain/tasks/l3dom.yml | 16 +- .../integration/targets/aci_domain/tasks/main.yml | 2 +- .../integration/targets/aci_domain/tasks/phys.yml | 16 +- .../targets/aci_domain/tasks/vmm-vmware.yml | 18 +- .../aci_domain_to_encap_pool/tasks/main.yml | 118 +- .../targets/aci_domain_to_vlan_pool/tasks/main.yml | 20 +- .../targets/aci_encap_pool/tasks/main.yml | 4 +- .../targets/aci_encap_pool/tasks/vlan.yml | 38 +- .../targets/aci_encap_pool/tasks/vxlan.yml | 24 +- .../targets/aci_encap_pool_range/tasks/main.yml | 4 +- .../targets/aci_encap_pool_range/tasks/vlan.yml | 50 +- .../integration/targets/aci_epg/tasks/main.yml | 351 +- .../aci_epg_monitoring_policy/tasks/main.yml | 2 +- .../targets/aci_epg_subnet/tasks/main.yml | 18 +- .../targets/aci_epg_to_contract/tasks/main.yml | 83 +- .../aci_epg_to_contract_interface/tasks/main.yml | 14 +- .../aci_epg_to_contract_master/tasks/main.yml | 22 +- .../targets/aci_epg_to_domain/tasks/main.yml | 82 +- .../aci_epg_useg_attribute_block_statement/aliases | 2 + .../tasks/main.yml | 251 + .../aliases | 2 + .../tasks/main.yml | 261 + .../tasks/simple_block_levels.yml | 156 + .../integration/targets/aci_esg/tasks/main.yml | 40 +- .../targets/aci_esg_contract_master/tasks/main.yml | 22 +- .../targets/aci_esg_epg_selector/tasks/main.yml | 28 +- .../aci_esg_ip_subnet_selector/tasks/main.yml | 20 +- .../targets/aci_esg_tag_selector/tasks/main.yml | 18 +- .../aci_fabric_external_connection_profile/aliases | 2 + .../tasks/main.yml | 222 + .../aci_fabric_external_routing_profile/aliases | 2 + .../tasks/main.yml | 278 + .../tasks/main.yml | 64 +- .../targets/aci_fabric_leaf_profile/tasks/main.yml | 32 +- .../aci_fabric_leaf_switch_assoc/tasks/main.yml | 50 +- .../targets/aci_fabric_management_access/aliases | 2 + .../aci_fabric_management_access/pki/admin.crt | 14 + .../aci_fabric_management_access/pki/admin.key | 16 + .../aci_fabric_management_access/tasks/main.yml | 328 ++ .../aliases | 2 + .../pki/admin.crt | 14 + .../pki/admin.key | 16 + .../tasks/main.yml | 233 + .../targets/aci_fabric_node/tasks/main.yml | 18 +- .../targets/aci_fabric_node_control/tasks/main.yml | 4 +- .../integration/targets/aci_fabric_pod/aliases | 2 + .../targets/aci_fabric_pod/tasks/main.yml | 206 + .../aci_fabric_pod_connectivity_profile/aliases | 2 + .../tasks/main.yml | 225 + .../targets/aci_fabric_pod_external_tep/aliases | 2 + .../aci_fabric_pod_external_tep/tasks/main.yml | 210 + .../aci_fabric_pod_policy_group/tasks/main.yml | 16 +- .../targets/aci_fabric_pod_profile/aliases | 2 + .../targets/aci_fabric_pod_profile/tasks/main.yml | 153 + .../targets/aci_fabric_pod_remote_pool/aliases | 2 + .../aci_fabric_pod_remote_pool/tasks/main.yml | 246 + .../targets/aci_fabric_pod_selector/tasks/main.yml | 4 +- .../targets/aci_fabric_scheduler/tasks/main.yml | 36 +- .../aci_fabric_span_dst_group/tasks/main.yml | 2 +- .../aci_fabric_span_src_group/tasks/main.yml | 4 +- .../aci_fabric_span_src_group_src/tasks/main.yml | 4 +- .../tasks/main.yml | 4 +- .../tasks/main.yml | 4 +- .../aci_fabric_spine_profile/tasks/main.yml | 32 +- .../aci_fabric_spine_switch_assoc/tasks/main.yml | 50 +- .../targets/aci_fabric_switch_block/tasks/main.yml | 60 +- .../aci_fabric_switch_policy_group/tasks/main.yml | 44 +- .../aci_fabric_wide_settings/tasks/main.yml | 6 +- .../targets/aci_file_remote_path/tasks/main.yml | 4 +- .../integration/targets/aci_filter/tasks/main.yml | 16 +- .../targets/aci_filter_entry/tasks/main.yml | 20 +- .../integration/targets/aci_filter_listify/aliases | 2 + .../targets/aci_filter_listify/tasks/main.yml | 197 + .../targets/aci_firmware_group/tasks/main.yml | 40 +- .../targets/aci_firmware_group_node/tasks/main.yml | 44 +- .../targets/aci_firmware_policy/tasks/main.yml | 36 +- .../targets/aci_firmware_source/tasks/main.yml | 42 +- .../aci_igmp_interface_policy/tasks/main.yml | 4 +- .../targets/aci_interface_blacklist/tasks/main.yml | 64 +- .../targets/aci_interface_config/tasks/main.yml | 42 +- .../aci_interface_description/tasks/main.yml | 36 +- .../targets/aci_interface_policy_bfd/aliases | 2 + .../aci_interface_policy_bfd/tasks/main.yml | 245 + .../aci_interface_policy_bfd_multihop/aliases | 2 + .../tasks/main.yml | 245 + .../aci_interface_policy_cdp/tasks/main.yml | 10 +- .../targets/aci_interface_policy_eigrp/aliases | 2 + .../aci_interface_policy_eigrp/tasks/main.yml | 192 + .../targets/aci_interface_policy_fc/tasks/main.yml | 36 +- .../targets/aci_interface_policy_hsrp/aliases | 2 + .../aci_interface_policy_hsrp/tasks/main.yml | 184 + .../targets/aci_interface_policy_l2/tasks/main.yml | 36 +- .../tasks/main.yml | 22 +- .../tasks/main.yml | 18 +- .../tasks/main.yml | 40 +- .../tasks/main.yml | 18 +- .../tasks/main.yml | 38 +- .../aci_interface_policy_link_level/tasks/main.yml | 149 +- .../aci_interface_policy_lldp/tasks/main.yml | 36 +- .../aci_interface_policy_mcp/tasks/main.yml | 64 +- .../aci_interface_policy_ospf/tasks/main.yml | 20 +- .../targets/aci_interface_policy_pim/aliases | 2 + .../aci_interface_policy_pim/tasks/main.yml | 275 + .../tasks/main.yml | 40 +- .../tasks/main.yml | 34 +- .../tasks/main.yml | 34 +- .../tasks/main.yml | 12 +- .../aci_interface_policy_storm_control/aliases | 2 + .../tasks/main.yml | 285 + .../tasks/main.yml | 12 +- .../integration/targets/aci_key_policy/aliases | 2 + .../targets/aci_key_policy/tasks/main.yml | 153 + .../targets/aci_keychain_policy/aliases | 2 + .../targets/aci_keychain_policy/tasks/main.yml | 135 + .../integration/targets/aci_l2out/tasks/main.yml | 34 +- .../targets/aci_l2out_extepg/tasks/main.yml | 40 +- .../aci_l2out_extepg_to_contract/tasks/main.yml | 50 +- .../tasks/main.yml | 14 +- .../tasks/main.yml | 18 +- .../aci_l2out_logical_node_profile/tasks/main.yml | 12 +- .../integration/targets/aci_l3out/tasks/main.yml | 223 +- .../aci_l3out_bfd_interface_profile/aliases | 2 + .../aci_l3out_bfd_interface_profile/tasks/main.yml | 226 + .../aliases | 2 + .../tasks/main.yml | 233 + .../targets/aci_l3out_bgp_peer/tasks/main.yml | 380 +- .../aci_l3out_bgp_protocol_profile/tasks/main.yml | 46 +- .../targets/aci_l3out_dhcp_relay_label/aliases | 2 + .../aci_l3out_dhcp_relay_label/tasks/main.yml | 242 + .../aci_l3out_eigrp_interface_profile/aliases | 2 + .../tasks/main.yml | 224 + .../targets/aci_l3out_extepg/tasks/main.yml | 2 +- .../aci_l3out_extepg_to_contract/tasks/main.yml | 236 +- .../targets/aci_l3out_extsubnet/tasks/main.yml | 34 +- .../targets/aci_l3out_floating_svi/aliases | 2 + .../targets/aci_l3out_floating_svi/tasks/main.yml | 220 + .../targets/aci_l3out_floating_svi_path/aliases | 2 + .../aci_l3out_floating_svi_path/tasks/main.yml | 365 ++ .../aliases | 2 + .../tasks/main.yml | 226 + .../aci_l3out_floating_svi_secondary_ip/aliases | 2 + .../tasks/main.yml | 159 + .../targets/aci_l3out_hsrp_group/aliases | 2 + .../targets/aci_l3out_hsrp_group/tasks/main.yml | 195 + .../aci_l3out_hsrp_interface_profile/aliases | 2 + .../tasks/main.yml | 152 + .../targets/aci_l3out_hsrp_secondary_vip/aliases | 2 + .../aci_l3out_hsrp_secondary_vip/tasks/main.yml | 173 + .../targets/aci_l3out_interface/tasks/main.yml | 362 +- .../tasks/main.yml | 86 +- .../tasks/main.yml | 346 +- .../tasks/main.yml | 18 +- .../tasks/main.yml | 26 +- .../targets/aci_l3out_logical_node/tasks/main.yml | 161 +- .../aci_l3out_logical_node_profile/tasks/main.yml | 89 +- .../aci_l3out_route_tag_policy/tasks/main.yml | 12 +- .../targets/aci_l3out_static_routes/tasks/main.yml | 56 +- .../aci_l3out_static_routes_nexthop/tasks/main.yml | 14 +- .../aci_l3out_to_sr_mpls_infra_l3out/aliases | 2 + .../tasks/main.yml | 238 + .../aci_lookup_interface_range/tasks/main.yml | 18 +- .../targets/aci_maintenance_group/tasks/main.yml | 44 +- .../aci_maintenance_group_node/tasks/main.yml | 48 +- .../targets/aci_maintenance_policy/tasks/main.yml | 40 +- .../aci_match_as_path_regex_term/tasks/main.yml | 38 +- .../aci_match_community_factor/tasks/main.yml | 40 +- .../aci_match_community_regex_term/tasks/main.yml | 38 +- .../aci_match_community_term/tasks/main.yml | 38 +- .../aci_match_route_destination/tasks/main.yml | 38 +- .../targets/aci_match_rule/tasks/main.yml | 36 +- .../targets/aci_netflow_exporter_policy/aliases | 2 + .../aci_netflow_exporter_policy/tasks/main.yml | 337 ++ .../targets/aci_netflow_monitor_policy/aliases | 2 + .../aci_netflow_monitor_policy/tasks/main.yml | 193 + .../aci_netflow_monitor_to_exporter/aliases | 2 + .../aci_netflow_monitor_to_exporter/tasks/main.yml | 172 + .../targets/aci_netflow_record_policy/aliases | 2 + .../aci_netflow_record_policy/tasks/main.yml | 194 + .../integration/targets/aci_node_block/aliases | 2 + .../targets/aci_node_block/tasks/main.yml | 275 + .../targets/aci_node_mgmt_epg/tasks/main.yml | 50 +- .../targets/aci_ntp_policy/tasks/main.yml | 14 +- .../targets/aci_ntp_server/tasks/main.yml | 14 +- .../targets/aci_pim_route_map_entry/aliases | 2 + .../targets/aci_pim_route_map_entry/tasks/main.yml | 196 + .../targets/aci_pim_route_map_policy/aliases | 2 + .../aci_pim_route_map_policy/tasks/main.yml | 135 + .../targets/aci_qos_custom_policy/aliases | 2 + .../targets/aci_qos_custom_policy/tasks/main.yml | 139 + .../targets/aci_qos_dot1p_class/aliases | 2 + .../targets/aci_qos_dot1p_class/tasks/main.yml | 167 + .../integration/targets/aci_qos_dscp_class/aliases | 2 + .../targets/aci_qos_dscp_class/tasks/main.yml | 167 + .../targets/aci_rest/tasks/error_handling.yml | 16 +- .../targets/aci_rest/tasks/json_inline.yml | 175 +- .../targets/aci_rest/tasks/json_string.yml | 175 +- .../integration/targets/aci_rest/tasks/main.yml | 2 +- .../targets/aci_rest/tasks/xml_file.yml | 125 +- .../targets/aci_rest/tasks/xml_files/tag.xml | 1 + .../tasks/xml_files/tn-ans_test_annotation.xml | 1 + .../xml_files/tn-ans_test_annotation_children.xml | 6 + .../targets/aci_rest/tasks/xml_string.yml | 137 +- .../targets/aci_rest/tasks/yaml_inline.yml | 141 +- .../targets/aci_rest/tasks/yaml_string.yml | 141 +- .../aci_route_control_context/tasks/main.yml | 46 +- .../aci_route_control_profile/tasks/main.yml | 38 +- .../targets/aci_snmp_client/tasks/main.yml | 38 +- .../targets/aci_snmp_client_group/tasks/main.yml | 40 +- .../aci_snmp_community_policy/tasks/main.yml | 34 +- .../targets/aci_snmp_policy/tasks/main.yml | 30 +- .../aci_static_binding_to_epg/tasks/main.yml | 16 +- .../aci_static_node_mgmt_address/tasks/main.yml | 60 +- .../integration/targets/aci_subject_label/aliases | 2 + .../targets/aci_subject_label/tasks/main.yml | 253 + .../aci_subject_label/tasks/subject_label.yml | 188 + .../aci_switch_leaf_selector/tasks/main.yml | 10 +- .../aci_switch_policy_leaf_profile/tasks/main.yml | 18 +- .../tasks/main.yml | 16 +- .../targets/aci_syslog_group/tasks/main.yml | 30 +- .../targets/aci_syslog_remote_dest/tasks/main.yml | 40 +- .../targets/aci_syslog_source/tasks/main.yml | 40 +- .../integration/targets/aci_system/tasks/main.yml | 16 +- .../targets/aci_system_banner/tasks/main.yml | 4 +- .../aci_system_endpoint_controls/tasks/main.yml | 6 +- .../tasks/main.yml | 6 +- .../targets/aci_taboo_contract/tasks/main.yml | 22 +- .../integration/targets/aci_tag/tasks/main.yml | 50 +- .../aci_tenant/tasks/httpapi_connection.yml | 38 +- .../integration/targets/aci_tenant/tasks/main.yml | 106 +- .../aci_tenant_action_rule_profile/tasks/main.yml | 220 +- .../aci_tenant_ep_retention_policy/tasks/main.yml | 50 +- .../aci_tenant_span_dst_group/tasks/main.yml | 42 +- .../aci_tenant_span_src_group/tasks/main.yml | 6 +- .../aci_tenant_span_src_group_src/tasks/main.yml | 6 +- .../tasks/main.yml | 6 +- .../targets/aci_vlan_pool/tasks/dynamic.yml | 24 +- .../targets/aci_vlan_pool/tasks/main.yml | 4 +- .../targets/aci_vlan_pool/tasks/static.yml | 24 +- .../aci_vlan_pool_encap_block/tasks/main.yml | 50 +- .../targets/aci_vmm_controller/tasks/main.yml | 94 +- .../targets/aci_vmm_credential/tasks/main.yml | 2 +- .../targets/aci_vmm_credential/tasks/vmware.yml | 16 +- .../targets/aci_vmm_uplink/tasks/main.yml | 28 +- .../aci_vmm_uplink_container/tasks/main.yml | 38 +- .../targets/aci_vmm_vswitch_policy/tasks/main.yml | 42 +- .../integration/targets/aci_vrf/tasks/main.yml | 8 +- .../aci_vrf_leak_internal_subnet/tasks/main.yml | 12 +- .../integration/targets/aci_vrf_multicast/aliases | 2 + .../targets/aci_vrf_multicast/tasks/main.yml | 1133 ++++ .../targets/aci_vzany_to_contract/tasks/main.yml | 12 +- .../cisco/aci/tests/unit/compat/builtins.py | 13 - .../cisco/aci/tests/unit/mock/loader.py | 2 +- .../cisco/aci/tests/unit/module_utils/test_aci.py | 2 - .../cisco/dnac/.github/workflows/docs.yml | 8 +- .../cisco/dnac/.github/workflows/sanity_tests.yml | 20 +- .../dnac/.github/workflows/sanity_tests_devel.yml | 32 + ansible_collections/cisco/dnac/FILES.json | 831 +-- ansible_collections/cisco/dnac/MANIFEST.json | 6 +- ansible_collections/cisco/dnac/README.md | 16 +- .../cisco/dnac/changelogs/changelog.yaml | 17 + ansible_collections/cisco/dnac/meta/runtime.yml | 2 +- ansible_collections/cisco/dnac/playbooks/PnP.yml | 4 +- .../playbooks/PnP_Workflow_Manager_Playbook.yml | 2 +- .../cisco/dnac/playbooks/device_details.template | 20 +- .../dnac/playbooks/device_provision_workflow.yml | 10 +- .../dnac/playbooks/template_workflow_manager.yml | 16 +- .../cisco/dnac/plugins/module_utils/dnac.py | 61 + ...spoint_configuration_details_by_task_id_info.py | 4 +- .../plugins/modules/app_policy_default_info.py | 4 +- .../cisco/dnac/plugins/modules/app_policy_info.py | 4 +- .../plugins/modules/app_policy_intent_create.py | 4 +- .../plugins/modules/app_policy_queuing_profile.py | 4 +- .../app_policy_queuing_profile_count_info.py | 4 +- .../modules/app_policy_queuing_profile_info.py | 4 +- .../cisco/dnac/plugins/modules/application_sets.py | 4 +- .../plugins/modules/application_sets_count_info.py | 4 +- .../dnac/plugins/modules/application_sets_info.py | 4 +- .../cisco/dnac/plugins/modules/applications.py | 4 +- .../plugins/modules/applications_count_info.py | 4 +- .../plugins/modules/applications_health_info.py | 4 +- .../dnac/plugins/modules/applications_info.py | 4 +- .../dnac/plugins/modules/assign_device_to_site.py | 4 +- .../modules/associate_site_to_network_profile.py | 4 +- .../modules/authentication_import_certificate.py | 4 +- .../authentication_import_certificate_p12.py | 4 +- .../modules/authentication_policy_servers_info.py | 4 +- .../buildings_planned_access_points_info.py | 4 +- .../business_sda_hostonboarding_ssid_ippool.py | 4 +- ...business_sda_hostonboarding_ssid_ippool_info.py | 4 +- .../business_sda_virtual_network_summary_info.py | 4 +- .../business_sda_wireless_controller_create.py | 4 +- .../business_sda_wireless_controller_delete.py | 4 +- .../cisco/dnac/plugins/modules/cli_credential.py | 4 +- .../dnac/plugins/modules/client_detail_info.py | 4 +- .../modules/client_enrichment_details_info.py | 4 +- .../dnac/plugins/modules/client_health_info.py | 4 +- .../dnac/plugins/modules/client_proximity_info.py | 4 +- .../plugins/modules/command_runner_run_command.py | 4 +- .../dnac/plugins/modules/compliance_check_run.py | 4 +- .../modules/compliance_device_by_id_info.py | 4 +- .../compliance_device_details_count_info.py | 4 +- .../modules/compliance_device_details_info.py | 4 +- .../dnac/plugins/modules/compliance_device_info.py | 4 +- .../modules/compliance_device_status_count_info.py | 4 +- .../dnac/plugins/modules/configuration_template.py | 4 +- .../modules/configuration_template_clone.py | 4 +- .../modules/configuration_template_create.py | 4 +- .../modules/configuration_template_deploy.py | 4 +- .../configuration_template_deploy_status_info.py | 4 +- .../modules/configuration_template_deploy_v2.py | 4 +- .../configuration_template_export_project.py | 4 +- .../configuration_template_export_template.py | 4 +- .../configuration_template_import_project.py | 4 +- .../configuration_template_import_template.py | 4 +- .../plugins/modules/configuration_template_info.py | 4 +- .../modules/configuration_template_project.py | 4 +- .../modules/configuration_template_project_info.py | 4 +- .../configuration_template_version_create.py | 4 +- .../modules/configuration_template_version_info.py | 4 +- .../credential_to_site_by_siteid_create_v2.py | 4 +- .../modules/device_configurations_export.py | 4 +- .../plugins/modules/device_credential_create.py | 4 +- .../plugins/modules/device_credential_delete.py | 4 +- .../dnac/plugins/modules/device_credential_info.py | 4 +- .../plugins/modules/device_credential_intent.py | 17 +- .../plugins/modules/device_credential_update.py | 4 +- .../modules/device_credential_workflow_manager.py | 17 +- .../dnac/plugins/modules/device_details_info.py | 4 +- .../modules/device_enrichment_details_info.py | 4 +- .../device_family_identifiers_details_info.py | 4 +- .../dnac/plugins/modules/device_health_info.py | 4 +- .../plugins/modules/device_interface_by_ip_info.py | 4 +- .../plugins/modules/device_interface_count_info.py | 4 +- .../dnac/plugins/modules/device_interface_info.py | 4 +- .../plugins/modules/device_interface_isis_info.py | 4 +- .../plugins/modules/device_interface_ospf_info.py | 4 +- .../dnac/plugins/modules/device_reboot_apreboot.py | 4 +- .../plugins/modules/device_reboot_apreboot_info.py | 4 +- .../dnac/plugins/modules/device_replacement.py | 4 +- .../modules/device_replacement_count_info.py | 4 +- .../plugins/modules/device_replacement_deploy.py | 4 +- .../plugins/modules/device_replacement_info.py | 4 +- .../disassociate_site_to_network_profile.py | 4 +- ...disasterrecovery_system_operationstatus_info.py | 4 +- .../modules/disasterrecovery_system_status_info.py | 4 +- .../cisco/dnac/plugins/modules/discovery.py | 4 +- .../dnac/plugins/modules/discovery_count_info.py | 4 +- .../plugins/modules/discovery_device_count_info.py | 4 +- .../dnac/plugins/modules/discovery_device_info.py | 4 +- .../plugins/modules/discovery_device_range_info.py | 4 +- .../cisco/dnac/plugins/modules/discovery_info.py | 4 +- .../cisco/dnac/plugins/modules/discovery_intent.py | 156 +- .../dnac/plugins/modules/discovery_job_info.py | 4 +- .../dnac/plugins/modules/discovery_range_delete.py | 4 +- .../dnac/plugins/modules/discovery_range_info.py | 4 +- .../dnac/plugins/modules/discovery_summary_info.py | 4 +- .../plugins/modules/discovery_workflow_manager.py | 156 +- .../modules/dna_command_runner_keywords_info.py | 4 +- .../dnac/plugins/modules/dnac_packages_info.py | 4 +- .../dnacaap_management_execution_status_info.py | 4 +- .../modules/endpoint_analytics_profiling_rules.py | 4 +- .../endpoint_analytics_profiling_rules_info.py | 4 +- .../dnac/plugins/modules/eox_status_device_info.py | 4 +- .../plugins/modules/eox_status_summary_info.py | 4 +- .../dnac/plugins/modules/event_api_status_info.py | 4 +- .../plugins/modules/event_artifact_count_info.py | 4 +- .../dnac/plugins/modules/event_artifact_info.py | 4 +- .../modules/event_config_connector_types_info.py | 4 +- .../cisco/dnac/plugins/modules/event_count_info.py | 4 +- .../dnac/plugins/modules/event_email_config.py | 4 +- .../plugins/modules/event_email_config_create.py | 4 +- .../plugins/modules/event_email_config_info.py | 4 +- .../plugins/modules/event_email_config_update.py | 4 +- .../cisco/dnac/plugins/modules/event_info.py | 4 +- .../modules/event_series_audit_logs_info.py | 4 +- .../event_series_audit_logs_parent_records_info.py | 4 +- .../event_series_audit_logs_summary_info.py | 4 +- .../plugins/modules/event_series_count_info.py | 4 +- .../dnac/plugins/modules/event_series_info.py | 4 +- .../dnac/plugins/modules/event_snmp_config_info.py | 4 +- .../dnac/plugins/modules/event_subscription.py | 4 +- .../modules/event_subscription_count_info.py | 4 +- .../event_subscription_details_email_info.py | 4 +- .../event_subscription_details_rest_info.py | 4 +- .../event_subscription_details_syslog_info.py | 4 +- .../plugins/modules/event_subscription_email.py | 4 +- .../modules/event_subscription_email_info.py | 4 +- .../plugins/modules/event_subscription_info.py | 4 +- .../plugins/modules/event_subscription_rest.py | 4 +- .../modules/event_subscription_rest_info.py | 4 +- .../plugins/modules/event_subscription_syslog.py | 4 +- .../modules/event_subscription_syslog_info.py | 4 +- .../dnac/plugins/modules/event_syslog_config.py | 4 +- .../plugins/modules/event_syslog_config_info.py | 4 +- .../dnac/plugins/modules/event_webhook_create.py | 4 +- .../dnac/plugins/modules/event_webhook_update.py | 4 +- .../modules/execute_suggested_actions_commands.py | 4 +- .../cisco/dnac/plugins/modules/file_import.py | 4 +- .../cisco/dnac/plugins/modules/file_info.py | 4 +- .../plugins/modules/file_namespace_files_info.py | 4 +- .../dnac/plugins/modules/file_namespaces_info.py | 4 +- .../plugins/modules/global_credential_delete.py | 4 +- .../dnac/plugins/modules/global_credential_info.py | 4 +- .../plugins/modules/global_credential_update.py | 4 +- .../dnac/plugins/modules/global_credential_v2.py | 4 +- .../plugins/modules/global_credential_v2_info.py | 4 +- .../cisco/dnac/plugins/modules/global_pool.py | 4 +- .../cisco/dnac/plugins/modules/global_pool_info.py | 4 +- .../dnac/plugins/modules/golden_image_create.py | 4 +- .../plugins/modules/golden_tag_image_delete.py | 4 +- .../modules/golden_tag_image_details_info.py | 4 +- .../dnac/plugins/modules/http_read_credential.py | 4 +- .../dnac/plugins/modules/http_write_credential.py | 4 +- .../modules/integration_settings_instances_itsm.py | 4 +- .../integration_settings_instances_itsm_info.py | 4 +- .../cisco/dnac/plugins/modules/interface_info.py | 4 +- .../interface_network_device_detail_info.py | 4 +- .../modules/interface_network_device_info.py | 4 +- .../modules/interface_network_device_range_info.py | 4 +- .../plugins/modules/interface_operation_create.py | 4 +- .../cisco/dnac/plugins/modules/interface_update.py | 4 +- .../cisco/dnac/plugins/modules/inventory_intent.py | 167 +- .../plugins/modules/inventory_workflow_manager.py | 172 +- .../modules/issues_enrichment_details_info.py | 4 +- .../cisco/dnac/plugins/modules/issues_info.py | 4 +- .../plugins/modules/itsm_cmdb_sync_status_info.py | 4 +- .../modules/itsm_integration_events_failed_info.py | 4 +- .../modules/itsm_integration_events_retry.py | 4 +- .../plugins/modules/lan_automation_count_info.py | 4 +- .../dnac/plugins/modules/lan_automation_create.py | 4 +- .../dnac/plugins/modules/lan_automation_delete.py | 4 +- .../lan_automation_log_by_serial_number_info.py | 4 +- .../plugins/modules/lan_automation_log_info.py | 4 +- .../plugins/modules/lan_automation_status_info.py | 4 +- .../plugins/modules/license_device_count_info.py | 4 +- .../modules/license_device_deregistration.py | 4 +- .../modules/license_device_license_details_info.py | 4 +- .../modules/license_device_license_summary_info.py | 4 +- .../plugins/modules/license_device_registration.py | 4 +- .../modules/license_smart_account_details_info.py | 4 +- .../plugins/modules/license_term_details_info.py | 4 +- .../plugins/modules/license_usage_details_info.py | 4 +- .../modules/license_virtual_account_change.py | 4 +- .../license_virtual_account_details_info.py | 4 +- .../dnac/plugins/modules/netconf_credential.py | 4 +- .../cisco/dnac/plugins/modules/network_create.py | 4 +- .../cisco/dnac/plugins/modules/network_device.py | 4 +- .../plugins/modules/network_device_by_ip_info.py | 4 +- .../network_device_by_serial_number_info.py | 4 +- .../modules/network_device_chassis_details_info.py | 4 +- .../modules/network_device_config_count_info.py | 4 +- .../plugins/modules/network_device_config_info.py | 4 +- .../plugins/modules/network_device_count_info.py | 4 +- .../modules/network_device_custom_prompt.py | 4 +- .../modules/network_device_custom_prompt_info.py | 4 +- .../modules/network_device_equipment_info.py | 4 +- .../dnac/plugins/modules/network_device_export.py | 4 +- .../network_device_functional_capability_info.py | 4 +- .../network_device_global_polling_interval_info.py | 4 +- .../dnac/plugins/modules/network_device_info.py | 4 +- .../network_device_interface_neighbor_info.py | 4 +- .../modules/network_device_interface_poe_info.py | 4 +- ..._device_inventory_insight_link_mismatch_info.py | 4 +- ...network_device_lexicographically_sorted_info.py | 4 +- .../network_device_linecard_details_info.py | 4 +- .../network_device_meraki_organization_info.py | 4 +- .../modules/network_device_module_count_info.py | 4 +- .../plugins/modules/network_device_module_info.py | 4 +- .../plugins/modules/network_device_poe_info.py | 4 +- .../network_device_polling_interval_info.py | 4 +- .../plugins/modules/network_device_range_info.py | 4 +- .../network_device_register_for_wsa_info.py | 4 +- .../modules/network_device_stack_details_info.py | 4 +- .../plugins/modules/network_device_summary_info.py | 4 +- .../network_device_supervisor_card_details_info.py | 4 +- .../dnac/plugins/modules/network_device_sync.py | 4 +- .../plugins/modules/network_device_update_role.py | 4 +- .../modules/network_device_user_defined_field.py | 4 +- .../network_device_user_defined_field_info.py | 4 +- .../plugins/modules/network_device_vlan_info.py | 4 +- .../modules/network_device_wireless_lan_info.py | 4 +- .../network_device_with_snmp_v3_des_info.py | 4 +- .../cisco/dnac/plugins/modules/network_info.py | 4 +- .../plugins/modules/network_settings_intent.py | 12 +- .../modules/network_settings_workflow_manager.py | 12 +- .../cisco/dnac/plugins/modules/network_update.py | 4 +- .../cisco/dnac/plugins/modules/network_v2.py | 4 +- .../cisco/dnac/plugins/modules/network_v2_info.py | 4 +- .../cisco/dnac/plugins/modules/nfv_profile.py | 4 +- .../cisco/dnac/plugins/modules/nfv_profile_info.py | 4 +- .../cisco/dnac/plugins/modules/nfv_provision.py | 4 +- .../plugins/modules/nfv_provision_detail_info.py | 4 +- .../dnac/plugins/modules/nfv_provision_details.py | 4 +- .../cisco/dnac/plugins/modules/path_trace.py | 4 +- .../cisco/dnac/plugins/modules/path_trace_info.py | 4 +- .../plugins/modules/planned_access_points_info.py | 4 +- .../platform_nodes_configuration_summary_info.py | 4 +- .../modules/platform_release_summary_info.py | 4 +- .../cisco/dnac/plugins/modules/pnp_device.py | 4 +- .../dnac/plugins/modules/pnp_device_authorize.py | 4 +- .../cisco/dnac/plugins/modules/pnp_device_claim.py | 4 +- .../plugins/modules/pnp_device_claim_to_site.py | 4 +- .../plugins/modules/pnp_device_config_preview.py | 4 +- .../dnac/plugins/modules/pnp_device_count_info.py | 4 +- .../plugins/modules/pnp_device_history_info.py | 4 +- .../dnac/plugins/modules/pnp_device_import.py | 4 +- .../cisco/dnac/plugins/modules/pnp_device_info.py | 4 +- .../cisco/dnac/plugins/modules/pnp_device_reset.py | 4 +- .../dnac/plugins/modules/pnp_device_unclaim.py | 4 +- .../dnac/plugins/modules/pnp_global_settings.py | 4 +- .../plugins/modules/pnp_global_settings_info.py | 4 +- .../cisco/dnac/plugins/modules/pnp_intent.py | 29 +- .../plugins/modules/pnp_server_profile_update.py | 4 +- .../modules/pnp_smart_account_domains_info.py | 4 +- .../plugins/modules/pnp_virtual_account_add.py | 4 +- .../modules/pnp_virtual_account_deregister.py | 4 +- .../modules/pnp_virtual_account_devices_sync.py | 4 +- .../pnp_virtual_account_sync_result_info.py | 4 +- .../plugins/modules/pnp_virtual_accounts_info.py | 4 +- .../cisco/dnac/plugins/modules/pnp_workflow.py | 4 +- .../plugins/modules/pnp_workflow_count_info.py | 4 +- .../dnac/plugins/modules/pnp_workflow_info.py | 4 +- .../dnac/plugins/modules/pnp_workflow_manager.py | 29 +- .../plugins/modules/profiling_rules_count_info.py | 4 +- .../modules/profiling_rules_in_bulk_create.py | 4 +- .../dnac/plugins/modules/projects_details_info.py | 4 +- .../cisco/dnac/plugins/modules/provision_intent.py | 10 +- .../plugins/modules/provision_workflow_manager.py | 29 +- .../dnac/plugins/modules/qos_device_interface.py | 4 +- .../plugins/modules/qos_device_interface_info.py | 4 +- .../qos_device_interface_info_count_info.py | 4 +- .../cisco/dnac/plugins/modules/reports.py | 4 +- .../plugins/modules/reports_executions_info.py | 4 +- .../cisco/dnac/plugins/modules/reports_info.py | 4 +- .../plugins/modules/reports_view_group_info.py | 4 +- .../modules/reports_view_group_view_info.py | 4 +- .../dnac/plugins/modules/reserve_ip_subpool.py | 4 +- .../plugins/modules/reserve_ip_subpool_create.py | 4 +- .../plugins/modules/reserve_ip_subpool_delete.py | 4 +- .../plugins/modules/reserve_ip_subpool_info.py | 4 +- .../plugins/modules/reserve_ip_subpool_update.py | 4 +- .../dnac/plugins/modules/role_permissions_info.py | 4 +- .../cisco/dnac/plugins/modules/roles_info.py | 4 +- .../cisco/dnac/plugins/modules/sda_count_info.py | 4 +- .../cisco/dnac/plugins/modules/sda_device_info.py | 4 +- .../dnac/plugins/modules/sda_device_role_info.py | 4 +- .../cisco/dnac/plugins/modules/sda_fabric.py | 4 +- .../modules/sda_fabric_authentication_profile.py | 4 +- .../sda_fabric_authentication_profile_info.py | 4 +- .../plugins/modules/sda_fabric_border_device.py | 4 +- .../modules/sda_fabric_border_device_info.py | 4 +- .../modules/sda_fabric_control_plane_device.py | 4 +- .../sda_fabric_control_plane_device_info.py | 4 +- .../dnac/plugins/modules/sda_fabric_edge_device.py | 4 +- .../plugins/modules/sda_fabric_edge_device_info.py | 4 +- .../cisco/dnac/plugins/modules/sda_fabric_info.py | 4 +- .../cisco/dnac/plugins/modules/sda_fabric_site.py | 4 +- .../dnac/plugins/modules/sda_fabric_site_info.py | 4 +- .../cisco/dnac/plugins/modules/sda_multicast.py | 4 +- .../dnac/plugins/modules/sda_multicast_info.py | 4 +- .../sda_port_assignment_for_access_point.py | 4 +- .../sda_port_assignment_for_access_point_info.py | 4 +- .../modules/sda_port_assignment_for_user_device.py | 4 +- .../sda_port_assignment_for_user_device_info.py | 4 +- .../dnac/plugins/modules/sda_provision_device.py | 4 +- .../plugins/modules/sda_provision_device_info.py | 4 +- .../dnac/plugins/modules/sda_virtual_network.py | 4 +- .../plugins/modules/sda_virtual_network_info.py | 4 +- .../plugins/modules/sda_virtual_network_ip_pool.py | 4 +- .../modules/sda_virtual_network_ip_pool_info.py | 4 +- .../dnac/plugins/modules/sda_virtual_network_v2.py | 4 +- .../plugins/modules/sda_virtual_network_v2_info.py | 4 +- .../modules/security_advisories_devices_info.py | 4 +- .../security_advisories_ids_per_device_info.py | 4 +- .../plugins/modules/security_advisories_info.py | 4 +- .../modules/security_advisories_per_device_info.py | 4 +- .../modules/security_advisories_summary_info.py | 4 +- .../cisco/dnac/plugins/modules/sensor.py | 4 +- .../cisco/dnac/plugins/modules/sensor_info.py | 4 +- .../cisco/dnac/plugins/modules/sensor_test_run.py | 4 +- .../modules/sensor_test_template_duplicate.py | 4 +- .../plugins/modules/sensor_test_template_edit.py | 4 +- .../plugins/modules/service_provider_create.py | 4 +- .../dnac/plugins/modules/service_provider_info.py | 4 +- .../modules/service_provider_profile_delete.py | 4 +- .../plugins/modules/service_provider_update.py | 4 +- .../dnac/plugins/modules/service_provider_v2.py | 4 +- .../plugins/modules/service_provider_v2_info.py | 4 +- .../dnac/plugins/modules/site_assign_credential.py | 4 +- .../dnac/plugins/modules/site_assign_device.py | 4 +- .../cisco/dnac/plugins/modules/site_count_info.py | 4 +- .../cisco/dnac/plugins/modules/site_create.py | 4 +- .../cisco/dnac/plugins/modules/site_delete.py | 4 +- .../dnac/plugins/modules/site_design_floormap.py | 4 +- .../plugins/modules/site_design_floormap_info.py | 4 +- .../cisco/dnac/plugins/modules/site_health_info.py | 4 +- .../cisco/dnac/plugins/modules/site_info.py | 4 +- .../cisco/dnac/plugins/modules/site_intent.py | 23 +- .../dnac/plugins/modules/site_membership_info.py | 4 +- .../cisco/dnac/plugins/modules/site_update.py | 4 +- .../dnac/plugins/modules/site_workflow_manager.py | 23 +- .../cisco/dnac/plugins/modules/snmp_properties.py | 4 +- .../dnac/plugins/modules/snmp_properties_info.py | 4 +- .../modules/snmpv2_read_community_credential.py | 4 +- .../modules/snmpv2_write_community_credential.py | 4 +- .../dnac/plugins/modules/snmpv3_credential.py | 4 +- .../dnac/plugins/modules/sp_profile_delete_v2.py | 4 +- .../plugins/modules/swim_image_details_info.py | 4 +- .../dnac/plugins/modules/swim_import_local.py | 4 +- .../dnac/plugins/modules/swim_import_via_url.py | 4 +- .../cisco/dnac/plugins/modules/swim_intent.py | 26 +- .../plugins/modules/swim_trigger_activation.py | 4 +- .../plugins/modules/swim_trigger_distribution.py | 4 +- .../dnac/plugins/modules/swim_workflow_manager.py | 26 +- .../dnac/plugins/modules/syslog_config_create.py | 4 +- .../dnac/plugins/modules/syslog_config_update.py | 4 +- .../plugins/modules/system_health_count_info.py | 4 +- .../dnac/plugins/modules/system_health_info.py | 4 +- .../modules/system_performance_historical_info.py | 4 +- .../plugins/modules/system_performance_info.py | 4 +- .../cisco/dnac/plugins/modules/tag.py | 4 +- .../cisco/dnac/plugins/modules/tag_count_info.py | 4 +- .../cisco/dnac/plugins/modules/tag_info.py | 4 +- .../cisco/dnac/plugins/modules/tag_member.py | 4 +- .../dnac/plugins/modules/tag_member_count_info.py | 4 +- .../cisco/dnac/plugins/modules/tag_member_info.py | 4 +- .../dnac/plugins/modules/tag_member_type_info.py | 4 +- .../cisco/dnac/plugins/modules/tag_membership.py | 4 +- .../cisco/dnac/plugins/modules/task_count_info.py | 4 +- .../cisco/dnac/plugins/modules/task_info.py | 4 +- .../dnac/plugins/modules/task_operation_info.py | 4 +- .../cisco/dnac/plugins/modules/task_tree_info.py | 4 +- .../cisco/dnac/plugins/modules/template_intent.py | 12 +- .../cisco/dnac/plugins/modules/template_preview.py | 4 +- .../plugins/modules/template_workflow_manager.py | 864 +-- .../dnac/plugins/modules/templates_details_info.py | 4 +- .../cisco/dnac/plugins/modules/threat_detail.py | 4 +- .../dnac/plugins/modules/threat_detail_count.py | 4 +- .../cisco/dnac/plugins/modules/threat_summary.py | 4 +- .../dnac/plugins/modules/topology_layer_2_info.py | 4 +- .../dnac/plugins/modules/topology_layer_3_info.py | 4 +- .../modules/topology_network_health_info.py | 4 +- .../dnac/plugins/modules/topology_physical_info.py | 4 +- .../dnac/plugins/modules/topology_site_info.py | 4 +- .../plugins/modules/topology_vlan_details_info.py | 4 +- .../dnac/plugins/modules/transit_peer_network.py | 4 +- .../plugins/modules/transit_peer_network_info.py | 4 +- .../cisco/dnac/plugins/modules/user.py | 4 +- .../modules/user_enrichment_details_info.py | 4 +- .../cisco/dnac/plugins/modules/user_info.py | 4 +- .../plugins/modules/users_external_servers_info.py | 4 +- .../modules/wireless_accespoint_configuration.py | 4 +- ...eless_accesspoint_configuration_summary_info.py | 4 +- .../plugins/modules/wireless_dynamic_interface.py | 4 +- .../modules/wireless_dynamic_interface_info.py | 4 +- .../plugins/modules/wireless_enterprise_ssid.py | 4 +- .../modules/wireless_enterprise_ssid_info.py | 4 +- .../cisco/dnac/plugins/modules/wireless_profile.py | 4 +- .../dnac/plugins/modules/wireless_profile_info.py | 4 +- .../modules/wireless_provision_access_point.py | 4 +- .../modules/wireless_provision_device_create.py | 4 +- .../modules/wireless_provision_device_update.py | 4 +- .../wireless_provision_ssid_create_provision.py | 4 +- .../wireless_provision_ssid_delete_reprovision.py | 4 +- .../dnac/plugins/modules/wireless_psk_override.py | 4 +- .../dnac/plugins/modules/wireless_rf_profile.py | 4 +- .../plugins/modules/wireless_rf_profile_info.py | 4 +- .../modules/wireless_sensor_test_results_info.py | 4 +- ansible_collections/cisco/intersight/CHANGELOG.md | 3 + ansible_collections/cisco/intersight/FILES.json | 6 +- ansible_collections/cisco/intersight/MANIFEST.json | 4 +- .../modules/intersight_local_user_policy.py | 54 +- .../plugins/modules/intersight_server_profile.py | 8 +- ansible_collections/cisco/ise/.DS_Store | Bin 10244 -> 0 bytes ansible_collections/cisco/ise/.vscode/launch.json | 16 - .../cisco/ise/.vscode/settings.json | 24 - ansible_collections/cisco/ise/FILES.json | 44 +- ansible_collections/cisco/ise/MANIFEST.json | 6 +- ansible_collections/cisco/ise/Pipfile | 13 + .../cisco/ise/changelogs/changelog.yaml | 8 +- ansible_collections/cisco/ise/plugins/.DS_Store | Bin 8196 -> 0 bytes .../cisco/meraki/.vscode/settings.json | 3 - ansible_collections/cisco/meraki/FILES.json | 1766 ++++-- ansible_collections/cisco/meraki/MANIFEST.json | 6 +- ansible_collections/cisco/meraki/README.md | 132 +- .../cisco/meraki/changelogs/changelog.yaml | 62 +- ...red_licensing_subscription_entitlements_info.py | 90 + ...ed_licensing_subscription_subscriptions_bind.py | 91 + ...d_licensing_subscription_subscriptions_claim.py | 95 + ...ubscription_subscriptions_claim_key_validate.py | 87 + ...ption_subscriptions_compliance_statuses_info.py | 94 + ...ed_licensing_subscription_subscriptions_info.py | 128 + .../cisco/meraki/plugins/action/devices.py | 65 +- .../action/devices_appliance_radio_settings.py | 211 + .../devices_appliance_radio_settings_info.py | 90 + .../meraki/plugins/action/devices_blink_leds.py | 4 +- .../action/devices_camera_custom_analytics.py | 10 +- .../action/devices_camera_generate_snapshot.py | 4 +- .../action/devices_camera_quality_and_retention.py | 42 +- .../meraki/plugins/action/devices_camera_sense.py | 22 +- .../action/devices_camera_wireless_profiles.py | 4 +- .../plugins/action/devices_cellular_gateway_lan.py | 12 +- ...vices_cellular_gateway_port_forwarding_rules.py | 4 +- .../meraki/plugins/action/devices_cellular_sims.py | 16 +- .../plugins/action/devices_live_tools_arp_table.py | 174 + .../action/devices_live_tools_arp_table_info.py | 79 + .../action/devices_live_tools_cable_test.py | 180 + .../action/devices_live_tools_cable_test_info.py | 79 + .../plugins/action/devices_live_tools_ping.py | 18 +- .../action/devices_live_tools_ping_device.py | 6 + .../action/devices_live_tools_throughput_test.py | 174 + .../devices_live_tools_throughput_test_info.py | 79 + .../action/devices_live_tools_wake_on_lan.py | 186 + .../action/devices_live_tools_wake_on_lan_info.py | 79 + .../plugins/action/devices_sensor_relationships.py | 4 +- .../meraki/plugins/action/devices_switch_ports.py | 213 +- .../action/devices_switch_routing_interfaces.py | 90 +- .../devices_switch_routing_interfaces_dhcp.py | 82 +- .../action/devices_switch_routing_static_routes.py | 32 +- ...wireless_alternate_management_interface_ipv6.py | 89 + .../action/devices_wireless_bluetooth_settings.py | 12 +- .../action/devices_wireless_radio_settings.py | 12 +- .../cisco/meraki/plugins/action/networks.py | 45 +- .../plugins/action/networks_alerts_settings.py | 18 +- .../action/networks_appliance_content_filtering.py | 12 +- .../plugins/action/networks_appliance_ports.py | 34 +- ...etworks_appliance_prefixes_delegated_statics.py | 36 +- .../action/networks_appliance_rf_profiles.py | 252 + .../action/networks_appliance_rf_profiles_info.py | 90 + .../networks_appliance_security_intrusion.py | 12 +- .../action/networks_appliance_security_malware.py | 24 +- .../action/networks_appliance_single_lan.py | 12 +- .../plugins/action/networks_appliance_ssids.py | 74 +- ...e_traffic_shaping_custom_performance_classes.py | 8 +- ...s_appliance_traffic_shaping_uplink_selection.py | 22 +- ...rks_appliance_traffic_shaping_vpn_exclusions.py | 91 + .../plugins/action/networks_appliance_vlans.py | 209 +- .../plugins/action/networks_appliance_vpn_bgp.py | 10 +- .../networks_appliance_vpn_site_to_site_vpn.py | 12 +- .../cisco/meraki/plugins/action/networks_bind.py | 4 +- .../networks_camera_quality_retention_profiles.py | 64 +- .../action/networks_camera_wireless_profiles.py | 18 +- .../action/networks_cellular_gateway_dhcp.py | 12 +- .../networks_cellular_gateway_subnet_pool.py | 12 +- .../meraki/plugins/action/networks_clients_info.py | 98 +- .../plugins/action/networks_firmware_upgrades.py | 24 +- .../action/networks_firmware_upgrades_rollbacks.py | 4 +- ...tworks_firmware_upgrades_staged_events_defer.py | 2 +- ...ks_firmware_upgrades_staged_events_rollbacks.py | 2 +- .../networks_firmware_upgrades_staged_groups.py | 36 +- .../meraki/plugins/action/networks_floor_plans.py | 54 +- .../plugins/action/networks_group_policies.py | 72 +- .../plugins/action/networks_meraki_auth_users.py | 57 +- .../meraki/plugins/action/networks_mqtt_brokers.py | 8 +- .../meraki/plugins/action/networks_netflow.py | 20 +- .../action/networks_sensor_alerts_profiles.py | 36 +- .../meraki/plugins/action/networks_settings.py | 18 +- .../plugins/action/networks_sm_devices_checkin.py | 8 +- .../plugins/action/networks_sm_devices_fields.py | 8 +- .../plugins/action/networks_sm_devices_info.py | 8 + .../action/networks_sm_devices_install_apps.py | 93 + .../plugins/action/networks_sm_devices_lock.py | 12 +- .../action/networks_sm_devices_modify_tags.py | 8 +- .../plugins/action/networks_sm_devices_move.py | 12 +- .../plugins/action/networks_sm_devices_reboot.py | 103 + .../plugins/action/networks_sm_devices_shutdown.py | 95 + .../action/networks_sm_devices_uninstall_apps.py | 91 + .../plugins/action/networks_sm_devices_wipe.py | 8 +- .../plugins/action/networks_sm_profiles_info.py | 4 + .../action/networks_switch_access_policies.py | 186 +- ...tworks_switch_alternate_management_interface.py | 12 +- .../action/networks_switch_dhcp_server_policy.py | 24 +- ...server_policy_arp_inspection_trusted_servers.py | 18 +- .../action/networks_switch_qos_rules_order.py | 72 +- .../plugins/action/networks_switch_routing_ospf.py | 36 +- .../plugins/action/networks_switch_settings.py | 34 +- .../networks_switch_stacks_routing_interfaces.py | 90 +- ...tworks_switch_stacks_routing_interfaces_dhcp.py | 82 +- ...networks_switch_stacks_routing_static_routes.py | 32 +- .../plugins/action/networks_traffic_analysis.py | 12 +- .../plugins/action/networks_vlan_profiles.py | 260 + ...rks_vlan_profiles_assignments_by_device_info.py | 120 + .../networks_vlan_profiles_assignments_reassign.py | 93 + .../plugins/action/networks_vlan_profiles_info.py | 92 + .../action/networks_webhooks_http_servers.py | 30 +- .../action/networks_webhooks_payload_templates.py | 36 +- ...orks_wireless_alternate_management_interface.py | 24 +- .../action/networks_wireless_bluetooth_settings.py | 34 +- .../networks_wireless_ethernet_ports_profiles.py | 270 + ...orks_wireless_ethernet_ports_profiles_assign.py | 91 + ...tworks_wireless_ethernet_ports_profiles_info.py | 102 + ...wireless_ethernet_ports_profiles_set_default.py | 89 + .../action/networks_wireless_rf_profiles.py | 113 +- .../plugins/action/networks_wireless_settings.py | 26 +- .../plugins/action/networks_wireless_ssids.py | 542 +- .../networks_wireless_ssids_bonjour_forwarding.py | 6 + ...ks_wireless_ssids_device_type_group_policies.py | 10 +- .../action/networks_wireless_ssids_eap_override.py | 24 +- ...ks_wireless_ssids_firewall_l3_firewall_rules.py | 10 +- .../action/networks_wireless_ssids_hotspot20.py | 58 +- .../networks_wireless_ssids_identity_psks.py | 36 +- .../networks_wireless_ssids_splash_settings.py | 132 +- ...etworks_wireless_ssids_traffic_shaping_rules.py | 10 +- .../plugins/action/networks_wireless_ssids_vpn.py | 12 +- .../cisco/meraki/plugins/action/organizations.py | 34 +- .../plugins/action/organizations_action_batches.py | 18 +- .../action/organizations_adaptive_policy_acls.py | 36 +- .../action/organizations_adaptive_policy_groups.py | 36 +- .../organizations_adaptive_policy_policies.py | 36 +- .../meraki/plugins/action/organizations_admins.py | 30 +- .../action/organizations_alerts_profiles.py | 58 +- ...affic_shaping_vpn_exclusions_by_network_info.py | 112 + ...ons_appliance_uplinks_statuses_overview_info.py | 90 + ...ions_appliance_uplinks_usage_by_network_info.py | 102 + .../action/organizations_branding_policies.py | 50 +- ...tions_camera_boundaries_areas_by_device_info.py | 94 + ...tions_camera_boundaries_lines_by_device_info.py | 94 + ...ections_history_by_boundary_by_interval_info.py | 116 + .../organizations_camera_permissions_info.py | 102 + .../plugins/action/organizations_camera_roles.py | 252 + .../action/organizations_camera_roles_info.py | 90 + .../meraki/plugins/action/organizations_claim.py | 4 +- .../action/organizations_config_templates.py | 6 + ...tions_config_templates_switch_profiles_ports.py | 182 +- ...s_devices_availabilities_change_history_info.py | 136 + .../organizations_devices_boots_history_info.py | 132 + .../organizations_early_access_features_opt_ins.py | 12 +- ...ganizations_firmware_upgrades_by_device_info.py | 8 +- .../action/organizations_firmware_upgrades_info.py | 26 +- .../meraki/plugins/action/organizations_info.py | 18 + ...rganizations_insight_monitored_media_servers.py | 18 +- .../action/organizations_inventory_claim.py | 4 +- ...ry_onboarding_cloud_monitoring_export_events.py | 8 +- ...ry_onboarding_cloud_monitoring_networks_info.py | 4 + .../plugins/action/organizations_login_security.py | 96 +- .../action/organizations_networks_combine.py | 4 +- .../action/organizations_openapi_spec_info.py | 4 + .../plugins/action/organizations_policy_objects.py | 66 +- .../action/organizations_policy_objects_groups.py | 12 +- .../plugins/action/organizations_saml_idps.py | 18 +- .../plugins/action/organizations_saml_roles.py | 36 +- .../action/organizations_sm_admins_roles.py | 256 + .../action/organizations_sm_admins_roles_info.py | 108 + ...organizations_sm_sentry_policies_assignments.py | 89 + ..._sentry_policies_assignments_by_network_info.py | 112 + .../meraki/plugins/action/organizations_snmp.py | 22 +- ...izations_summary_top_networks_by_status_info.py | 108 + ...ganizations_webhooks_callbacks_statuses_info.py | 102 + ...s_devices_channel_utilization_by_device_info.py | 132 + ..._devices_channel_utilization_by_network_info.py | 132 + ...ilization_history_by_device_by_interval_info.py | 132 + ...lization_history_by_network_by_interval_info.py | 132 + ..._wireless_devices_packet_loss_by_client_info.py | 136 + ..._wireless_devices_packet_loss_by_device_info.py | 136 + ...wireless_devices_packet_loss_by_network_info.py | 136 + .../modules/administered_identities_me_info.py | 14 +- ...red_licensing_subscription_entitlements_info.py | 83 + ...ed_licensing_subscription_subscriptions_bind.py | 95 + ...d_licensing_subscription_subscriptions_claim.py | 112 + ...ubscription_subscriptions_claim_key_validate.py | 99 + ...ption_subscriptions_compliance_statuses_info.py | 107 + ...ed_licensing_subscription_subscriptions_info.py | 164 + .../cisco/meraki/plugins/modules/devices.py | 3 - .../modules/devices_appliance_performance_info.py | 6 +- .../modules/devices_appliance_radio_settings.py | 128 + .../devices_appliance_radio_settings_info.py | 87 + .../modules/devices_appliance_uplinks_settings.py | 40 +- .../devices_appliance_uplinks_settings_info.py | 40 +- .../devices_appliance_vmx_authentication_token.py | 4 +- .../meraki/plugins/modules/devices_blink_leds.py | 6 +- .../modules/devices_camera_analytics_live_info.py | 11 +- .../modules/devices_camera_custom_analytics.py | 15 +- .../devices_camera_custom_analytics_info.py | 17 +- .../modules/devices_camera_generate_snapshot.py | 4 +- .../devices_camera_quality_and_retention.py | 8 +- .../devices_camera_quality_and_retention_info.py | 16 +- .../meraki/plugins/modules/devices_camera_sense.py | 4 +- .../plugins/modules/devices_camera_sense_info.py | 17 +- .../modules/devices_camera_video_link_info.py | 7 +- .../modules/devices_camera_video_settings.py | 9 +- .../modules/devices_camera_video_settings_info.py | 11 +- .../modules/devices_camera_wireless_profiles.py | 4 +- .../devices_camera_wireless_profiles_info.py | 12 +- .../modules/devices_cellular_gateway_lan.py | 30 +- .../modules/devices_cellular_gateway_lan_info.py | 26 +- ..._cellular_gateway_port_forwarding_rules_info.py | 21 +- .../plugins/modules/devices_cellular_sims.py | 3 + .../plugins/modules/devices_cellular_sims_info.py | 24 +- .../cisco/meraki/plugins/modules/devices_info.py | 46 +- .../modules/devices_live_tools_arp_table.py | 120 + .../modules/devices_live_tools_arp_table_info.py | 36 + .../modules/devices_live_tools_cable_test.py | 130 + .../modules/devices_live_tools_cable_test_info.py | 36 + .../plugins/modules/devices_live_tools_ping.py | 50 +- .../modules/devices_live_tools_ping_device.py | 50 +- .../modules/devices_live_tools_ping_device_info.py | 35 +- .../modules/devices_live_tools_ping_info.py | 30 +- .../modules/devices_live_tools_throughput_test.py | 126 + .../devices_live_tools_throughput_test_info.py | 36 + .../modules/devices_live_tools_wake_on_lan.py | 131 + .../modules/devices_live_tools_wake_on_lan_info.py | 36 + .../plugins/modules/devices_lldp_cdp_info.py | 7 +- .../modules/devices_management_interface.py | 36 +- .../modules/devices_management_interface_info.py | 32 +- .../modules/devices_sensor_relationships.py | 18 +- .../modules/devices_sensor_relationships_info.py | 25 +- .../meraki/plugins/modules/devices_switch_ports.py | 64 +- .../plugins/modules/devices_switch_ports_cycle.py | 4 +- .../plugins/modules/devices_switch_ports_info.py | 92 +- .../modules/devices_switch_ports_statuses_info.py | 91 +- .../modules/devices_switch_routing_interfaces.py | 78 +- .../devices_switch_routing_interfaces_dhcp.py | 42 +- .../devices_switch_routing_interfaces_dhcp_info.py | 42 +- .../devices_switch_routing_interfaces_info.py | 28 +- .../devices_switch_routing_static_routes.py | 39 +- .../devices_switch_routing_static_routes_info.py | 16 +- .../plugins/modules/devices_switch_warm_spare.py | 10 +- .../modules/devices_switch_warm_spare_info.py | 12 +- ...wireless_alternate_management_interface_ipv6.py | 125 + .../modules/devices_wireless_bluetooth_settings.py | 8 +- .../devices_wireless_bluetooth_settings_info.py | 8 +- .../devices_wireless_connection_stats_info.py | 4 +- .../modules/devices_wireless_latency_stats_info.py | 33 +- .../modules/devices_wireless_radio_settings.py | 4 +- .../devices_wireless_radio_settings_info.py | 20 +- .../modules/devices_wireless_status_info.py | 24 +- .../cisco/meraki/plugins/modules/networks.py | 46 +- .../modules/networks_alerts_history_info.py | 12 +- .../plugins/modules/networks_alerts_settings.py | 14 +- .../modules/networks_alerts_settings_info.py | 34 +- ...ce_connectivity_monitoring_destinations_info.py | 13 +- ..._appliance_content_filtering_categories_info.py | 12 +- .../networks_appliance_content_filtering_info.py | 18 +- ...liance_firewall_cellular_firewall_rules_info.py | 18 +- ...works_appliance_firewall_firewalled_services.py | 8 +- ..._appliance_firewall_firewalled_services_info.py | 10 +- ...ks_appliance_firewall_inbound_firewall_rules.py | 17 +- ...pliance_firewall_inbound_firewall_rules_info.py | 18 +- ...ks_appliance_firewall_l3_firewall_rules_info.py | 18 +- ...7_firewall_rules_application_categories_info.py | 18 +- ...ks_appliance_firewall_l7_firewall_rules_info.py | 13 +- ...ppliance_firewall_one_to_many_nat_rules_info.py | 24 +- ...appliance_firewall_one_to_one_nat_rules_info.py | 25 +- ...ppliance_firewall_port_forwarding_rules_info.py | 19 +- .../networks_appliance_firewall_settings_info.py | 8 +- .../plugins/modules/networks_appliance_ports.py | 10 +- .../modules/networks_appliance_ports_info.py | 10 +- ...etworks_appliance_prefixes_delegated_statics.py | 20 +- ...ks_appliance_prefixes_delegated_statics_info.py | 12 +- .../modules/networks_appliance_rf_profiles.py | 199 + .../modules/networks_appliance_rf_profiles_info.py | 108 + .../networks_appliance_security_intrusion.py | 14 +- .../networks_appliance_security_intrusion_info.py | 16 +- .../modules/networks_appliance_security_malware.py | 18 +- .../networks_appliance_security_malware_info.py | 18 +- .../modules/networks_appliance_single_lan.py | 20 +- .../modules/networks_appliance_single_lan_info.py | 20 +- .../plugins/modules/networks_appliance_ssids.py | 27 +- .../modules/networks_appliance_ssids_info.py | 14 +- ...e_traffic_shaping_custom_performance_classes.py | 8 +- .../networks_appliance_traffic_shaping_info.py | 7 +- ...etworks_appliance_traffic_shaping_rules_info.py | 25 +- ...s_appliance_traffic_shaping_uplink_bandwidth.py | 4 +- ...liance_traffic_shaping_uplink_bandwidth_info.py | 16 +- ...s_appliance_traffic_shaping_uplink_selection.py | 62 +- ...liance_traffic_shaping_uplink_selection_info.py | 62 +- ...rks_appliance_traffic_shaping_vpn_exclusions.py | 119 + .../plugins/modules/networks_appliance_vlans.py | 84 +- .../modules/networks_appliance_vlans_info.py | 64 +- .../modules/networks_appliance_vlans_settings.py | 2 +- .../networks_appliance_vlans_settings_info.py | 6 +- .../plugins/modules/networks_appliance_vpn_bgp.py | 8 +- .../modules/networks_appliance_vpn_bgp_info.py | 18 +- .../networks_appliance_vpn_site_to_site_vpn.py | 2 +- ...networks_appliance_vpn_site_to_site_vpn_info.py | 2 +- .../modules/networks_appliance_warm_spare_info.py | 17 +- .../cisco/meraki/plugins/modules/networks_bind.py | 18 +- .../modules/networks_bluetooth_clients_info.py | 18 +- .../networks_camera_quality_retention_profiles.py | 60 +- ...works_camera_quality_retention_profiles_info.py | 36 +- .../modules/networks_camera_wireless_profiles.py | 26 +- .../networks_camera_wireless_profiles_info.py | 20 +- ...ay_connectivity_monitoring_destinations_info.py | 13 +- .../modules/networks_cellular_gateway_dhcp.py | 4 +- .../modules/networks_cellular_gateway_dhcp_info.py | 4 +- .../networks_cellular_gateway_subnet_pool.py | 1 - .../networks_cellular_gateway_subnet_pool_info.py | 16 +- .../modules/networks_cellular_gateway_uplink.py | 9 +- .../networks_cellular_gateway_uplink_info.py | 7 +- .../plugins/modules/networks_clients_info.py | 162 +- .../modules/networks_clients_overview_info.py | 13 +- .../plugins/modules/networks_clients_policy.py | 7 +- .../modules/networks_clients_policy_info.py | 8 +- .../plugins/modules/networks_clients_provision.py | 64 +- ...rks_clients_splash_authorization_status_info.py | 13 +- .../plugins/modules/networks_devices_claim.py | 10 +- .../plugins/modules/networks_devices_claim_vmx.py | 27 +- .../modules/networks_events_event_types_info.py | 4 +- .../meraki/plugins/modules/networks_events_info.py | 34 +- .../plugins/modules/networks_firmware_upgrades.py | 273 +- .../modules/networks_firmware_upgrades_info.py | 246 +- .../networks_firmware_upgrades_rollbacks.py | 20 +- .../networks_firmware_upgrades_staged_events.py | 55 +- ...tworks_firmware_upgrades_staged_events_defer.py | 22 +- ...etworks_firmware_upgrades_staged_events_info.py | 22 +- ...ks_firmware_upgrades_staged_events_rollbacks.py | 22 +- .../networks_firmware_upgrades_staged_groups.py | 49 +- ...etworks_firmware_upgrades_staged_groups_info.py | 14 +- .../networks_firmware_upgrades_staged_stages.py | 4 +- ...etworks_firmware_upgrades_staged_stages_info.py | 4 +- .../meraki/plugins/modules/networks_floor_plans.py | 116 +- .../plugins/modules/networks_floor_plans_info.py | 62 +- .../plugins/modules/networks_group_policies.py | 241 +- .../modules/networks_group_policies_info.py | 130 +- .../plugins/modules/networks_health_alerts_info.py | 46 +- .../cisco/meraki/plugins/modules/networks_info.py | 20 +- ...rks_insight_applications_health_by_time_info.py | 12 +- .../plugins/modules/networks_meraki_auth_users.py | 51 +- .../modules/networks_meraki_auth_users_info.py | 20 +- .../plugins/modules/networks_mqtt_brokers.py | 35 +- .../meraki/plugins/modules/networks_netflow.py | 8 +- .../plugins/modules/networks_netflow_info.py | 10 +- .../plugins/modules/networks_pii_pii_keys_info.py | 23 +- .../plugins/modules/networks_pii_requests_info.py | 17 +- .../networks_pii_sm_devices_for_key_info.py | 9 +- .../modules/networks_pii_sm_owners_for_key_info.py | 9 +- .../modules/networks_policies_by_client_info.py | 12 +- ...ensor_alerts_current_overview_by_metric_info.py | 16 +- ...tworks_sensor_alerts_overview_by_metric_info.py | 14 +- .../modules/networks_sensor_alerts_profiles.py | 228 +- .../networks_sensor_alerts_profiles_info.py | 79 +- .../modules/networks_sensor_mqtt_brokers.py | 4 +- .../modules/networks_sensor_mqtt_brokers_info.py | 4 +- .../modules/networks_sensor_relationships_info.py | 8 +- .../meraki/plugins/modules/networks_settings.py | 27 +- .../plugins/modules/networks_settings_info.py | 18 +- ...orks_sm_bypass_activation_lock_attempts_info.py | 18 +- .../modules/networks_sm_devices_certs_info.py | 10 +- .../plugins/modules/networks_sm_devices_checkin.py | 6 +- .../networks_sm_devices_desktop_logs_info.py | 24 +- ...networks_sm_devices_device_command_logs_info.py | 4 +- .../networks_sm_devices_device_profiles_info.py | 2 +- .../plugins/modules/networks_sm_devices_fields.py | 6 +- .../plugins/modules/networks_sm_devices_info.py | 30 +- .../modules/networks_sm_devices_install_apps.py | 87 + .../plugins/modules/networks_sm_devices_lock.py | 8 +- .../modules/networks_sm_devices_modify_tags.py | 10 +- .../plugins/modules/networks_sm_devices_move.py | 6 +- ...networks_sm_devices_performance_history_info.py | 18 +- .../plugins/modules/networks_sm_devices_reboot.py | 126 + .../networks_sm_devices_security_centers_info.py | 2 +- .../modules/networks_sm_devices_shutdown.py | 104 + .../modules/networks_sm_devices_unenroll.py | 4 +- .../modules/networks_sm_devices_uninstall_apps.py | 81 + .../plugins/modules/networks_sm_devices_wipe.py | 2 +- .../plugins/modules/networks_sm_profiles_info.py | 11 +- .../plugins/modules/networks_sm_target_groups.py | 29 +- .../modules/networks_sm_target_groups_info.py | 14 +- .../networks_sm_trusted_access_configs_info.py | 11 +- .../networks_sm_user_access_devices_info.py | 12 +- .../networks_sm_users_device_profiles_info.py | 2 +- .../plugins/modules/networks_sm_users_info.py | 26 +- .../modules/networks_sm_users_softwares_info.py | 2 +- .../cisco/meraki/plugins/modules/networks_snmp.py | 12 +- .../meraki/plugins/modules/networks_snmp_info.py | 13 +- .../cisco/meraki/plugins/modules/networks_split.py | 12 +- .../networks_switch_access_control_lists.py | 6 +- .../networks_switch_access_control_lists_info.py | 6 +- .../modules/networks_switch_access_policies.py | 97 +- .../networks_switch_access_policies_info.py | 45 +- ...s_switch_alternate_management_interface_info.py | 18 +- .../modules/networks_switch_dhcp_server_policy.py | 25 +- ...server_policy_arp_inspection_trusted_servers.py | 24 +- ...r_policy_arp_inspection_trusted_servers_info.py | 8 +- ...olicy_arp_inspection_warnings_by_device_info.py | 6 +- .../networks_switch_dhcp_server_policy_info.py | 23 +- .../networks_switch_dhcp_v4_servers_seen_info.py | 116 +- .../networks_switch_dscp_to_cos_mappings_info.py | 13 +- .../modules/networks_switch_link_aggregations.py | 44 +- .../networks_switch_link_aggregations_info.py | 4 +- .../meraki/plugins/modules/networks_switch_mtu.py | 6 +- .../plugins/modules/networks_switch_mtu_info.py | 8 +- .../modules/networks_switch_port_schedules.py | 95 +- .../modules/networks_switch_port_schedules_info.py | 15 +- .../modules/networks_switch_qos_rules_order.py | 33 +- .../networks_switch_qos_rules_order_info.py | 16 +- .../modules/networks_switch_routing_multicast.py | 41 +- .../networks_switch_routing_multicast_info.py | 24 +- ...s_switch_routing_multicast_rendezvous_points.py | 24 +- ...tch_routing_multicast_rendezvous_points_info.py | 15 +- .../modules/networks_switch_routing_ospf_info.py | 32 +- .../plugins/modules/networks_switch_settings.py | 34 +- .../modules/networks_switch_settings_info.py | 16 +- .../plugins/modules/networks_switch_stacks.py | 10 +- .../modules/networks_switch_stacks_remove.py | 8 +- .../networks_switch_stacks_routing_interfaces.py | 71 +- ...tworks_switch_stacks_routing_interfaces_dhcp.py | 40 +- ...s_switch_stacks_routing_interfaces_dhcp_info.py | 38 +- ...tworks_switch_stacks_routing_interfaces_info.py | 31 +- ...networks_switch_stacks_routing_static_routes.py | 27 +- ...rks_switch_stacks_routing_static_routes_info.py | 14 +- .../modules/networks_switch_storm_control.py | 6 +- .../meraki/plugins/modules/networks_switch_stp.py | 6 +- .../plugins/modules/networks_switch_stp_info.py | 14 +- .../modules/networks_topology_link_layer_info.py | 59 +- .../plugins/modules/networks_traffic_analysis.py | 25 +- .../modules/networks_traffic_analysis_info.py | 13 +- ..._traffic_shaping_application_categories_info.py | 20 +- ...ks_traffic_shaping_dscp_tagging_options_info.py | 5 +- .../meraki/plugins/modules/networks_unbind.py | 12 +- .../plugins/modules/networks_vlan_profiles.py | 168 + ...rks_vlan_profiles_assignments_by_device_info.py | 135 + .../networks_vlan_profiles_assignments_reassign.py | 102 + .../plugins/modules/networks_vlan_profiles_info.py | 100 + .../modules/networks_webhooks_http_servers.py | 24 +- .../modules/networks_webhooks_http_servers_info.py | 8 +- .../modules/networks_webhooks_payload_templates.py | 32 +- .../networks_webhooks_payload_templates_info.py | 10 +- .../networks_webhooks_webhook_tests_info.py | 4 +- ...wireless_alternate_management_interface_info.py | 20 +- .../plugins/modules/networks_wireless_billing.py | 21 +- .../modules/networks_wireless_billing_info.py | 17 +- .../networks_wireless_bluetooth_settings.py | 8 +- .../networks_wireless_bluetooth_settings_info.py | 8 +- ...ks_wireless_channel_utilization_history_info.py | 6 +- .../networks_wireless_client_count_history_info.py | 4 +- ...works_wireless_clients_connection_stats_info.py | 13 +- ...networks_wireless_clients_latency_stats_info.py | 29 +- .../networks_wireless_data_rate_history_info.py | 4 +- ...works_wireless_devices_connection_stats_info.py | 4 +- .../networks_wireless_ethernet_ports_profiles.py | 171 + ...orks_wireless_ethernet_ports_profiles_assign.py | 87 + ...tworks_wireless_ethernet_ports_profiles_info.py | 100 + ...wireless_ethernet_ports_profiles_set_default.py | 76 + .../networks_wireless_failed_connections_info.py | 8 +- .../networks_wireless_latency_history_info.py | 4 +- .../networks_wireless_latency_stats_info.py | 26 +- .../networks_wireless_mesh_statuses_info.py | 19 +- .../modules/networks_wireless_rf_profiles.py | 689 ++- .../modules/networks_wireless_rf_profiles_info.py | 225 +- .../plugins/modules/networks_wireless_settings.py | 38 +- .../modules/networks_wireless_settings_info.py | 17 +- ...etworks_wireless_signal_quality_history_info.py | 4 +- .../plugins/modules/networks_wireless_ssids.py | 336 +- .../networks_wireless_ssids_bonjour_forwarding.py | 27 +- ...works_wireless_ssids_bonjour_forwarding_info.py | 18 +- ...reless_ssids_device_type_group_policies_info.py | 12 +- .../networks_wireless_ssids_eap_override.py | 12 +- .../networks_wireless_ssids_eap_override_info.py | 12 +- ...ks_wireless_ssids_firewall_l3_firewall_rules.py | 11 +- ...reless_ssids_firewall_l3_firewall_rules_info.py | 15 +- ...ks_wireless_ssids_firewall_l7_firewall_rules.py | 17 +- ...reless_ssids_firewall_l7_firewall_rules_info.py | 13 +- .../networks_wireless_ssids_hotspot20_info.py | 51 +- .../networks_wireless_ssids_identity_psks.py | 28 +- .../networks_wireless_ssids_identity_psks_info.py | 10 +- .../modules/networks_wireless_ssids_info.py | 57 +- .../networks_wireless_ssids_schedules_info.py | 14 +- .../networks_wireless_ssids_splash_settings.py | 79 +- ...networks_wireless_ssids_splash_settings_info.py | 75 +- ...etworks_wireless_ssids_traffic_shaping_rules.py | 36 +- ...ks_wireless_ssids_traffic_shaping_rules_info.py | 26 +- .../modules/networks_wireless_ssids_vpn_info.py | 27 +- .../networks_wireless_usage_history_info.py | 6 +- .../cisco/meraki/plugins/modules/organizations.py | 36 +- .../modules/organizations_action_batches.py | 81 +- .../modules/organizations_action_batches_info.py | 32 +- .../modules/organizations_adaptive_policy_acls.py | 32 +- .../organizations_adaptive_policy_acls_info.py | 8 +- .../organizations_adaptive_policy_groups.py | 27 +- .../organizations_adaptive_policy_groups_info.py | 24 +- .../organizations_adaptive_policy_overview_info.py | 14 +- .../organizations_adaptive_policy_policies.py | 34 +- .../organizations_adaptive_policy_policies_info.py | 28 +- .../organizations_adaptive_policy_settings_info.py | 9 +- .../meraki/plugins/modules/organizations_admins.py | 48 +- .../plugins/modules/organizations_admins_info.py | 24 +- .../modules/organizations_alerts_profiles.py | 60 +- .../modules/organizations_api_requests_info.py | 10 +- ...sts_overview_response_codes_by_interval_info.py | 6 +- ...anizations_appliance_security_intrusion_info.py | 12 +- ...affic_shaping_vpn_exclusions_by_network_info.py | 124 + ...ons_appliance_uplinks_statuses_overview_info.py | 83 + ...ions_appliance_uplinks_usage_by_network_info.py | 109 + ...nizations_appliance_vpn_third_party_vpnpeers.py | 40 +- ...ions_appliance_vpn_third_party_vpnpeers_info.py | 40 +- ...ganizations_appliance_vpn_vpn_firewall_rules.py | 26 +- ...ations_appliance_vpn_vpn_firewall_rules_info.py | 18 +- .../modules/organizations_branding_policies.py | 94 +- .../organizations_branding_policies_info.py | 42 +- ...tions_camera_boundaries_areas_by_device_info.py | 100 + ...tions_camera_boundaries_lines_by_device_info.py | 104 + ...anizations_camera_custom_analytics_artifacts.py | 13 +- ...tions_camera_custom_analytics_artifacts_info.py | 15 +- ...ections_history_by_boundary_by_interval_info.py | 123 + .../organizations_camera_permissions_info.py | 84 + .../plugins/modules/organizations_camera_roles.py | 129 + .../modules/organizations_camera_roles_info.py | 106 + ...ations_cellular_gateway_uplink_statuses_info.py | 20 +- .../meraki/plugins/modules/organizations_claim.py | 22 +- ...zations_clients_bandwidth_usage_history_info.py | 6 +- .../modules/organizations_clients_overview_info.py | 12 +- .../modules/organizations_clients_search_info.py | 51 +- .../meraki/plugins/modules/organizations_clone.py | 14 +- .../modules/organizations_config_templates.py | 25 +- .../modules/organizations_config_templates_info.py | 14 +- ...ations_config_templates_switch_profiles_info.py | 17 +- ...tions_config_templates_switch_profiles_ports.py | 82 +- ..._config_templates_switch_profiles_ports_info.py | 56 +- ...s_devices_availabilities_change_history_info.py | 174 + .../organizations_devices_boots_history_info.py | 149 + .../plugins/modules/organizations_devices_info.py | 27 +- ...evices_power_modules_statuses_by_device_info.py | 12 +- .../modules/organizations_devices_statuses_info.py | 58 +- ...organizations_devices_statuses_overview_info.py | 4 +- ...ons_devices_uplinks_addresses_by_device_info.py | 8 +- ...ations_devices_uplinks_loss_and_latency_info.py | 14 +- .../organizations_early_access_features_info.py | 14 +- .../organizations_early_access_features_opt_ins.py | 24 +- ...nizations_early_access_features_opt_ins_info.py | 17 +- ...ganizations_firmware_upgrades_by_device_info.py | 42 +- .../organizations_firmware_upgrades_info.py | 58 +- .../meraki/plugins/modules/organizations_info.py | 38 +- .../organizations_insight_applications_info.py | 6 +- ...rganizations_insight_monitored_media_servers.py | 21 +- ...zations_insight_monitored_media_servers_info.py | 17 +- .../modules/organizations_inventory_claim.py | 19 +- .../organizations_inventory_devices_info.py | 23 +- ...nventory_onboarding_cloud_monitoring_imports.py | 4 +- ...ory_onboarding_cloud_monitoring_imports_info.py | 8 +- ...ry_onboarding_cloud_monitoring_networks_info.py | 17 +- ...nventory_onboarding_cloud_monitoring_prepare.py | 20 +- .../modules/organizations_inventory_release.py | 6 +- .../plugins/modules/organizations_licenses.py | 28 +- .../modules/organizations_licenses_assign_seats.py | 28 +- .../plugins/modules/organizations_licenses_info.py | 28 +- .../organizations_licenses_overview_info.py | 61 +- .../modules/organizations_licenses_renew_seats.py | 28 +- ...organizations_licensing_coterm_licenses_info.py | 28 +- ...organizations_licensing_coterm_licenses_move.py | 60 +- .../modules/organizations_login_security.py | 28 +- .../modules/organizations_login_security_info.py | 28 +- .../modules/organizations_networks_combine.py | 12 +- .../modules/organizations_openapi_spec_info.py | 39 +- .../modules/organizations_policy_objects.py | 43 +- .../modules/organizations_policy_objects_groups.py | 31 +- .../organizations_policy_objects_groups_info.py | 19 +- .../modules/organizations_policy_objects_info.py | 21 +- .../plugins/modules/organizations_saml_idps.py | 18 +- .../modules/organizations_saml_idps_info.py | 6 +- .../plugins/modules/organizations_saml_roles.py | 44 +- .../modules/organizations_saml_roles_info.py | 29 +- .../organizations_sensor_readings_history_info.py | 48 +- .../organizations_sensor_readings_latest_info.py | 46 +- .../modules/organizations_sm_admins_roles.py | 92 + .../modules/organizations_sm_admins_roles_info.py | 118 + ...organizations_sm_sentry_policies_assignments.py | 134 + ..._sentry_policies_assignments_by_network_info.py | 138 + .../modules/organizations_sm_vpp_accounts_info.py | 19 + .../meraki/plugins/modules/organizations_snmp.py | 16 +- .../plugins/modules/organizations_snmp_info.py | 16 +- ...s_summary_top_appliances_by_utilization_info.py | 14 +- ...anizations_summary_top_clients_by_usage_info.py | 18 +- ...mary_top_clients_manufacturers_by_usage_info.py | 6 +- ...anizations_summary_top_devices_by_usage_info.py | 30 +- ...ons_summary_top_devices_models_by_usage_info.py | 10 +- ...izations_summary_top_networks_by_status_info.py | 145 + ...rganizations_summary_top_ssids_by_usage_info.py | 18 +- ...ns_summary_top_switches_by_energy_usage_info.py | 14 +- .../organizations_switch_ports_by_switch_info.py | 38 +- .../modules/organizations_uplinks_statuses_info.py | 28 +- ...ganizations_webhooks_callbacks_statuses_info.py | 99 + ...s_devices_channel_utilization_by_device_info.py | 159 + ..._devices_channel_utilization_by_network_info.py | 157 + ...ilization_history_by_device_by_interval_info.py | 161 + ...lization_history_by_network_by_interval_info.py | 159 + ...ions_wireless_devices_ethernet_statuses_info.py | 40 +- ..._wireless_devices_packet_loss_by_client_info.py | 163 + ..._wireless_devices_packet_loss_by_device_info.py | 166 + ...wireless_devices_packet_loss_by_network_info.py | 159 + .../cisco/mso/.github/workflows/ansible-test.yml | 24 +- .../mso/.github/workflows/galaxy-importer.cfg | 2 +- ansible_collections/cisco/mso/CHANGELOG.rst | 31 + ansible_collections/cisco/mso/FILES.json | 405 +- ansible_collections/cisco/mso/MANIFEST.json | 4 +- ansible_collections/cisco/mso/README.md | 3 +- .../cisco/mso/changelogs/.plugin-cache.yaml | 16 +- .../cisco/mso/changelogs/changelog.yaml | 642 ++- ansible_collections/cisco/mso/meta/runtime.yml | 11 +- .../cisco/mso/plugins/module_utils/constants.py | 39 +- .../cisco/mso/plugins/module_utils/mso.py | 217 +- .../cisco/mso/plugins/module_utils/schema.py | 75 + .../cisco/mso/plugins/modules/mso_backup.py | 10 - .../mso/plugins/modules/mso_backup_schedule.py | 5 +- .../mso/plugins/modules/mso_dhcp_option_policy.py | 6 +- .../modules/mso_dhcp_option_policy_option.py | 6 +- .../mso/plugins/modules/mso_dhcp_relay_policy.py | 6 +- .../modules/mso_dhcp_relay_policy_provider.py | 6 +- .../cisco/mso/plugins/modules/mso_label.py | 4 - .../mso/plugins/modules/mso_remote_location.py | 5 +- .../cisco/mso/plugins/modules/mso_rest.py | 5 +- .../cisco/mso/plugins/modules/mso_role.py | 4 - .../cisco/mso/plugins/modules/mso_schema.py | 70 +- .../cisco/mso/plugins/modules/mso_schema_clone.py | 1 - .../cisco/mso/plugins/modules/mso_schema_site.py | 4 - .../mso/plugins/modules/mso_schema_site_anp.py | 4 - .../mso/plugins/modules/mso_schema_site_anp_epg.py | 4 - .../mso_schema_site_anp_epg_bulk_staticport.py | 9 +- .../modules/mso_schema_site_anp_epg_domain.py | 208 +- .../modules/mso_schema_site_anp_epg_selector.py | 4 - .../modules/mso_schema_site_anp_epg_staticleaf.py | 4 - .../modules/mso_schema_site_anp_epg_staticport.py | 569 +- .../modules/mso_schema_site_anp_epg_subnet.py | 4 - .../mso_schema_site_anp_epg_useg_attribute.py | 18 +- .../mso/plugins/modules/mso_schema_site_bd.py | 4 - .../plugins/modules/mso_schema_site_bd_l3out.py | 5 - .../plugins/modules/mso_schema_site_bd_subnet.py | 4 - .../mso_schema_site_contract_service_graph.py | 376 ++ ..._schema_site_contract_service_graph_listener.py | 739 +++ .../modules/mso_schema_site_external_epg.py | 40 +- .../mso_schema_site_external_epg_selector.py | 4 - .../mso/plugins/modules/mso_schema_site_l3out.py | 4 - .../modules/mso_schema_site_service_graph.py | 164 +- .../mso/plugins/modules/mso_schema_site_vrf.py | 4 - .../plugins/modules/mso_schema_site_vrf_region.py | 4 - .../modules/mso_schema_site_vrf_region_cidr.py | 4 - .../mso_schema_site_vrf_region_cidr_subnet.py | 4 - .../mso_schema_site_vrf_region_hub_network.py | 3 - .../mso/plugins/modules/mso_schema_template.py | 21 +- .../mso/plugins/modules/mso_schema_template_anp.py | 4 - .../plugins/modules/mso_schema_template_anp_epg.py | 5 - .../mso_schema_template_anp_epg_contract.py | 358 +- .../mso_schema_template_anp_epg_selector.py | 4 - .../modules/mso_schema_template_anp_epg_subnet.py | 4 - .../mso_schema_template_anp_epg_useg_attribute.py | 16 +- .../mso/plugins/modules/mso_schema_template_bd.py | 6 - .../modules/mso_schema_template_bd_dhcp_policy.py | 4 - .../modules/mso_schema_template_bd_subnet.py | 4 - .../plugins/modules/mso_schema_template_clone.py | 3 - .../modules/mso_schema_template_contract_filter.py | 4 - .../mso_schema_template_contract_service_graph.py | 3 - .../plugins/modules/mso_schema_template_deploy.py | 3 - .../modules/mso_schema_template_deploy_status.py | 4 - .../modules/mso_schema_template_external_epg.py | 5 - .../mso_schema_template_external_epg_contract.py | 4 - .../mso_schema_template_external_epg_selector.py | 4 - .../mso_schema_template_external_epg_subnet.py | 6 +- .../modules/mso_schema_template_externalepg.py | 5 - .../modules/mso_schema_template_filter_entry.py | 4 - .../plugins/modules/mso_schema_template_l3out.py | 4 - .../plugins/modules/mso_schema_template_migrate.py | 6 - .../modules/mso_schema_template_service_graph.py | 11 +- .../mso/plugins/modules/mso_schema_template_vrf.py | 4 - .../modules/mso_schema_template_vrf_contract.py | 4 - .../mso/plugins/modules/mso_schema_validate.py | 10 +- .../mso/plugins/modules/mso_service_node_type.py | 6 +- .../cisco/mso/plugins/modules/mso_site.py | 4 - .../cisco/mso/plugins/modules/mso_tenant.py | 36 +- .../cisco/mso/plugins/modules/mso_tenant_site.py | 9 +- .../cisco/mso/plugins/modules/mso_user.py | 6 - .../cisco/mso/plugins/modules/mso_version.py | 1 - .../plugins/modules/ndo_schema_template_deploy.py | 5 +- .../mso/tests/integration/inventory.networking | 4 +- .../integration/targets/mso_backup/tasks/main.yml | 120 +- .../targets/mso_backup_schedule/tasks/main.yml | 39 +- .../targets/mso_dhcp_option_policy/tasks/main.yaml | 72 +- .../mso_dhcp_option_policy_option/tasks/main.yaml | 102 +- .../targets/mso_dhcp_relay_policy/tasks/main.yaml | 66 +- .../mso_dhcp_relay_policy_provider/tasks/main.yaml | 124 +- .../integration/targets/mso_label/tasks/main.yml | 104 +- .../targets/mso_remote_location/tasks/main.yml | 47 +- .../targets/mso_rest/tasks/error_handling.yml | 22 +- .../targets/mso_rest/tasks/json_inline.yml | 52 +- .../targets/mso_rest/tasks/json_string.yml | 42 +- .../targets/mso_rest/tasks/json_template.yml | 14 +- .../integration/targets/mso_rest/tasks/main.yml | 14 +- .../targets/mso_rest/tasks/yaml_inline.yml | 42 +- .../targets/mso_rest/tasks/yaml_string.yml | 42 +- .../integration/targets/mso_role/tasks/main.yml | 14 +- .../integration/targets/mso_role/tasks/role-ro.yml | 20 +- .../integration/targets/mso_role/tasks/role-rw.yml | 72 +- .../integration/targets/mso_schema/tasks/main.yml | 145 +- .../targets/mso_schema_clone/tasks/main.yml | 22 +- .../targets/mso_schema_site/tasks/main.yml | 62 +- .../targets/mso_schema_site_anp/tasks/main.yml | 104 +- .../targets/mso_schema_site_anp_epg/tasks/main.yml | 140 +- .../tasks/main.yml | 138 +- .../mso_schema_site_anp_epg_domain/tasks/main.yml | 341 +- .../tasks/main.yml | 194 +- .../tasks/main.yml | 696 ++- .../tasks/main.yml | 191 +- .../targets/mso_schema_site_bd/tasks/main.yml | 152 +- .../mso_schema_site_bd_l3out/tasks/main.yml | 94 +- .../mso_schema_site_bd_subnet/tasks/main.yml | 134 +- .../mso_schema_site_contract_service_graph/aliases | 2 + .../tasks/l4_l7_devices.yml | 312 + .../tasks/main.yml | 935 +++ .../aliases | 2 + .../tasks/l4_l7_devices.yml | 222 + .../tasks/main.yml | 1604 ++++++ .../tasks/pki/admin.crt | 14 + .../mso_schema_site_external_epg/tasks/main.yml | 435 +- .../tasks/main.yml | 104 +- .../tasks/l4_l7_devices.yml | 237 + .../mso_schema_site_service_graph/tasks/main.yml | 1948 ++++--- .../mso_schema_site_vrf_region/tasks/main.yml | 96 +- .../mso_schema_site_vrf_region_cidr/tasks/main.yml | 172 +- .../tasks/main.yml | 204 +- .../tasks/hub_network.yml | 130 +- .../tasks/main.yml | 6 +- .../targets/mso_schema_template/tasks/main.yml | 160 +- .../targets/mso_schema_template_anp/tasks/main.yml | 68 +- .../mso_schema_template_anp_epg/tasks/main.yml | 240 +- .../tasks/main.yml | 642 ++- .../tasks/main.yml | 142 +- .../tasks/main.yml | 189 +- .../targets/mso_schema_template_bd/tasks/main.yml | 304 +- .../tasks/main.yml | 98 +- .../mso_schema_template_bd_subnet/tasks/main.yml | 122 +- .../mso_schema_template_clone/tasks/main.yml | 26 +- .../tasks/main.yml | 242 +- .../tasks/main.yml | 106 +- .../mso_schema_template_deploy/tasks/main.yml | 2 +- .../tasks/main.yml | 156 +- .../tasks/main.yml | 226 +- .../tasks/main.yml | 126 +- .../tasks/main.yml | 92 +- .../tasks/main.yml | 114 +- .../tasks/main.yml | 34 +- .../mso_schema_template_l3out/tasks/main.yml | 54 +- .../mso_schema_template_migrate/tasks/main.yml | 62 +- .../tasks/main.yml | 255 +- .../targets/mso_schema_template_vrf/tasks/main.yml | 116 +- .../tasks/main.yml | 158 +- .../targets/mso_schema_validate/tasks/main.yml | 2 +- .../targets/mso_service_node_type/tasks/main.yml | 28 +- .../integration/targets/mso_site/tasks/main.yml | 148 +- .../integration/targets/mso_tenant/tasks/main.yml | 234 +- .../targets/mso_tenant_site/tasks/main.yml | 160 +- .../integration/targets/mso_user/tasks/main.yml | 117 +- .../integration/targets/mso_version/tasks/main.yml | 20 +- .../ndo_schema_template_deploy/tasks/main.yml | 2 +- ansible_collections/community/aws/CHANGELOG.rst | 31 +- ansible_collections/community/aws/FILES.json | 37 +- ansible_collections/community/aws/MANIFEST.json | 4 +- .../community/aws/changelogs/changelog.yaml | 23 +- .../community/aws/docs/docsite/rst/CHANGELOG.rst | 31 +- ansible_collections/community/aws/meta/runtime.yml | 1 + .../community/aws/plugins/connection/aws_ssm.py | 5 +- .../community/aws/plugins/module_utils/common.py | 2 +- .../aws/plugins/modules/dynamodb_table_info.py | 292 + .../community/aws/plugins/modules/glue_job.py | 5 +- .../community/aws/plugins/modules/msk_cluster.py | 22 + .../targets/dynamodb_table/tasks/main.yml | 21 + .../dynamodb_table/tasks/test_pay_per_request.yml | 52 + .../targets/elb_target/tasks/lambda_target.yml | 2 +- .../tasks/test_lambda_notifications.yml | 2 +- .../secretsmanager_secret/tasks/rotation.yml | 4 +- .../integration/targets/sns_topic/tasks/main.yml | 2 +- .../community/aws/tests/sanity/ignore-2.17.txt | 2 - .../crypto/.azure-pipelines/azure-pipelines.yml | 136 +- .../crypto/.github/workflows/ansible-test.yml | 19 + .../community/crypto/.github/workflows/reuse.yml | 2 +- ansible_collections/community/crypto/CHANGELOG.md | 620 +- ansible_collections/community/crypto/CHANGELOG.rst | 29 + ansible_collections/community/crypto/FILES.json | 139 +- ansible_collections/community/crypto/MANIFEST.json | 4 +- ansible_collections/community/crypto/README.md | 3 +- .../community/crypto/changelogs/changelog.yaml | 27 + .../community/crypto/docs/docsite/config.yml | 7 + .../module_utils/acme/backend_cryptography.py | 45 +- .../module_utils/acme/backend_openssl_cli.py | 35 +- .../crypto/plugins/module_utils/acme/backends.py | 17 + .../module_utils/crypto/cryptography_crl.py | 45 +- .../module_utils/crypto/cryptography_support.py | 27 + .../crypto/module_backends/certificate.py | 6 +- .../crypto/module_backends/certificate_entrust.py | 8 +- .../crypto/module_backends/certificate_info.py | 11 +- .../crypto/module_backends/certificate_ownca.py | 12 +- .../module_backends/certificate_selfsigned.py | 12 +- .../crypto/plugins/module_utils/crypto/pem.py | 29 + .../crypto/plugins/module_utils/crypto/support.py | 29 +- .../plugins/module_utils/openssh/certificate.py | 26 +- .../crypto/plugins/modules/acme_certificate.py | 2 +- .../plugins/modules/acme_challenge_cert_helper.py | 37 +- .../crypto/plugins/modules/get_certificate.py | 14 +- .../plugins/modules/x509_certificate_convert.py | 280 + .../plugins/modules/x509_certificate_info.py | 6 +- .../community/crypto/plugins/modules/x509_crl.py | 31 +- .../targets/x509_certificate_convert/aliases | 7 + .../targets/x509_certificate_convert/meta/main.yml | 9 + .../x509_certificate_convert/tasks/impl.yml | 212 + .../x509_certificate_convert/tasks/main.yml | 136 + .../community/crypto/tests/sanity/ignore-2.10.txt | 1 + .../community/crypto/tests/sanity/ignore-2.11.txt | 1 + .../community/crypto/tests/sanity/ignore-2.12.txt | 1 + .../community/crypto/tests/sanity/ignore-2.13.txt | 1 + .../community/crypto/tests/sanity/ignore-2.14.txt | 1 + .../community/crypto/tests/sanity/ignore-2.18.txt | 2 + .../crypto/tests/sanity/ignore-2.18.txt.license | 3 + .../community/crypto/tests/sanity/ignore-2.9.txt | 1 + .../dns/.github/workflows/ansible-test.yml | 8 +- .../community/dns/.github/workflows/docs-pr.yml | 1 + .../community/dns/.github/workflows/docs-push.yml | 1 + ansible_collections/community/dns/CHANGELOG.md | 362 +- ansible_collections/community/dns/CHANGELOG.rst | 23 + ansible_collections/community/dns/FILES.json | 103 +- ansible_collections/community/dns/MANIFEST.json | 4 +- ansible_collections/community/dns/README.md | 4 +- .../community/dns/changelogs/changelog.yaml | 20 + .../community/dns/docs/docsite/config.yml | 7 + .../dns/docs/docsite/rst/filter_guide.rst | 5 + .../community/dns/plugins/filter/quote_txt.yml | 46 + .../community/dns/plugins/filter/txt.py | 47 + .../community/dns/plugins/filter/unquote_txt.yml | 42 + .../dns/plugins/plugin_utils/inventory/records.py | 3 +- .../community/dns/plugins/plugin_utils/unsafe.py | 41 + .../community/dns/plugins/public_suffix_list.dat | 211 +- .../tests/integration/targets/filter_txt/aliases | 6 + .../integration/targets/filter_txt/tasks/main.yml | 49 + .../community/dns/tests/sanity/ignore-2.18.txt | 1 + .../dns/tests/sanity/ignore-2.18.txt.license | 3 + .../plugins/inventory/test_hetzner_dns_records.py | 72 +- .../plugins/inventory/test_hosttech_dns_records.py | 76 +- .../dns/tests/unit/requirements-stable-2.10.txt | 2 +- .../docker/.azure-pipelines/azure-pipelines.yml | 100 +- .../docker/.github/workflows/ansible-test.yml | 15 + ansible_collections/community/docker/CHANGELOG.md | 491 +- ansible_collections/community/docker/CHANGELOG.rst | 25 +- ansible_collections/community/docker/FILES.json | 66 +- ansible_collections/community/docker/MANIFEST.json | 4 +- ansible_collections/community/docker/README.md | 2 +- .../community/docker/changelogs/changelog.yaml | 40 +- .../community/docker/docs/docsite/config.yml | 3 + .../community/docker/meta/ee-requirements.txt | 1 + .../docker/plugins/doc_fragments/compose_v2.py | 25 +- .../docker/plugins/inventory/docker_containers.py | 2 +- .../docker/plugins/inventory/docker_machine.py | 2 +- .../docker/plugins/inventory/docker_swarm.py | 2 +- .../docker/plugins/module_utils/_api/api/daemon.py | 62 - .../plugins/module_utils/_api/utils/utils.py | 7 - .../docker/plugins/module_utils/compose_v2.py | 86 +- .../docker/plugins/modules/docker_compose_v2.py | 16 +- .../plugins/modules/docker_compose_v2_pull.py | 12 +- .../docker/plugins/plugin_utils/unsafe.py | 41 + .../docker_compose_v2/tasks/tests/definition.yml | 264 + .../community/docker/tests/sanity/ignore-2.17.txt | 3 + .../community/docker/tests/sanity/ignore-2.18.txt | 4 + .../docker/tests/sanity/ignore-2.18.txt.license | 3 + .../plugins/module_utils/_api/api/test_client.py | 51 - .../general/.azure-pipelines/azure-pipelines.yml | 131 +- .../community/general/.github/BOTMETA.yml | 7 +- .../general/.github/workflows/ansible-test.yml | 21 + ansible_collections/community/general/CHANGELOG.md | 164 +- .../community/general/CHANGELOG.rst | 54 + ansible_collections/community/general/FILES.json | 269 +- .../community/general/MANIFEST.json | 4 +- ansible_collections/community/general/README.md | 2 +- .../community/general/changelogs/changelog.yaml | 112 + .../community/general/docs/docsite/config.yml | 7 + .../community/general/meta/runtime.yml | 40 +- .../community/general/plugins/callback/hipchat.py | 4 + .../general/plugins/callback/loganalytics.py | 13 +- .../community/general/plugins/callback/logstash.py | 9 +- .../community/general/plugins/callback/splunk.py | 13 +- .../general/plugins/callback/sumologic.py | 14 +- .../community/general/plugins/filter/from_ini.py | 2 +- .../community/general/plugins/filter/to_ini.py | 2 +- .../community/general/plugins/inventory/cobbler.py | 3 +- .../general/plugins/inventory/gitlab_runners.py | 3 +- .../community/general/plugins/inventory/icinga2.py | 3 +- .../community/general/plugins/inventory/linode.py | 3 +- .../community/general/plugins/inventory/lxd.py | 2 +- .../community/general/plugins/inventory/nmap.py | 3 +- .../community/general/plugins/inventory/online.py | 3 +- .../general/plugins/inventory/opennebula.py | 3 +- .../community/general/plugins/inventory/proxmox.py | 2 +- .../general/plugins/inventory/scaleway.py | 2 +- .../general/plugins/inventory/stackpath_compute.py | 3 +- .../general/plugins/inventory/virtualbox.py | 3 +- .../general/plugins/inventory/xen_orchestra.py | 2 +- .../community/general/plugins/lookup/bitwarden.py | 40 +- .../plugins/lookup/bitwarden_secrets_manager.py | 21 +- .../general/plugins/lookup/passwordstore.py | 31 + .../general/plugins/module_utils/datetime.py | 32 + .../general/plugins/module_utils/gitlab.py | 13 +- .../module_utils/identity/keycloak/keycloak.py | 102 + .../community/general/plugins/module_utils/ipa.py | 2 +- .../general/plugins/module_utils/puppet.py | 1 + .../general/plugins/module_utils/redfish_utils.py | 50 + .../general/plugins/module_utils/scaleway.py | 8 +- .../general/plugins/modules/aix_filesystem.py | 2 +- .../community/general/plugins/modules/apt_rpm.py | 33 +- .../general/plugins/modules/cobbler_sync.py | 9 +- .../general/plugins/modules/cobbler_system.py | 9 +- .../general/plugins/modules/filesystem.py | 50 +- .../community/general/plugins/modules/flatpak.py | 83 +- .../general/plugins/modules/github_key.py | 10 +- .../general/plugins/modules/gitlab_issue.py | 8 +- .../general/plugins/modules/gitlab_label.py | 12 +- .../general/plugins/modules/gitlab_milestone.py | 12 +- .../community/general/plugins/modules/haproxy.py | 2 +- .../community/general/plugins/modules/imc_rest.py | 13 +- .../community/general/plugins/modules/ini_file.py | 133 +- .../community/general/plugins/modules/java_cert.py | 37 +- .../general/plugins/modules/keycloak_client.py | 16 +- .../plugins/modules/keycloak_client_rolescope.py | 280 + .../plugins/modules/keycloak_clientscope.py | 9 +- .../plugins/modules/keycloak_clienttemplate.py | 9 +- .../general/plugins/modules/keycloak_realm.py | 29 +- .../general/plugins/modules/lxd_container.py | 41 +- .../community/general/plugins/modules/nmcli.py | 47 +- .../general/plugins/modules/osx_defaults.py | 18 +- .../community/general/plugins/modules/pagerduty.py | 10 +- .../general/plugins/modules/pagerduty_change.py | 8 +- .../community/general/plugins/modules/portage.py | 11 + .../community/general/plugins/modules/puppet.py | 10 + .../general/plugins/modules/redfish_command.py | 17 + .../community/general/plugins/modules/riak.py | 15 +- .../general/plugins/modules/scaleway_compute.py | 5 +- .../plugins/modules/scaleway_database_backup.py | 7 +- .../general/plugins/modules/scaleway_lb.py | 5 +- .../general/plugins/modules/ssh_config.py | 5 +- .../plugins/modules/statusio_maintenance.py | 12 +- .../community/general/plugins/modules/xml.py | 9 +- .../general/plugins/plugin_utils/unsafe.py | 41 + .../targets/filesystem/defaults/main.yml | 1 + .../integration/targets/filesystem/tasks/main.yml | 6 +- .../integration/targets/filesystem/tasks/setup.yml | 10 + .../targets/filter_from_ini/tasks/main.yml | 10 +- .../targets/filter_to_ini/tasks/main.yml | 6 + .../targets/flatpak/tasks/check_mode.yml | 98 + .../integration/targets/flatpak/tasks/test.yml | 159 + .../integration/targets/ini_file/tasks/main.yml | 4 +- .../targets/ini_file/tasks/tests/08-section.yml | 341 ++ .../targets/keycloak_client_rolescope/README.md | 20 + .../targets/keycloak_client_rolescope/aliases | 5 + .../keycloak_client_rolescope/tasks/main.yml | 317 + .../keycloak_client_rolescope/vars/main.yml | 26 + .../integration/targets/lookup_lmdb_kv/test.yml | 4 +- .../community/general/tests/sanity/ignore-2.18.txt | 17 + .../general/tests/sanity/ignore-2.18.txt.license | 3 + .../unit/plugins/callback/test_loganalytics.py | 14 +- .../tests/unit/plugins/callback/test_splunk.py | 12 +- .../tests/unit/plugins/lookup/test_bitwarden.py | 86 +- .../hrobot/.github/workflows/ansible-test.yml | 2 + .../community/hrobot/.github/workflows/docs-pr.yml | 1 + .../hrobot/.github/workflows/docs-push.yml | 1 + ansible_collections/community/hrobot/CHANGELOG.md | 116 +- ansible_collections/community/hrobot/CHANGELOG.rst | 13 + ansible_collections/community/hrobot/FILES.json | 53 +- ansible_collections/community/hrobot/MANIFEST.json | 4 +- ansible_collections/community/hrobot/README.md | 2 +- .../community/hrobot/changelogs/changelog.yaml | 10 + .../community/hrobot/docs/docsite/config.yml | 7 + .../community/hrobot/plugins/inventory/robot.py | 2 +- .../hrobot/plugins/plugin_utils/unsafe.py | 41 + .../community/hrobot/tests/sanity/ignore-2.18.txt | 1 + .../hrobot/tests/sanity/ignore-2.18.txt.license | 3 + .../tests/unit/plugins/inventory/test_robot.py | 20 +- .../.github/workflows/ansible-test.yml | 2 + .../.github/workflows/docs-pr.yml | 92 + .../.github/workflows/docs-push.yml | 51 + .../.github/workflows/extra-tests.yml | 4 +- .../.github/workflows/import-galaxy.yml | 79 +- .../.github/workflows/reuse.yml | 9 +- .../library_inventory_filtering_v1/CHANGELOG.md | 34 + .../CHANGELOG.md.license | 3 + .../library_inventory_filtering_v1/CHANGELOG.rst | 7 + .../library_inventory_filtering_v1/FILES.json | 93 +- .../library_inventory_filtering_v1/MANIFEST.json | 4 +- .../library_inventory_filtering_v1/README.md | 26 +- .../changelogs/changelog.yaml | 6 + .../changelogs/config.yaml | 3 + .../docs/docsite/config.yml | 7 + .../docs/docsite/extra-docs.yml | 9 + .../docs/docsite/links.yml | 20 + .../docs/docsite/rst/usage_guide.rst | 75 + .../community/mongodb/CHANGELOG.rst | 13 + ansible_collections/community/mongodb/FILES.json | 8 +- .../community/mongodb/MANIFEST.json | 4 +- ansible_collections/community/mongodb/README.md | 2 +- .../community/mongodb/changelogs/changelog.yaml | 5 + .../roles/mongodb_mongod/templates/mongod.conf.j2 | 2 + .../rabbitmq/.azure-pipelines/azure-pipelines.yml | 239 +- .../community/rabbitmq/CHANGELOG.rst | 17 +- ansible_collections/community/rabbitmq/FILES.json | 65 +- .../community/rabbitmq/MANIFEST.json | 4 +- .../community/rabbitmq/changelogs/changelog.yaml | 24 +- .../community/rabbitmq/plugins/lookup/rabbitmq.py | 3 +- .../rabbitmq/plugins/module_utils/rabbitmq.py | 1 - .../rabbitmq/plugins/modules/rabbitmq_parameter.py | 15 + .../rabbitmq/plugins/modules/rabbitmq_publish.py | 8 - .../rabbitmq/plugins/modules/rabbitmq_user.py | 504 +- .../targets/lookup_rabbitmq/tasks/main.yml | 4 +- .../targets/rabbitmq_publish/tasks/main.yml | 4 +- .../targets/rabbitmq_queue/tasks/main.yml | 4 +- .../targets/rabbitmq_user/tasks/main.yml | 2 + .../targets/rabbitmq_user/tasks/tests_api.yml | 131 + .../targets/rabbitmq_user_limits/tasks/main.yml | 4 +- .../targets/rabbitmq_vhost_limits/tasks/main.yml | 4 +- .../rabbitmq/tests/sanity/ignore-2.10.txt | 2 - .../rabbitmq/tests/sanity/ignore-2.11.txt | 2 - .../rabbitmq/tests/sanity/ignore-2.15.txt | 2 + .../rabbitmq/tests/sanity/ignore-2.16.txt | 3 + .../rabbitmq/tests/sanity/ignore-2.17.txt | 3 + .../community/rabbitmq/tests/sanity/ignore-2.9.txt | 2 - .../community/rabbitmq/tests/sanity/ignore.txt | 2 - .../community/rabbitmq/tests/unit/compat/mock.py | 6 +- .../community/rabbitmq/tests/unit/mock/loader.py | 2 +- .../rabbitmq/tests/utils/shippable/shippable.sh | 1 + .../routeros/.github/workflows/ansible-test.yml | 6 + .../community/routeros/CHANGELOG.md | 193 +- .../community/routeros/CHANGELOG.rst | 22 + ansible_collections/community/routeros/FILES.json | 37 +- .../community/routeros/MANIFEST.json | 4 +- ansible_collections/community/routeros/README.md | 2 +- .../community/routeros/changelogs/changelog.yaml | 32 + .../community/routeros/docs/docsite/config.yml | 7 + .../routeros/plugins/module_utils/_api_data.py | 378 +- .../community/routeros/plugins/modules/api_info.py | 13 + .../routeros/plugins/modules/api_modify.py | 13 + .../routeros/tests/sanity/ignore-2.18.txt | 2 + .../routeros/tests/sanity/ignore-2.18.txt.license | 3 + .../vmware/.github/workflows/ansible-test.yml | 4 +- .../.github/workflows/extra-docs-linting.yml | 6 +- ansible_collections/community/vmware/CHANGELOG.rst | 23 + ansible_collections/community/vmware/FILES.json | 289 +- ansible_collections/community/vmware/MANIFEST.json | 4 +- .../community/vmware/changelogs/changelog.yaml | 28 + .../community/vmware/docs/docsite/extra-docs.yml | 3 - .../vmware/docs/docsite/rst/scenario_guide.rst | 33 - .../docs/docsite/rst/vmware_scenarios/faq.rst | 26 - .../vmware_scenarios/scenario_clone_template.rst | 223 - .../vmware_scenarios/scenario_find_vm_folder.rst | 121 - .../rst/vmware_scenarios/scenario_remove_vm.rst | 127 - .../rst/vmware_scenarios/scenario_rename_vm.rst | 174 - .../rst/vmware_scenarios/scenario_vmware_http.rst | 162 - .../scenario_vmware_tools_connection.rst | 120 - .../rst/vmware_scenarios/vmware_concepts.rst | 45 - .../vmware_scenarios/vmware_external_doc_links.rst | 10 - .../vmware_scenarios/vmware_getting_started.rst | 9 - .../docsite/rst/vmware_scenarios/vmware_intro.rst | 54 - .../rst/vmware_scenarios/vmware_inventory.rst | 91 - .../vmware_scenarios/vmware_inventory_filters.rst | 216 - .../vmware_inventory_hostnames.rst | 128 - .../vmware_inventory_vm_attributes.rst | 1184 ---- .../vmware_scenarios/vmware_module_reference.rst | 9 - .../rst/vmware_scenarios/vmware_requirements.rst | 73 - .../rst/vmware_scenarios/vmware_scenarios.rst | 17 - .../vmware_scenarios/vmware_troubleshooting.rst | 103 - .../community/vmware/meta/runtime.yml | 1 + .../vmware/plugins/doc_fragments/vmware.py | 1 + .../plugins/doc_fragments/vmware_rest_client.py | 3 + .../vmware/plugins/module_utils/vmware.py | 6 +- .../vmware/plugins/modules/vcenter_folder.py | 2 - .../plugins/modules/vmware_all_snapshots_info.py | 204 + .../vmware/plugins/modules/vmware_category.py | 1 - .../vmware/plugins/modules/vmware_category_info.py | 1 - .../vmware/plugins/modules/vmware_cluster.py | 1 - .../vmware/plugins/modules/vmware_cluster_dpm.py | 1 - .../vmware/plugins/modules/vmware_cluster_drs.py | 1 - .../vmware/plugins/modules/vmware_cluster_ha.py | 1 - .../vmware/plugins/modules/vmware_cluster_info.py | 1 - .../vmware/plugins/modules/vmware_cluster_vcls.py | 1 - .../vmware/plugins/modules/vmware_cluster_vsan.py | 1 - .../modules/vmware_content_deploy_ovf_template.py | 1 - .../modules/vmware_content_deploy_template.py | 1 - .../plugins/modules/vmware_content_library_info.py | 1 - .../modules/vmware_content_library_manager.py | 1 - .../plugins/modules/vmware_datastore_cluster.py | 2 - .../modules/vmware_datastore_cluster_manager.py | 1 - .../plugins/modules/vmware_datastore_info.py | 1 - .../vmware/plugins/modules/vmware_deploy_ovf.py | 2 - .../vmware/plugins/modules/vmware_dvswitch.py | 49 +- .../vmware/plugins/modules/vmware_export_ovf.py | 2 - .../vmware/plugins/modules/vmware_guest.py | 37 +- .../plugins/modules/vmware_guest_boot_manager.py | 1 - .../plugins/modules/vmware_guest_controller.py | 1 - .../plugins/modules/vmware_guest_cross_vc_clone.py | 1 - .../modules/vmware_guest_customization_info.py | 1 - .../vmware/plugins/modules/vmware_guest_disk.py | 2 - .../plugins/modules/vmware_guest_disk_info.py | 1 - .../plugins/modules/vmware_guest_instant_clone.py | 2 - .../vmware/plugins/modules/vmware_guest_move.py | 1 - .../plugins/modules/vmware_guest_powerstate.py | 1 - .../modules/vmware_guest_register_operation.py | 4 - .../plugins/modules/vmware_guest_screenshot.py | 1 - .../vmware/plugins/modules/vmware_guest_sendkey.py | 1 - .../plugins/modules/vmware_guest_snapshot.py | 1 - .../plugins/modules/vmware_guest_storage_policy.py | 2 - .../plugins/modules/vmware_guest_tools_info.py | 7 +- .../vmware/plugins/modules/vmware_guest_tpm.py | 1 - .../vmware/plugins/modules/vmware_guest_vgpu.py | 2 - .../plugins/modules/vmware_guest_vgpu_info.py | 2 - .../vmware/plugins/modules/vmware_guest_video.py | 2 - .../plugins/modules/vmware_host_datastore.py | 1 - .../vmware/plugins/modules/vmware_host_dns_info.py | 1 - .../vmware/plugins/modules/vmware_host_lockdown.py | 1 - .../modules/vmware_host_lockdown_exceptions.py | 1 - .../vmware/plugins/modules/vmware_host_scanhba.py | 1 - .../plugins/modules/vmware_local_user_info.py | 1 - .../vmware/plugins/modules/vmware_object_rename.py | 1 - .../community/vmware/plugins/modules/vmware_tag.py | 1 - .../vmware/plugins/modules/vmware_tag_info.py | 1 - .../vmware/plugins/modules/vmware_tag_manager.py | 1 - .../plugins/modules/vmware_vc_infraprofile_info.py | 1 - .../plugins/modules/vmware_vm_config_option.py | 1 - .../vmware/plugins/modules/vmware_vm_shell.py | 1 + .../vmware/scripts/inventory/vmware_inventory.py | 2 +- .../community/vmware/tests/sanity/ignore-2.18.txt | 4 + .../community/vmware/tests/unit/mock/loader.py | 2 +- .../containers/podman/CHANGELOG.rst | 52 + ansible_collections/containers/podman/FILES.json | 1127 ++-- .../containers/podman/MANIFEST.json | 4 +- .../containers/podman/changelogs/changelog.yaml | 33 + .../containers/podman/docs/buildah_connection.html | 2 +- .../containers/podman/docs/index.html | 2 +- .../containers/podman/docs/objects.inv | Bin 6943 -> 7128 bytes .../containers/podman/docs/podman_connection.html | 2 +- .../podman/docs/podman_container_exec_module.html | 18 +- .../podman/docs/podman_container_info_module.html | 2 +- .../podman/docs/podman_container_module.html | 105 +- .../podman/docs/podman_containers_module.html | 2 +- .../podman/docs/podman_export_module.html | 2 +- .../docs/podman_generate_systemd_module.html | 3 +- .../podman/docs/podman_image_info_module.html | 4 +- .../podman/docs/podman_image_module.html | 42 +- .../podman/docs/podman_import_module.html | 2 +- .../containers/podman/docs/podman_load_module.html | 2 +- .../podman/docs/podman_login_info_module.html | 2 +- .../podman/docs/podman_login_module.html | 2 +- .../podman/docs/podman_logout_module.html | 2 +- .../podman/docs/podman_network_info_module.html | 2 +- .../podman/docs/podman_network_module.html | 36 +- .../containers/podman/docs/podman_play_module.html | 51 +- .../podman/docs/podman_pod_info_module.html | 2 +- .../containers/podman/docs/podman_pod_module.html | 50 +- .../podman/docs/podman_prune_module.html | 2 +- .../podman/docs/podman_runlabel_module.html | 2 +- .../containers/podman/docs/podman_save_module.html | 2 +- .../podman/docs/podman_secret_info_module.html | 2 +- .../podman/docs/podman_secret_module.html | 2 +- .../containers/podman/docs/podman_tag_module.html | 2 +- .../podman/docs/podman_unshare_become.html | 2 +- .../podman/docs/podman_volume_info_module.html | 2 +- .../podman/docs/podman_volume_module.html | 39 +- .../module_utils/podman/podman_container_lib.py | 30 +- .../plugins/module_utils/podman/podman_pod_lib.py | 49 +- .../podman/plugins/module_utils/podman/quadlet.py | 636 ++ .../podman/plugins/modules/podman_container.py | 36 + .../plugins/modules/podman_container_exec.py | 14 +- .../plugins/modules/podman_generate_systemd.py | 1 + .../podman/plugins/modules/podman_image.py | 45 +- .../podman/plugins/modules/podman_image_info.py | 2 +- .../podman/plugins/modules/podman_login.py | 5 +- .../podman/plugins/modules/podman_network.py | 41 +- .../podman/plugins/modules/podman_play.py | 100 +- .../podman/plugins/modules/podman_pod.py | 33 +- .../podman/plugins/modules/podman_pod_info.py | 7 +- .../podman/plugins/modules/podman_volume.py | 45 +- .../targets/podman_container/tasks/main.yml | 277 +- .../targets/podman_container_exec/tasks/main.yml | 20 + .../podman_container_idempotency/tasks/main.yml | 20 + .../tasks/rootless-podman-network.yml | 139 +- .../targets/podman_generate_systemd/tasks/main.yml | 11 +- .../targets/podman_image/tasks/main.yml | 128 + .../targets/podman_network/tasks/main.yml | 125 + .../targets/podman_play/tasks/files/multi-yaml.yml | 27 + .../integration/targets/podman_play/tasks/main.yml | 184 +- .../targets/podman_play/tasks/play-multi-yaml.yml | 40 + .../targets/podman_play/tasks/play-with-build.yml | 3 + .../podman_play/tasks/play-with-options.yml | 4 + .../integration/targets/podman_pod/tasks/main.yml | 332 +- .../targets/podman_pod/tasks/resource-limit.yml | 3 + .../targets/podman_prune/tasks/main.yml | 16 + .../targets/podman_volume/tasks/main.yml | 128 + .../containers/podman/tests/sanity/ignore-2.10.txt | 1 + .../containers/podman/tests/sanity/ignore-2.11.txt | 1 + .../containers/podman/tests/sanity/ignore-2.12.txt | 1 + .../containers/podman/tests/sanity/ignore-2.13.txt | 1 + .../containers/podman/tests/sanity/ignore-2.14.txt | 1 + .../containers/podman/tests/sanity/ignore-2.15.txt | 1 + .../containers/podman/tests/sanity/ignore-2.16.txt | 1 + .../containers/podman/tests/sanity/ignore-2.17.txt | 1 + .../containers/podman/tests/sanity/ignore-2.18.txt | 1 + .../containers/podman/tests/sanity/ignore-2.9.txt | 1 + .../dellemc/powerflex/.github/CODEOWNERS | 2 +- .../dellemc/powerflex/CHANGELOG.rst | 15 + ansible_collections/dellemc/powerflex/FILES.json | 81 +- .../dellemc/powerflex/MANIFEST.json | 10 +- ansible_collections/dellemc/powerflex/README.md | 52 +- .../powerflex/changelogs/.plugin-cache.yaml | 12 +- .../dellemc/powerflex/changelogs/changelog.yaml | 12 + .../dellemc/powerflex/docs/CONTRIBUTING.md | 8 +- .../dellemc/powerflex/docs/INSTALLATION.md | 4 +- .../dellemc/powerflex/docs/ISSUE_TRIAGE.md | 4 +- .../dellemc/powerflex/docs/MAINTAINER_GUIDE.md | 2 +- .../dellemc/powerflex/docs/Release Notes.md | 18 +- .../dellemc/powerflex/docs/SECURITY.md | 2 +- .../dellemc/powerflex/docs/modules/info.rst | 172 +- .../powerflex/docs/modules/resource_group.rst | 281 + .../dellemc/powerflex/meta/runtime.yml | 35 +- .../dellemc/powerflex/playbooks/modules/info.yml | 57 + .../powerflex/playbooks/modules/resource_group.yml | 71 + .../powerflex/plugins/doc_fragments/powerflex.py | 2 +- .../plugins/module_utils/storage/dell/utils.py | 38 +- .../dellemc/powerflex/plugins/modules/info.py | 233 +- .../powerflex/plugins/modules/resource_group.py | 631 ++ .../dellemc/powerflex/tests/sanity/ignore-2.14.txt | 3 + .../dellemc/powerflex/tests/sanity/ignore-2.15.txt | 3 + .../dellemc/powerflex/tests/sanity/ignore-2.16.txt | 3 + .../dellemc/powerflex/tests/sanity/ignore-2.17.txt | 1 + .../unit/plugins/module_utils/mock_info_api.py | 3 +- .../module_utils/mock_resource_group_api.py | 162 + .../tests/unit/plugins/modules/test_info.py | 21 + .../unit/plugins/modules/test_resource_group.py | 228 + ansible_collections/fortinet/fortios/CHANGELOG.rst | 28 + ansible_collections/fortinet/fortios/FILES.json | 1384 ++--- ansible_collections/fortinet/fortios/MANIFEST.json | 4 +- ansible_collections/fortinet/fortios/README.md | 10 +- .../fortinet/fortios/changelogs/.plugin-cache.yaml | 2 +- .../fortinet/fortios/changelogs/changelog.yaml | 24 + .../fortinet/fortios/meta/runtime.yml | 2 +- .../plugins/module_utils/fortios/comparison.py | 2 +- .../plugins/module_utils/fortios/secret_field.py | 4 +- .../plugins/modules/fortios_alertemail_setting.py | 9 +- .../modules/fortios_antivirus_exempt_list.py | 9 +- .../plugins/modules/fortios_antivirus_heuristic.py | 9 +- .../modules/fortios_antivirus_mms_checksum.py | 9 +- .../modules/fortios_antivirus_notification.py | 9 +- .../plugins/modules/fortios_antivirus_profile.py | 11 +- .../modules/fortios_antivirus_quarantine.py | 9 +- .../plugins/modules/fortios_antivirus_settings.py | 9 +- .../plugins/modules/fortios_application_custom.py | 9 +- .../plugins/modules/fortios_application_group.py | 9 +- .../plugins/modules/fortios_application_list.py | 9 +- .../plugins/modules/fortios_application_name.py | 15 +- .../modules/fortios_application_rule_settings.py | 9 +- .../plugins/modules/fortios_authentication_rule.py | 9 +- .../modules/fortios_authentication_scheme.py | 9 +- .../modules/fortios_authentication_setting.py | 13 +- .../plugins/modules/fortios_automation_setting.py | 9 +- .../plugins/modules/fortios_casb_profile.py | 22 +- .../modules/fortios_casb_saas_application.py | 32 +- .../plugins/modules/fortios_casb_user_activity.py | 42 +- .../plugins/modules/fortios_certificate_ca.py | 9 +- .../plugins/modules/fortios_certificate_crl.py | 9 +- .../plugins/modules/fortios_certificate_local.py | 9 +- .../plugins/modules/fortios_certificate_remote.py | 9 +- .../modules/fortios_cifs_domain_controller.py | 9 +- .../plugins/modules/fortios_cifs_profile.py | 7 +- .../plugins/modules/fortios_configuration_fact.py | 300 +- .../fortios_credential_store_domain_controller.py | 11 +- .../modules/fortios_diameter_filter_profile.py | 542 ++ .../plugins/modules/fortios_dlp_data_type.py | 30 +- .../plugins/modules/fortios_dlp_dictionary.py | 9 +- .../modules/fortios_dlp_exact_data_match.py | 411 ++ .../plugins/modules/fortios_dlp_filepattern.py | 9 +- .../plugins/modules/fortios_dlp_fp_doc_source.py | 9 +- .../plugins/modules/fortios_dlp_fp_sensitivity.py | 9 +- .../fortios/plugins/modules/fortios_dlp_profile.py | 25 +- .../plugins/modules/fortios_dlp_sensitivity.py | 9 +- .../fortios/plugins/modules/fortios_dlp_sensor.py | 17 +- .../plugins/modules/fortios_dlp_settings.py | 7 +- .../modules/fortios_dnsfilter_domain_filter.py | 9 +- .../plugins/modules/fortios_dnsfilter_profile.py | 9 +- .../fortios/plugins/modules/fortios_dpdk_cpus.py | 22 +- .../fortios/plugins/modules/fortios_dpdk_global.py | 14 +- .../fortios_emailfilter_block_allow_list.py | 11 +- .../plugins/modules/fortios_emailfilter_bwl.py | 9 +- .../plugins/modules/fortios_emailfilter_bword.py | 9 +- .../plugins/modules/fortios_emailfilter_dnsbl.py | 9 +- .../modules/fortios_emailfilter_fortishield.py | 9 +- .../plugins/modules/fortios_emailfilter_iptrust.py | 9 +- .../plugins/modules/fortios_emailfilter_mheader.py | 9 +- .../plugins/modules/fortios_emailfilter_options.py | 9 +- .../plugins/modules/fortios_emailfilter_profile.py | 9 +- .../modules/fortios_endpoint_control_client.py | 9 +- .../modules/fortios_endpoint_control_fctems.py | 36 +- .../fortios_endpoint_control_fctems_override.py | 38 +- .../fortios_endpoint_control_forticlient_ems.py | 11 +- ...dpoint_control_forticlient_registration_sync.py | 11 +- .../modules/fortios_endpoint_control_profile.py | 9 +- ...tios_endpoint_control_registered_forticlient.py | 11 +- .../modules/fortios_endpoint_control_settings.py | 9 +- .../modules/fortios_export_config_playbook.py | 311 +- .../fortios_extender_controller_dataplan.py | 11 +- .../fortios_extender_controller_extender.py | 11 +- ...fortios_extender_controller_extender_profile.py | 11 +- .../modules/fortios_extender_extender_info.py | 15 +- .../fortios_extender_lte_carrier_by_mcc_mnc.py | 17 +- .../modules/fortios_extender_lte_carrier_list.py | 15 +- .../modules/fortios_extender_modem_status.py | 15 +- .../plugins/modules/fortios_extender_sys_info.py | 15 +- .../fortios_extension_controller_dataplan.py | 9 +- .../fortios_extension_controller_extender.py | 9 +- ...ortios_extension_controller_extender_profile.py | 11 +- .../fortios_extension_controller_fortigate.py | 9 +- ...rtios_extension_controller_fortigate_profile.py | 11 +- .../plugins/modules/fortios_file_filter_profile.py | 11 +- .../modules/fortios_firewall_access_proxy.py | 9 +- .../modules/fortios_firewall_access_proxy6.py | 9 +- ...ortios_firewall_access_proxy_ssh_client_cert.py | 11 +- .../fortios_firewall_access_proxy_virtual_host.py | 73 +- .../plugins/modules/fortios_firewall_acl.py | 7 +- .../plugins/modules/fortios_firewall_acl6.py | 7 +- .../plugins/modules/fortios_firewall_address.py | 35 +- .../plugins/modules/fortios_firewall_address6.py | 9 +- .../modules/fortios_firewall_address6_template.py | 9 +- .../plugins/modules/fortios_firewall_addrgrp.py | 19 +- .../plugins/modules/fortios_firewall_addrgrp6.py | 9 +- .../modules/fortios_firewall_auth_portal.py | 9 +- .../fortios_firewall_carrier_endpoint_bwl.py | 9 +- .../modules/fortios_firewall_central_snat_map.py | 9 +- .../plugins/modules/fortios_firewall_city.py | 7 +- .../fortios_firewall_consolidated_policy.py | 11 +- .../plugins/modules/fortios_firewall_country.py | 9 +- .../fortios_firewall_decrypted_traffic_mirror.py | 11 +- .../modules/fortios_firewall_dnstranslation.py | 9 +- .../plugins/modules/fortios_firewall_dos_policy.py | 203 +- .../modules/fortios_firewall_dos_policy6.py | 203 +- .../plugins/modules/fortios_firewall_global.py | 9 +- .../plugins/modules/fortios_firewall_gtp.py | 1038 +++- .../fortios_firewall_identity_based_route.py | 9 +- .../modules/fortios_firewall_interface_policy.py | 16 +- .../modules/fortios_firewall_interface_policy6.py | 16 +- .../modules/fortios_firewall_internet_service.py | 9 +- .../fortios_firewall_internet_service_addition.py | 11 +- .../fortios_firewall_internet_service_append.py | 13 +- .../fortios_firewall_internet_service_botnet.py | 11 +- .../fortios_firewall_internet_service_custom.py | 11 +- ...rtios_firewall_internet_service_custom_group.py | 11 +- ...fortios_firewall_internet_service_definition.py | 11 +- .../fortios_firewall_internet_service_extension.py | 11 +- .../fortios_firewall_internet_service_group.py | 11 +- ...ortios_firewall_internet_service_ipbl_reason.py | 11 +- ...ortios_firewall_internet_service_ipbl_vendor.py | 11 +- .../fortios_firewall_internet_service_list.py | 9 +- .../fortios_firewall_internet_service_name.py | 9 +- .../fortios_firewall_internet_service_owner.py | 11 +- ...fortios_firewall_internet_service_reputation.py | 11 +- .../fortios_firewall_internet_service_sld.py | 9 +- .../modules/fortios_firewall_ip_translation.py | 9 +- .../fortios_firewall_ipmacbinding_setting.py | 9 +- .../modules/fortios_firewall_ipmacbinding_table.py | 9 +- .../plugins/modules/fortios_firewall_ippool.py | 11 +- .../plugins/modules/fortios_firewall_ippool6.py | 9 +- .../modules/fortios_firewall_iprope_list.py | 15 +- .../modules/fortios_firewall_ipv6_eh_filter.py | 9 +- .../modules/fortios_firewall_ldb_monitor.py | 15 +- .../modules/fortios_firewall_local_in_policy.py | 67 +- .../modules/fortios_firewall_local_in_policy6.py | 67 +- .../modules/fortios_firewall_mms_profile.py | 9 +- .../modules/fortios_firewall_multicast_address.py | 9 +- .../modules/fortios_firewall_multicast_address6.py | 9 +- .../modules/fortios_firewall_multicast_policy.py | 57 +- .../modules/fortios_firewall_multicast_policy6.py | 57 +- .../fortios_firewall_network_service_dynamic.py | 11 +- .../plugins/modules/fortios_firewall_pfcp.py | 33 +- .../plugins/modules/fortios_firewall_policy.py | 158 +- .../plugins/modules/fortios_firewall_policy46.py | 9 +- .../plugins/modules/fortios_firewall_policy6.py | 9 +- .../plugins/modules/fortios_firewall_policy64.py | 9 +- .../modules/fortios_firewall_profile_group.py | 18 +- .../fortios_firewall_profile_protocol_options.py | 29 +- .../plugins/modules/fortios_firewall_proute.py | 15 +- .../modules/fortios_firewall_proxy_address.py | 9 +- .../modules/fortios_firewall_proxy_addrgrp.py | 9 +- .../modules/fortios_firewall_proxy_policy.py | 76 +- .../plugins/modules/fortios_firewall_region.py | 9 +- .../modules/fortios_firewall_schedule_group.py | 9 +- .../modules/fortios_firewall_schedule_onetime.py | 9 +- .../modules/fortios_firewall_schedule_recurring.py | 9 +- .../modules/fortios_firewall_security_policy.py | 78 +- .../modules/fortios_firewall_service_category.py | 9 +- .../modules/fortios_firewall_service_custom.py | 40 +- .../modules/fortios_firewall_service_group.py | 25 +- .../fortios_firewall_shaper_per_ip_shaper.py | 9 +- .../fortios_firewall_shaper_traffic_shaper.py | 9 +- .../modules/fortios_firewall_shaping_policy.py | 9 +- .../modules/fortios_firewall_shaping_profile.py | 9 +- .../plugins/modules/fortios_firewall_sniffer.py | 218 +- .../modules/fortios_firewall_ssh_host_key.py | 9 +- .../modules/fortios_firewall_ssh_local_ca.py | 9 +- .../modules/fortios_firewall_ssh_local_key.py | 9 +- .../modules/fortios_firewall_ssh_setting.py | 9 +- .../plugins/modules/fortios_firewall_ssl_server.py | 64 +- .../modules/fortios_firewall_ssl_setting.py | 9 +- .../modules/fortios_firewall_ssl_ssh_profile.py | 39 +- .../modules/fortios_firewall_traffic_class.py | 9 +- .../plugins/modules/fortios_firewall_ttl_policy.py | 9 +- .../plugins/modules/fortios_firewall_vendor_mac.py | 9 +- .../plugins/modules/fortios_firewall_vip.py | 134 +- .../plugins/modules/fortios_firewall_vip46.py | 9 +- .../plugins/modules/fortios_firewall_vip6.py | 183 +- .../plugins/modules/fortios_firewall_vip64.py | 9 +- .../plugins/modules/fortios_firewall_vipgrp.py | 9 +- .../plugins/modules/fortios_firewall_vipgrp46.py | 9 +- .../plugins/modules/fortios_firewall_vipgrp6.py | 9 +- .../plugins/modules/fortios_firewall_vipgrp64.py | 9 +- .../fortios_firewall_wildcard_fqdn_custom.py | 9 +- .../fortios_firewall_wildcard_fqdn_group.py | 11 +- .../plugins/modules/fortios_ftp_proxy_explicit.py | 63 +- .../fortios/plugins/modules/fortios_gtp_apn.py | 13 +- .../plugins/modules/fortios_gtp_apn_shaper.py | 27 +- .../fortios/plugins/modules/fortios_gtp_apngrp.py | 19 +- .../plugins/modules/fortios_gtp_ie_allow_list.py | 39 +- .../plugins/modules/fortios_gtp_ie_white_list.py | 15 +- .../modules/fortios_gtp_message_filter_v0v1.py | 93 +- .../modules/fortios_gtp_message_filter_v2.py | 115 +- .../modules/fortios_gtp_rat_timeout_profile.py | 33 +- .../plugins/modules/fortios_gtp_tunnel_limit.py | 15 +- .../plugins/modules/fortios_hardware_nic.py | 13 +- .../modules/fortios_hardware_npu_np6_dce.py | 15 +- .../fortios_hardware_npu_np6_session_stats.py | 15 +- .../modules/fortios_hardware_npu_np6_sse_stats.py | 15 +- .../plugins/modules/fortios_icap_profile.py | 13 +- .../fortios/plugins/modules/fortios_icap_server.py | 7 +- .../plugins/modules/fortios_icap_server_group.py | 9 +- .../fortios/plugins/modules/fortios_ips_custom.py | 7 +- .../fortios/plugins/modules/fortios_ips_decoder.py | 7 +- .../fortios/plugins/modules/fortios_ips_global.py | 17 +- .../fortios/plugins/modules/fortios_ips_rule.py | 7 +- .../plugins/modules/fortios_ips_rule_settings.py | 9 +- .../fortios/plugins/modules/fortios_ips_sensor.py | 7 +- .../plugins/modules/fortios_ips_settings.py | 21 +- .../plugins/modules/fortios_ips_view_map.py | 7 +- .../plugins/modules/fortios_log_custom_field.py | 9 +- .../plugins/modules/fortios_log_disk_filter.py | 32 +- .../plugins/modules/fortios_log_disk_setting.py | 14 +- .../plugins/modules/fortios_log_eventfilter.py | 9 +- .../modules/fortios_log_fortianalyzer2_filter.py | 25 +- .../fortios_log_fortianalyzer2_override_filter.py | 27 +- .../fortios_log_fortianalyzer2_override_setting.py | 18 +- .../modules/fortios_log_fortianalyzer2_setting.py | 16 +- .../modules/fortios_log_fortianalyzer3_filter.py | 25 +- .../fortios_log_fortianalyzer3_override_filter.py | 27 +- .../fortios_log_fortianalyzer3_override_setting.py | 18 +- .../modules/fortios_log_fortianalyzer3_setting.py | 16 +- .../fortios_log_fortianalyzer_cloud_filter.py | 25 +- ...tios_log_fortianalyzer_cloud_override_filter.py | 27 +- ...ios_log_fortianalyzer_cloud_override_setting.py | 11 +- .../fortios_log_fortianalyzer_cloud_setting.py | 11 +- .../modules/fortios_log_fortianalyzer_filter.py | 25 +- .../fortios_log_fortianalyzer_override_filter.py | 27 +- .../fortios_log_fortianalyzer_override_setting.py | 18 +- .../modules/fortios_log_fortianalyzer_setting.py | 16 +- .../modules/fortios_log_fortiguard_filter.py | 25 +- .../fortios_log_fortiguard_override_filter.py | 25 +- .../fortios_log_fortiguard_override_setting.py | 11 +- .../modules/fortios_log_fortiguard_setting.py | 9 +- .../plugins/modules/fortios_log_gui_display.py | 9 +- .../plugins/modules/fortios_log_memory_filter.py | 25 +- .../modules/fortios_log_memory_global_setting.py | 11 +- .../plugins/modules/fortios_log_memory_setting.py | 9 +- .../modules/fortios_log_null_device_filter.py | 25 +- .../modules/fortios_log_null_device_setting.py | 9 +- .../fortios/plugins/modules/fortios_log_setting.py | 23 +- .../plugins/modules/fortios_log_syslogd2_filter.py | 25 +- .../fortios_log_syslogd2_override_filter.py | 25 +- .../fortios_log_syslogd2_override_setting.py | 9 +- .../modules/fortios_log_syslogd2_setting.py | 9 +- .../plugins/modules/fortios_log_syslogd3_filter.py | 25 +- .../fortios_log_syslogd3_override_filter.py | 25 +- .../fortios_log_syslogd3_override_setting.py | 9 +- .../modules/fortios_log_syslogd3_setting.py | 9 +- .../plugins/modules/fortios_log_syslogd4_filter.py | 25 +- .../fortios_log_syslogd4_override_filter.py | 25 +- .../fortios_log_syslogd4_override_setting.py | 9 +- .../modules/fortios_log_syslogd4_setting.py | 9 +- .../plugins/modules/fortios_log_syslogd_filter.py | 25 +- .../modules/fortios_log_syslogd_override_filter.py | 25 +- .../fortios_log_syslogd_override_setting.py | 9 +- .../plugins/modules/fortios_log_syslogd_setting.py | 9 +- .../fortios_log_tacacsplusaccounting2_filter.py | 11 +- .../fortios_log_tacacsplusaccounting2_setting.py | 11 +- .../fortios_log_tacacsplusaccounting3_filter.py | 11 +- .../fortios_log_tacacsplusaccounting3_setting.py | 11 +- .../fortios_log_tacacsplusaccounting_filter.py | 11 +- .../fortios_log_tacacsplusaccounting_setting.py | 11 +- .../plugins/modules/fortios_log_threat_weight.py | 9 +- .../modules/fortios_log_webtrends_filter.py | 25 +- .../modules/fortios_log_webtrends_setting.py | 9 +- .../fortios/plugins/modules/fortios_monitor.py | 6 +- .../plugins/modules/fortios_monitor_fact.py | 60 + .../modules/fortios_monitoring_np6_ipsec_engine.py | 20 +- .../plugins/modules/fortios_monitoring_npu_hpe.py | 9 +- .../plugins/modules/fortios_nsxt_service_chain.py | 9 +- .../plugins/modules/fortios_nsxt_setting.py | 7 +- .../plugins/modules/fortios_pfcp_message_filter.py | 47 +- .../plugins/modules/fortios_report_chart.py | 7 +- .../plugins/modules/fortios_report_dataset.py | 9 +- .../plugins/modules/fortios_report_layout.py | 7 +- .../plugins/modules/fortios_report_setting.py | 9 +- .../plugins/modules/fortios_report_style.py | 7 +- .../plugins/modules/fortios_report_theme.py | 7 +- .../plugins/modules/fortios_router_access_list.py | 9 +- .../plugins/modules/fortios_router_access_list6.py | 9 +- .../plugins/modules/fortios_router_aspath_list.py | 9 +- .../plugins/modules/fortios_router_auth_path.py | 9 +- .../fortios/plugins/modules/fortios_router_bfd.py | 7 +- .../fortios/plugins/modules/fortios_router_bfd6.py | 7 +- .../fortios/plugins/modules/fortios_router_bgp.py | 711 ++- .../modules/fortios_router_community_list.py | 9 +- .../modules/fortios_router_extcommunity_list.py | 9 +- .../fortios/plugins/modules/fortios_router_isis.py | 7 +- .../plugins/modules/fortios_router_key_chain.py | 11 +- .../plugins/modules/fortios_router_multicast.py | 11 +- .../plugins/modules/fortios_router_multicast6.py | 9 +- .../modules/fortios_router_multicast_flow.py | 9 +- .../fortios/plugins/modules/fortios_router_ospf.py | 7 +- .../plugins/modules/fortios_router_ospf6.py | 7 +- .../plugins/modules/fortios_router_policy.py | 7 +- .../plugins/modules/fortios_router_policy6.py | 9 +- .../plugins/modules/fortios_router_prefix_list.py | 9 +- .../plugins/modules/fortios_router_prefix_list6.py | 9 +- .../fortios/plugins/modules/fortios_router_rip.py | 7 +- .../plugins/modules/fortios_router_ripng.py | 7 +- .../plugins/modules/fortios_router_route_map.py | 24 +- .../plugins/modules/fortios_router_setting.py | 9 +- .../plugins/modules/fortios_router_static.py | 7 +- .../plugins/modules/fortios_router_static6.py | 9 +- .../plugins/modules/fortios_sctp_filter_profile.py | 9 +- .../plugins/modules/fortios_spamfilter_bwl.py | 9 +- .../plugins/modules/fortios_spamfilter_bword.py | 9 +- .../plugins/modules/fortios_spamfilter_dnsbl.py | 9 +- .../modules/fortios_spamfilter_fortishield.py | 9 +- .../plugins/modules/fortios_spamfilter_iptrust.py | 9 +- .../plugins/modules/fortios_spamfilter_mheader.py | 9 +- .../plugins/modules/fortios_spamfilter_options.py | 9 +- .../plugins/modules/fortios_spamfilter_profile.py | 9 +- .../plugins/modules/fortios_ssh_filter_profile.py | 9 +- .../fortios_switch_controller_802_1x_settings.py | 109 +- .../modules/fortios_switch_controller_acl_group.py | 9 +- .../fortios_switch_controller_acl_ingress.py | 9 +- ...fortios_switch_controller_auto_config_custom.py | 11 +- ...ortios_switch_controller_auto_config_default.py | 11 +- ...fortios_switch_controller_auto_config_policy.py | 11 +- .../fortios_switch_controller_custom_command.py | 11 +- ...ortios_switch_controller_dynamic_port_policy.py | 17 +- .../fortios_switch_controller_flow_tracking.py | 11 +- ...fortios_switch_controller_fortilink_settings.py | 11 +- .../modules/fortios_switch_controller_global.py | 9 +- .../fortios_switch_controller_igmp_snooping.py | 11 +- ...os_switch_controller_initial_config_template.py | 11 +- ...rtios_switch_controller_initial_config_vlans.py | 11 +- .../fortios_switch_controller_lldp_profile.py | 15 +- .../fortios_switch_controller_lldp_settings.py | 11 +- .../modules/fortios_switch_controller_location.py | 9 +- .../fortios_switch_controller_mac_policy.py | 11 +- .../fortios_switch_controller_mac_sync_settings.py | 11 +- .../fortios_switch_controller_managed_switch.py | 234 +- .../fortios_switch_controller_nac_device.py | 11 +- .../fortios_switch_controller_nac_settings.py | 9 +- ...s_switch_controller_network_monitor_settings.py | 11 +- .../modules/fortios_switch_controller_poe.py | 15 +- .../fortios_switch_controller_port_policy.py | 15 +- ...rtios_switch_controller_ptp_interface_policy.py | 11 +- .../fortios_switch_controller_ptp_policy.py | 11 +- .../fortios_switch_controller_ptp_profile.py | 9 +- .../fortios_switch_controller_ptp_settings.py | 9 +- .../fortios_switch_controller_qos_dot1p_map.py | 11 +- .../fortios_switch_controller_qos_ip_dscp_map.py | 11 +- .../fortios_switch_controller_qos_qos_policy.py | 11 +- .../fortios_switch_controller_qos_queue_policy.py | 11 +- .../fortios_switch_controller_quarantine.py | 9 +- .../fortios_switch_controller_remote_log.py | 11 +- ...ios_switch_controller_security_policy_802_1x.py | 14 +- ...ch_controller_security_policy_captive_portal.py | 11 +- ...itch_controller_security_policy_local_access.py | 11 +- .../modules/fortios_switch_controller_sflow.py | 9 +- .../fortios_switch_controller_snmp_community.py | 11 +- .../fortios_switch_controller_snmp_sysinfo.py | 9 +- ...ortios_switch_controller_snmp_trap_threshold.py | 11 +- .../modules/fortios_switch_controller_snmp_user.py | 9 +- .../fortios_switch_controller_storm_control.py | 11 +- ...rtios_switch_controller_storm_control_policy.py | 11 +- .../fortios_switch_controller_stp_instance.py | 9 +- .../fortios_switch_controller_stp_settings.py | 9 +- .../fortios_switch_controller_switch_group.py | 9 +- ...rtios_switch_controller_switch_interface_tag.py | 11 +- .../fortios_switch_controller_switch_log.py | 9 +- .../fortios_switch_controller_switch_profile.py | 11 +- .../modules/fortios_switch_controller_system.py | 16 +- .../fortios_switch_controller_traffic_policy.py | 11 +- .../fortios_switch_controller_traffic_sniffer.py | 11 +- .../fortios_switch_controller_virtual_port_pool.py | 11 +- .../modules/fortios_switch_controller_vlan.py | 9 +- .../fortios_switch_controller_vlan_policy.py | 9 +- .../modules/fortios_system_3g_modem_custom.py | 9 +- .../plugins/modules/fortios_system_accprofile.py | 99 +- .../fortios/plugins/modules/fortios_system_acme.py | 7 +- .../plugins/modules/fortios_system_admin.py | 7 +- .../modules/fortios_system_affinity_interrupt.py | 9 +- ...ortios_system_affinity_packet_redistribution.py | 11 +- .../plugins/modules/fortios_system_alarm.py | 7 +- .../plugins/modules/fortios_system_alias.py | 7 +- .../plugins/modules/fortios_system_api_user.py | 9 +- .../plugins/modules/fortios_system_arp_table.py | 9 +- .../plugins/modules/fortios_system_auto_install.py | 9 +- .../plugins/modules/fortios_system_auto_script.py | 9 +- .../modules/fortios_system_automation_action.py | 15 +- .../fortios_system_automation_destination.py | 9 +- .../modules/fortios_system_automation_stitch.py | 9 +- .../modules/fortios_system_automation_trigger.py | 9 +- .../fortios_system_autoupdate_push_update.py | 9 +- .../modules/fortios_system_autoupdate_schedule.py | 9 +- .../modules/fortios_system_autoupdate_tunneling.py | 9 +- .../modules/fortios_system_central_management.py | 9 +- .../plugins/modules/fortios_system_cluster_sync.py | 9 +- .../plugins/modules/fortios_system_console.py | 31 +- .../fortios/plugins/modules/fortios_system_csf.py | 14 +- .../modules/fortios_system_custom_language.py | 9 +- .../fortios/plugins/modules/fortios_system_ddns.py | 17 +- .../modules/fortios_system_dedicated_mgmt.py | 9 +- .../modules/fortios_system_device_upgrade.py | 47 +- .../plugins/modules/fortios_system_dhcp6_server.py | 9 +- .../plugins/modules/fortios_system_dhcp_server.py | 187 +- .../fortios/plugins/modules/fortios_system_dns.py | 7 +- .../plugins/modules/fortios_system_dns64.py | 7 +- .../plugins/modules/fortios_system_dns_database.py | 9 +- .../plugins/modules/fortios_system_dns_server.py | 9 +- .../modules/fortios_system_dscp_based_priority.py | 9 +- .../plugins/modules/fortios_system_email_server.py | 9 +- .../fortios/plugins/modules/fortios_system_evpn.py | 7 +- .../modules/fortios_system_external_resource.py | 11 +- .../plugins/modules/fortios_system_fabric_vpn.py | 9 +- .../modules/fortios_system_federated_upgrade.py | 36 +- .../plugins/modules/fortios_system_fips_cc.py | 9 +- .../fortios/plugins/modules/fortios_system_fm.py | 7 +- .../plugins/modules/fortios_system_fortiai.py | 9 +- .../plugins/modules/fortios_system_fortiguard.py | 9 +- .../plugins/modules/fortios_system_fortimanager.py | 9 +- .../plugins/modules/fortios_system_fortindr.py | 9 +- .../plugins/modules/fortios_system_fortisandbox.py | 9 +- .../plugins/modules/fortios_system_fsso_polling.py | 9 +- .../plugins/modules/fortios_system_ftm_push.py | 9 +- .../plugins/modules/fortios_system_geneve.py | 7 +- .../modules/fortios_system_geoip_country.py | 9 +- .../modules/fortios_system_geoip_override.py | 9 +- .../plugins/modules/fortios_system_gi_gk.py | 13 +- .../plugins/modules/fortios_system_global.py | 437 +- .../plugins/modules/fortios_system_gre_tunnel.py | 25 +- .../fortios/plugins/modules/fortios_system_ha.py | 74 +- .../plugins/modules/fortios_system_ha_monitor.py | 9 +- .../fortios/plugins/modules/fortios_system_ike.py | 7 +- .../plugins/modules/fortios_system_interface.py | 387 +- .../fortios/plugins/modules/fortios_system_ipam.py | 29 +- .../plugins/modules/fortios_system_ipip_tunnel.py | 9 +- .../fortios/plugins/modules/fortios_system_ips.py | 7 +- .../modules/fortios_system_ips_urlfilter_dns.py | 9 +- .../modules/fortios_system_ips_urlfilter_dns6.py | 9 +- .../modules/fortios_system_ipsec_aggregate.py | 9 +- .../modules/fortios_system_ipv6_neighbor_cache.py | 9 +- .../plugins/modules/fortios_system_ipv6_tunnel.py | 9 +- .../modules/fortios_system_isf_queue_profile.py | 48 +- .../plugins/modules/fortios_system_link_monitor.py | 9 +- .../modules/fortios_system_lldp_network_policy.py | 9 +- .../plugins/modules/fortios_system_lte_modem.py | 9 +- .../modules/fortios_system_mac_address_table.py | 9 +- .../modules/fortios_system_management_tunnel.py | 9 +- .../plugins/modules/fortios_system_mem_mgr.py | 9 +- .../modules/fortios_system_mobile_tunnel.py | 9 +- .../plugins/modules/fortios_system_modem.py | 7 +- .../plugins/modules/fortios_system_nat64.py | 7 +- .../plugins/modules/fortios_system_nd_proxy.py | 9 +- .../plugins/modules/fortios_system_netflow.py | 88 +- .../modules/fortios_system_network_visibility.py | 9 +- .../fortios/plugins/modules/fortios_system_np6.py | 179 +- .../fortios/plugins/modules/fortios_system_npu.py | 6051 +++++++++++++++++++- .../plugins/modules/fortios_system_npu_vlink.py | 352 ++ .../fortios/plugins/modules/fortios_system_ntp.py | 25 +- .../modules/fortios_system_object_tagging.py | 9 +- .../modules/fortios_system_password_policy.py | 9 +- .../fortios_system_password_policy_guest_admin.py | 11 +- .../plugins/modules/fortios_system_pcp_server.py | 9 +- .../modules/fortios_system_performance_top.py | 15 +- .../modules/fortios_system_physical_switch.py | 19 +- .../modules/fortios_system_pppoe_interface.py | 9 +- .../modules/fortios_system_probe_response.py | 9 +- .../plugins/modules/fortios_system_proxy_arp.py | 9 +- .../fortios/plugins/modules/fortios_system_ptp.py | 7 +- .../modules/fortios_system_replacemsg_admin.py | 9 +- .../modules/fortios_system_replacemsg_alertmail.py | 9 +- .../modules/fortios_system_replacemsg_auth.py | 9 +- .../fortios_system_replacemsg_automation.py | 11 +- ...os_system_replacemsg_device_detection_portal.py | 11 +- .../modules/fortios_system_replacemsg_ec.py | 9 +- .../fortios_system_replacemsg_fortiguard_wf.py | 11 +- .../modules/fortios_system_replacemsg_ftp.py | 9 +- .../modules/fortios_system_replacemsg_group.py | 15 +- .../modules/fortios_system_replacemsg_http.py | 9 +- .../modules/fortios_system_replacemsg_icap.py | 9 +- .../modules/fortios_system_replacemsg_image.py | 9 +- .../modules/fortios_system_replacemsg_mail.py | 9 +- .../modules/fortios_system_replacemsg_mm1.py | 15 +- .../modules/fortios_system_replacemsg_mm3.py | 15 +- .../modules/fortios_system_replacemsg_mm4.py | 15 +- .../modules/fortios_system_replacemsg_mm7.py | 15 +- .../modules/fortios_system_replacemsg_mms.py | 9 +- .../modules/fortios_system_replacemsg_nac_quar.py | 9 +- .../modules/fortios_system_replacemsg_nntp.py | 9 +- .../modules/fortios_system_replacemsg_spam.py | 9 +- .../modules/fortios_system_replacemsg_sslvpn.py | 9 +- .../fortios_system_replacemsg_traffic_quota.py | 11 +- .../modules/fortios_system_replacemsg_utm.py | 9 +- .../modules/fortios_system_replacemsg_webproxy.py | 9 +- .../modules/fortios_system_resource_limits.py | 9 +- .../fortios/plugins/modules/fortios_system_saml.py | 7 +- .../modules/fortios_system_sdn_connector.py | 9 +- .../plugins/modules/fortios_system_sdn_proxy.py | 9 +- .../plugins/modules/fortios_system_sdwan.py | 92 +- .../modules/fortios_system_session_helper.py | 33 +- .../plugins/modules/fortios_system_session_ttl.py | 11 +- .../plugins/modules/fortios_system_settings.py | 59 +- .../plugins/modules/fortios_system_sflow.py | 87 +- .../plugins/modules/fortios_system_sit_tunnel.py | 9 +- .../plugins/modules/fortios_system_smc_ntp.py | 36 +- .../plugins/modules/fortios_system_sms_server.py | 9 +- .../modules/fortios_system_snmp_community.py | 15 +- .../modules/fortios_system_snmp_mib_view.py | 9 +- .../plugins/modules/fortios_system_snmp_sysinfo.py | 26 +- .../plugins/modules/fortios_system_snmp_user.py | 15 +- .../modules/fortios_system_speed_test_schedule.py | 46 +- .../modules/fortios_system_speed_test_server.py | 9 +- .../modules/fortios_system_speed_test_setting.py | 9 +- .../plugins/modules/fortios_system_sso_admin.py | 9 +- .../modules/fortios_system_sso_forticloud_admin.py | 9 +- .../fortios_system_sso_fortigate_cloud_admin.py | 11 +- .../modules/fortios_system_standalone_cluster.py | 29 +- .../plugins/modules/fortios_system_storage.py | 22 +- .../fortios/plugins/modules/fortios_system_stp.py | 19 +- .../modules/fortios_system_switch_interface.py | 9 +- .../modules/fortios_system_tos_based_priority.py | 9 +- .../fortios/plugins/modules/fortios_system_vdom.py | 7 +- .../plugins/modules/fortios_system_vdom_dns.py | 9 +- .../modules/fortios_system_vdom_exception.py | 15 +- .../plugins/modules/fortios_system_vdom_link.py | 9 +- .../plugins/modules/fortios_system_vdom_netflow.py | 88 +- .../modules/fortios_system_vdom_property.py | 9 +- .../modules/fortios_system_vdom_radius_server.py | 9 +- .../plugins/modules/fortios_system_vdom_sflow.py | 89 +- .../modules/fortios_system_virtual_switch.py | 28 +- .../modules/fortios_system_virtual_wan_link.py | 9 +- .../modules/fortios_system_virtual_wire_pair.py | 37 +- .../plugins/modules/fortios_system_vne_tunnel.py | 9 +- .../plugins/modules/fortios_system_vxlan.py | 7 +- .../fortios/plugins/modules/fortios_system_wccp.py | 7 +- .../fortios/plugins/modules/fortios_system_zone.py | 7 +- .../fortios/plugins/modules/fortios_user_adgrp.py | 7 +- .../plugins/modules/fortios_user_certificate.py | 9 +- .../fortios/plugins/modules/fortios_user_device.py | 7 +- .../modules/fortios_user_device_access_list.py | 9 +- .../modules/fortios_user_device_category.py | 9 +- .../plugins/modules/fortios_user_device_group.py | 9 +- .../modules/fortios_user_domain_controller.py | 9 +- .../plugins/modules/fortios_user_exchange.py | 7 +- .../fortios_user_external_identity_provider.py | 462 ++ .../plugins/modules/fortios_user_fortitoken.py | 9 +- .../fortios/plugins/modules/fortios_user_fsso.py | 7 +- .../plugins/modules/fortios_user_fsso_polling.py | 9 +- .../fortios/plugins/modules/fortios_user_group.py | 21 +- .../plugins/modules/fortios_user_krb_keytab.py | 9 +- .../fortios/plugins/modules/fortios_user_ldap.py | 7 +- .../fortios/plugins/modules/fortios_user_local.py | 20 +- .../plugins/modules/fortios_user_nac_policy.py | 9 +- .../modules/fortios_user_password_policy.py | 9 +- .../fortios/plugins/modules/fortios_user_peer.py | 11 +- .../plugins/modules/fortios_user_peergrp.py | 7 +- .../fortios/plugins/modules/fortios_user_pop3.py | 7 +- .../plugins/modules/fortios_user_quarantine.py | 9 +- .../fortios/plugins/modules/fortios_user_radius.py | 21 +- .../fortios/plugins/modules/fortios_user_saml.py | 9 +- .../modules/fortios_user_security_exempt_list.py | 9 +- .../plugins/modules/fortios_user_setting.py | 7 +- .../plugins/modules/fortios_user_tacacsplus.py | 9 +- .../plugins/modules/fortios_videofilter_keyword.py | 438 ++ .../plugins/modules/fortios_videofilter_profile.py | 173 +- .../fortios_videofilter_youtube_channel_filter.py | 33 +- .../modules/fortios_videofilter_youtube_key.py | 9 +- .../modules/fortios_virtual_patch_profile.py | 9 +- .../plugins/modules/fortios_voip_profile.py | 7 +- .../plugins/modules/fortios_vpn_certificate_ca.py | 9 +- .../plugins/modules/fortios_vpn_certificate_crl.py | 9 +- .../modules/fortios_vpn_certificate_local.py | 9 +- .../modules/fortios_vpn_certificate_ocsp_server.py | 9 +- .../modules/fortios_vpn_certificate_remote.py | 9 +- .../modules/fortios_vpn_certificate_setting.py | 16 +- .../plugins/modules/fortios_vpn_ike_gateway.py | 15 +- .../modules/fortios_vpn_ipsec_concentrator.py | 9 +- .../plugins/modules/fortios_vpn_ipsec_fec.py | 7 +- .../modules/fortios_vpn_ipsec_forticlient.py | 9 +- .../plugins/modules/fortios_vpn_ipsec_manualkey.py | 9 +- .../fortios_vpn_ipsec_manualkey_interface.py | 9 +- .../plugins/modules/fortios_vpn_ipsec_phase1.py | 205 +- .../modules/fortios_vpn_ipsec_phase1_interface.py | 163 +- .../plugins/modules/fortios_vpn_ipsec_phase2.py | 9 +- .../modules/fortios_vpn_ipsec_phase2_interface.py | 9 +- .../plugins/modules/fortios_vpn_kmip_server.py | 9 +- .../fortios/plugins/modules/fortios_vpn_l2tp.py | 7 +- .../fortios/plugins/modules/fortios_vpn_ocvpn.py | 7 +- .../fortios/plugins/modules/fortios_vpn_pptp.py | 7 +- .../fortios/plugins/modules/fortios_vpn_qkd.py | 403 ++ .../plugins/modules/fortios_vpn_ssl_client.py | 9 +- .../plugins/modules/fortios_vpn_ssl_settings.py | 9 +- .../fortios_vpn_ssl_web_host_check_software.py | 11 +- .../plugins/modules/fortios_vpn_ssl_web_portal.py | 11 +- .../plugins/modules/fortios_vpn_ssl_web_realm.py | 9 +- .../modules/fortios_vpn_ssl_web_user_bookmark.py | 11 +- .../fortios_vpn_ssl_web_user_group_bookmark.py | 13 +- .../plugins/modules/fortios_waf_main_class.py | 9 +- .../fortios/plugins/modules/fortios_waf_profile.py | 7 +- .../plugins/modules/fortios_waf_signature.py | 7 +- .../plugins/modules/fortios_waf_sub_class.py | 7 +- .../plugins/modules/fortios_wanopt_auth_group.py | 9 +- .../modules/fortios_wanopt_cache_service.py | 9 +- ...fortios_wanopt_content_delivery_network_rule.py | 11 +- .../fortios/plugins/modules/fortios_wanopt_peer.py | 7 +- .../plugins/modules/fortios_wanopt_profile.py | 9 +- .../modules/fortios_wanopt_remote_storage.py | 9 +- .../plugins/modules/fortios_wanopt_settings.py | 9 +- .../plugins/modules/fortios_wanopt_webcache.py | 9 +- .../plugins/modules/fortios_web_proxy_debug_url.py | 9 +- .../plugins/modules/fortios_web_proxy_explicit.py | 9 +- .../modules/fortios_web_proxy_fast_fallback.py | 9 +- .../modules/fortios_web_proxy_forward_server.py | 25 +- .../fortios_web_proxy_forward_server_group.py | 9 +- .../plugins/modules/fortios_web_proxy_global.py | 51 +- .../plugins/modules/fortios_web_proxy_profile.py | 9 +- .../plugins/modules/fortios_web_proxy_url_match.py | 9 +- .../plugins/modules/fortios_web_proxy_wisp.py | 9 +- .../plugins/modules/fortios_webfilter_content.py | 9 +- .../modules/fortios_webfilter_content_header.py | 9 +- .../modules/fortios_webfilter_fortiguard.py | 9 +- .../modules/fortios_webfilter_ftgd_local_cat.py | 9 +- .../modules/fortios_webfilter_ftgd_local_rating.py | 9 +- ...ortios_webfilter_ips_urlfilter_cache_setting.py | 11 +- .../fortios_webfilter_ips_urlfilter_setting.py | 11 +- .../fortios_webfilter_ips_urlfilter_setting6.py | 13 +- .../plugins/modules/fortios_webfilter_override.py | 9 +- .../plugins/modules/fortios_webfilter_profile.py | 59 +- .../modules/fortios_webfilter_search_engine.py | 9 +- .../plugins/modules/fortios_webfilter_status.py | 15 +- .../plugins/modules/fortios_webfilter_urlfilter.py | 9 +- ...tios_wireless_controller_access_control_list.py | 11 +- .../modules/fortios_wireless_controller_address.py | 9 +- .../modules/fortios_wireless_controller_addrgrp.py | 9 +- .../fortios_wireless_controller_ap_status.py | 9 +- .../fortios_wireless_controller_apcfg_profile.py | 13 +- .../fortios_wireless_controller_arrp_profile.py | 11 +- .../fortios_wireless_controller_ble_profile.py | 11 +- .../fortios_wireless_controller_bonjour_profile.py | 11 +- .../fortios_wireless_controller_client_info.py | 17 +- .../modules/fortios_wireless_controller_global.py | 33 +- ...less_controller_hotspot20_anqp_3gpp_cellular.py | 11 +- ...ss_controller_hotspot20_anqp_ip_address_type.py | 11 +- ...wireless_controller_hotspot20_anqp_nai_realm.py | 11 +- ..._controller_hotspot20_anqp_network_auth_type.py | 11 +- ...controller_hotspot20_anqp_roaming_consortium.py | 11 +- ...ireless_controller_hotspot20_anqp_venue_name.py | 11 +- ...wireless_controller_hotspot20_anqp_venue_url.py | 11 +- ...s_controller_hotspot20_h2qp_advice_of_charge.py | 11 +- ...ss_controller_hotspot20_h2qp_conn_capability.py | 11 +- ...less_controller_hotspot20_h2qp_operator_name.py | 11 +- ...eless_controller_hotspot20_h2qp_osu_provider.py | 11 +- ...s_controller_hotspot20_h2qp_osu_provider_nai.py | 11 +- ...ntroller_hotspot20_h2qp_terms_and_conditions.py | 11 +- ...ireless_controller_hotspot20_h2qp_wan_metric.py | 11 +- ...ios_wireless_controller_hotspot20_hs_profile.py | 17 +- .../fortios_wireless_controller_hotspot20_icon.py | 11 +- ...ortios_wireless_controller_hotspot20_qos_map.py | 11 +- ...fortios_wireless_controller_inter_controller.py | 11 +- .../modules/fortios_wireless_controller_log.py | 9 +- .../fortios_wireless_controller_mpsk_profile.py | 11 +- .../fortios_wireless_controller_nac_profile.py | 11 +- .../fortios_wireless_controller_qos_profile.py | 11 +- .../modules/fortios_wireless_controller_region.py | 9 +- .../fortios_wireless_controller_rf_analysis.py | 17 +- .../modules/fortios_wireless_controller_setting.py | 23 +- .../modules/fortios_wireless_controller_snmp.py | 9 +- .../fortios_wireless_controller_spectral_info.py | 17 +- .../fortios_wireless_controller_ssid_policy.py | 11 +- .../modules/fortios_wireless_controller_status.py | 15 +- .../fortios_wireless_controller_syslog_profile.py | 11 +- .../modules/fortios_wireless_controller_timers.py | 41 +- .../fortios_wireless_controller_utm_profile.py | 11 +- .../modules/fortios_wireless_controller_vap.py | 191 +- .../fortios_wireless_controller_vap_group.py | 9 +- .../fortios_wireless_controller_vap_status.py | 15 +- .../fortios_wireless_controller_wag_profile.py | 11 +- .../fortios_wireless_controller_wids_profile.py | 11 +- .../modules/fortios_wireless_controller_wtp.py | 50 +- .../fortios_wireless_controller_wtp_group.py | 19 +- .../fortios_wireless_controller_wtp_profile.py | 306 +- .../fortios_wireless_controller_wtp_status.py | 15 +- .../infinidat/infinibox/CHANGELOG.rst | 49 +- ansible_collections/infinidat/infinibox/FILES.json | 132 +- .../infinidat/infinibox/MANIFEST.json | 8 +- ansible_collections/infinidat/infinibox/README.md | 12 +- .../infinidat/infinibox/ibox_vars/iboxCICD.yaml | 166 +- .../infinibox/ibox_vars/iboxNNNN_example.yaml | 59 +- .../infinidat/infinibox/ibox_vars/vibox.yaml | 283 +- .../infinibox/playbooks/configure_array.yml | 134 +- .../plugins/modules/infini_infinimetrics.py | 358 ++ .../plugins/modules/infini_notification_rule.py | 41 +- .../infinibox/plugins/modules/infini_pool.py | 68 +- .../tests/hacking/infini_infinimetrics_absent.json | 14 + .../hacking/infini_infinimetrics_present.json | 17 + .../infini_notification_rule_absent_1521.json | 9 + .../infini_notification_rule_absent_vibox.json | 9 + .../hacking/infini_notification_rule_present.json | 4 +- .../infini_notification_rule_present_1521.json | 13 + .../infini_notification_rule_present_vibox.json | 13 + .../tests/hacking/infini_pool_absent.json | 9 + .../tests/hacking/infini_pool_present.json | 15 + .../infinibox/tests/hacking/infini_pool_stat.json | 9 + .../tests/hacking/infini_sso_present_1521.json | 15 + .../tests/hacking/infini_sso_present_vibox.json | 15 + ansible_collections/netapp/ontap/CHANGELOG.rst | 18 + ansible_collections/netapp/ontap/FILES.json | 151 +- ansible_collections/netapp/ontap/MANIFEST.json | 4 +- ansible_collections/netapp/ontap/README.md | 14 + .../netapp/ontap/changelogs/.DS_Store | Bin 6148 -> 0 bytes .../netapp/ontap/changelogs/.plugin-cache.yaml | 391 +- .../netapp/ontap/changelogs/changelog.yaml | 23 + .../ontap/changelogs/fragments/DEVOPS-6356.yaml | 2 + .../ontap/changelogs/fragments/DEVOPS-6691.yaml | 2 + .../ontap/changelogs/fragments/DEVOPS-6715.yaml | 2 + .../ontap/changelogs/fragments/DEVOPS-6721.yaml | 2 + .../ontap/changelogs/fragments/DEVOPS-6747.yaml | 2 + .../ontap/changelogs/fragments/DEVOPS-6807.yaml | 2 + .../ontap/changelogs/fragments/DEVOPS-6825.yaml | 2 + .../netapp/ontap/plugins/module_utils/netapp.py | 2 +- .../netapp/ontap/plugins/modules/na_ontap_cifs.py | 20 +- .../netapp/ontap/plugins/modules/na_ontap_dns.py | 4 +- .../plugins/modules/na_ontap_fpolicy_policy.py | 5 +- .../ontap/plugins/modules/na_ontap_net_ifgrp.py | 2 +- .../ontap/plugins/modules/na_ontap_quotas.py | 22 +- .../plugins/modules/na_ontap_security_config.py | 12 + .../plugins/modules/na_ontap_vserver_audit.py | 113 +- .../unit/plugins/modules/.pytest_cache/.gitignore | 2 - .../plugins/modules/.pytest_cache/CACHEDIR.TAG | 4 - .../unit/plugins/modules/.pytest_cache/README.md | 8 - .../modules/.pytest_cache/v/cache/lastfailed | 3 - .../plugins/modules/.pytest_cache/v/cache/nodeids | 6 - .../plugins/modules/.pytest_cache/v/cache/stepwise | 1 - .../unit/plugins/modules/test_na_ontap_cifs.py | 26 + .../unit/plugins/modules/test_na_ontap_quotas.py | 55 +- .../modules/test_na_ontap_security_config.py | 14 +- .../plugins/modules/test_na_ontap_vserver_audit.py | 91 +- .../purestorage/flashblade/CHANGELOG.rst | 16 +- .../purestorage/flashblade/FILES.json | 44 +- .../purestorage/flashblade/MANIFEST.json | 4 +- .../flashblade/changelogs/.plugin-cache.yaml | 2 +- .../flashblade/changelogs/changelog.yaml | 18 +- .../changelogs/fragments/270_add_go.yaml | 2 + .../changelogs/fragments/271_add_worm.yaml | 2 + .../changelogs/fragments/273_add_nap.yaml | 3 + .../changelogs/fragments/274_fan_in.yaml | 2 + .../flashblade/plugins/modules/purefb_bucket.py | 108 +- .../flashblade/plugins/modules/purefb_connect.py | 10 +- .../flashblade/plugins/modules/purefb_fs.py | 48 +- .../flashblade/plugins/modules/purefb_info.py | 5 + .../flashblade/plugins/modules/purefb_policy.py | 391 +- build-ansible.sh | 4 +- porting_guide_9.rst | 37 + setup.cfg | 10 +- tags.yaml | 96 +- 2967 files changed, 133338 insertions(+), 32281 deletions(-) create mode 100644 ansible_collections/amazon/aws/tests/integration/targets/inventory_aws_ec2/templates/config.ini.j2 create mode 100644 ansible_collections/amazon/aws/tests/unit/module_utils/iam/test_iam_resource_transforms.py create mode 100644 ansible_collections/amazon/aws/tests/unit/module_utils/transformation/test_boto3_resource_to_ansible_dict.py create mode 100644 ansible_collections/cisco/aci/plugins/filter/listify.py create mode 100644 ansible_collections/cisco/aci/plugins/module_utils/annotation_unsupported.py create mode 100644 ansible_collections/cisco/aci/plugins/modules/aci_aaa_certificate_authority.py create mode 100644 ansible_collections/cisco/aci/plugins/modules/aci_aaa_key_ring.py create mode 100644 ansible_collections/cisco/aci/plugins/modules/aci_aaa_security_default_settings.py create mode 100644 ansible_collections/cisco/aci/plugins/modules/aci_access_spine_interface_profile.py create mode 100644 ansible_collections/cisco/aci/plugins/modules/aci_access_spine_interface_profile_to_spine_switch_profile.py create mode 100644 ansible_collections/cisco/aci/plugins/modules/aci_access_spine_interface_selector.py create mode 100644 ansible_collections/cisco/aci/plugins/modules/aci_access_spine_switch_profile.py create mode 100644 ansible_collections/cisco/aci/plugins/modules/aci_access_spine_switch_selector.py create mode 100644 ansible_collections/cisco/aci/plugins/modules/aci_access_switch_policy_group.py create mode 100644 ansible_collections/cisco/aci/plugins/modules/aci_action_rule_additional_communities.py create mode 100644 ansible_collections/cisco/aci/plugins/modules/aci_action_rule_set_as_path.py create mode 100644 ansible_collections/cisco/aci/plugins/modules/aci_action_rule_set_as_path_asn.py create mode 100644 ansible_collections/cisco/aci/plugins/modules/aci_bd_rogue_exception_mac.py create mode 100644 ansible_collections/cisco/aci/plugins/modules/aci_bd_to_netflow_monitor_policy.py create mode 100644 ansible_collections/cisco/aci/plugins/modules/aci_bfd_multihop_node_policy.py create mode 100644 ansible_collections/cisco/aci/plugins/modules/aci_bgp_address_family_context_policy.py create mode 100644 ansible_collections/cisco/aci/plugins/modules/aci_bgp_peer_prefix_policy.py create mode 100644 ansible_collections/cisco/aci/plugins/modules/aci_bgp_route_summarization_policy.py create mode 100644 ansible_collections/cisco/aci/plugins/modules/aci_dhcp_option.py create mode 100644 ansible_collections/cisco/aci/plugins/modules/aci_dhcp_option_policy.py create mode 100644 ansible_collections/cisco/aci/plugins/modules/aci_epg_useg_attribute_block_statement.py create mode 100644 ansible_collections/cisco/aci/plugins/modules/aci_epg_useg_attribute_simple_statement.py create mode 100644 ansible_collections/cisco/aci/plugins/modules/aci_fabric_external_connection_profile.py create mode 100644 ansible_collections/cisco/aci/plugins/modules/aci_fabric_external_routing_profile.py create mode 100644 ansible_collections/cisco/aci/plugins/modules/aci_fabric_management_access.py create mode 100644 ansible_collections/cisco/aci/plugins/modules/aci_fabric_management_access_https_cipher.py create mode 100644 ansible_collections/cisco/aci/plugins/modules/aci_fabric_pod.py create mode 100644 ansible_collections/cisco/aci/plugins/modules/aci_fabric_pod_connectivity_profile.py create mode 100644 ansible_collections/cisco/aci/plugins/modules/aci_fabric_pod_external_tep.py create mode 100644 ansible_collections/cisco/aci/plugins/modules/aci_fabric_pod_profile.py create mode 100644 ansible_collections/cisco/aci/plugins/modules/aci_fabric_pod_remote_pool.py create mode 100644 ansible_collections/cisco/aci/plugins/modules/aci_interface_policy_bfd.py create mode 100644 ansible_collections/cisco/aci/plugins/modules/aci_interface_policy_bfd_multihop.py create mode 100644 ansible_collections/cisco/aci/plugins/modules/aci_interface_policy_eigrp.py create mode 100644 ansible_collections/cisco/aci/plugins/modules/aci_interface_policy_hsrp.py create mode 100644 ansible_collections/cisco/aci/plugins/modules/aci_interface_policy_pim.py create mode 100644 ansible_collections/cisco/aci/plugins/modules/aci_interface_policy_storm_control.py create mode 100644 ansible_collections/cisco/aci/plugins/modules/aci_key_policy.py create mode 100644 ansible_collections/cisco/aci/plugins/modules/aci_keychain_policy.py create mode 100644 ansible_collections/cisco/aci/plugins/modules/aci_l3out_bfd_interface_profile.py create mode 100644 ansible_collections/cisco/aci/plugins/modules/aci_l3out_bfd_multihop_interface_profile.py create mode 100644 ansible_collections/cisco/aci/plugins/modules/aci_l3out_dhcp_relay_label.py create mode 100644 ansible_collections/cisco/aci/plugins/modules/aci_l3out_eigrp_interface_profile.py create mode 100644 ansible_collections/cisco/aci/plugins/modules/aci_l3out_floating_svi.py create mode 100644 ansible_collections/cisco/aci/plugins/modules/aci_l3out_floating_svi_path.py create mode 100644 ansible_collections/cisco/aci/plugins/modules/aci_l3out_floating_svi_path_secondary_ip.py create mode 100644 ansible_collections/cisco/aci/plugins/modules/aci_l3out_floating_svi_secondary_ip.py create mode 100644 ansible_collections/cisco/aci/plugins/modules/aci_l3out_hsrp_group.py create mode 100644 ansible_collections/cisco/aci/plugins/modules/aci_l3out_hsrp_interface_profile.py create mode 100644 ansible_collections/cisco/aci/plugins/modules/aci_l3out_hsrp_secondary_vip.py create mode 100644 ansible_collections/cisco/aci/plugins/modules/aci_l3out_to_sr_mpls_infra_l3out.py create mode 100644 ansible_collections/cisco/aci/plugins/modules/aci_netflow_exporter_policy.py create mode 100644 ansible_collections/cisco/aci/plugins/modules/aci_netflow_monitor_policy.py create mode 100644 ansible_collections/cisco/aci/plugins/modules/aci_netflow_monitor_to_exporter.py create mode 100644 ansible_collections/cisco/aci/plugins/modules/aci_netflow_record_policy.py create mode 100644 ansible_collections/cisco/aci/plugins/modules/aci_node_block.py create mode 100644 ansible_collections/cisco/aci/plugins/modules/aci_pim_route_map_entry.py create mode 100644 ansible_collections/cisco/aci/plugins/modules/aci_pim_route_map_policy.py create mode 100644 ansible_collections/cisco/aci/plugins/modules/aci_qos_custom_policy.py create mode 100644 ansible_collections/cisco/aci/plugins/modules/aci_qos_dot1p_class.py create mode 100644 ansible_collections/cisco/aci/plugins/modules/aci_qos_dscp_class.py create mode 100644 ansible_collections/cisco/aci/plugins/modules/aci_subject_label.py create mode 100644 ansible_collections/cisco/aci/plugins/modules/aci_vrf_multicast.py create mode 100644 ansible_collections/cisco/aci/tests/integration/targets/aci_aaa_certificate_authority/aliases create mode 100644 ansible_collections/cisco/aci/tests/integration/targets/aci_aaa_certificate_authority/pki/admin.crt create mode 100644 ansible_collections/cisco/aci/tests/integration/targets/aci_aaa_certificate_authority/tasks/main.yml create mode 100644 ansible_collections/cisco/aci/tests/integration/targets/aci_aaa_key_ring/aliases create mode 100644 ansible_collections/cisco/aci/tests/integration/targets/aci_aaa_key_ring/pki/admin.crt create mode 100644 ansible_collections/cisco/aci/tests/integration/targets/aci_aaa_key_ring/pki/admin.key create mode 100644 ansible_collections/cisco/aci/tests/integration/targets/aci_aaa_key_ring/tasks/main.yml create mode 100644 ansible_collections/cisco/aci/tests/integration/targets/aci_aaa_security_default_settings/aliases create mode 100644 ansible_collections/cisco/aci/tests/integration/targets/aci_aaa_security_default_settings/tasks/main.yml create mode 100644 ansible_collections/cisco/aci/tests/integration/targets/aci_access_spine_interface_profile/aliases create mode 100644 ansible_collections/cisco/aci/tests/integration/targets/aci_access_spine_interface_profile/tasks/main.yml create mode 100644 ansible_collections/cisco/aci/tests/integration/targets/aci_access_spine_interface_profile_to_spine_switch_profile/aliases create mode 100644 ansible_collections/cisco/aci/tests/integration/targets/aci_access_spine_interface_profile_to_spine_switch_profile/tasks/main.yml create mode 100644 ansible_collections/cisco/aci/tests/integration/targets/aci_access_spine_interface_selector/aliases create mode 100644 ansible_collections/cisco/aci/tests/integration/targets/aci_access_spine_interface_selector/tasks/main.yml create mode 100644 ansible_collections/cisco/aci/tests/integration/targets/aci_access_spine_switch_profile/aliases create mode 100644 ansible_collections/cisco/aci/tests/integration/targets/aci_access_spine_switch_profile/tasks/main.yml create mode 100644 ansible_collections/cisco/aci/tests/integration/targets/aci_access_spine_switch_selector/aliases create mode 100644 ansible_collections/cisco/aci/tests/integration/targets/aci_access_spine_switch_selector/tasks/main.yml create mode 100644 ansible_collections/cisco/aci/tests/integration/targets/aci_access_switch_policy_group/aliases create mode 100644 ansible_collections/cisco/aci/tests/integration/targets/aci_access_switch_policy_group/tasks/main.yml create mode 100644 ansible_collections/cisco/aci/tests/integration/targets/aci_action_rule_additional_communities/aliases create mode 100644 ansible_collections/cisco/aci/tests/integration/targets/aci_action_rule_additional_communities/tasks/main.yml create mode 100644 ansible_collections/cisco/aci/tests/integration/targets/aci_action_rule_set_as_path/aliases create mode 100644 ansible_collections/cisco/aci/tests/integration/targets/aci_action_rule_set_as_path/tasks/main.yml create mode 100644 ansible_collections/cisco/aci/tests/integration/targets/aci_action_rule_set_as_path_asn/aliases create mode 100644 ansible_collections/cisco/aci/tests/integration/targets/aci_action_rule_set_as_path_asn/tasks/main.yml create mode 100644 ansible_collections/cisco/aci/tests/integration/targets/aci_bd_rogue_exception_mac/aliases create mode 100644 ansible_collections/cisco/aci/tests/integration/targets/aci_bd_rogue_exception_mac/tasks/main.yml create mode 100644 ansible_collections/cisco/aci/tests/integration/targets/aci_bd_to_netflow_monitor_policy/aliases create mode 100644 ansible_collections/cisco/aci/tests/integration/targets/aci_bd_to_netflow_monitor_policy/tasks/main.yml create mode 100644 ansible_collections/cisco/aci/tests/integration/targets/aci_bfd_multihop_node_policy/aliases create mode 100644 ansible_collections/cisco/aci/tests/integration/targets/aci_bfd_multihop_node_policy/tasks/main.yml create mode 100644 ansible_collections/cisco/aci/tests/integration/targets/aci_bgp_address_family_context_policy/aliases create mode 100644 ansible_collections/cisco/aci/tests/integration/targets/aci_bgp_address_family_context_policy/tasks/main.yml create mode 100644 ansible_collections/cisco/aci/tests/integration/targets/aci_bgp_peer_prefix_policy/aliases create mode 100644 ansible_collections/cisco/aci/tests/integration/targets/aci_bgp_peer_prefix_policy/tasks/main.yml create mode 100644 ansible_collections/cisco/aci/tests/integration/targets/aci_bgp_route_summarization_policy/aliases create mode 100644 ansible_collections/cisco/aci/tests/integration/targets/aci_bgp_route_summarization_policy/tasks/main.yml create mode 100644 ansible_collections/cisco/aci/tests/integration/targets/aci_dhcp_option/aliases create mode 100644 ansible_collections/cisco/aci/tests/integration/targets/aci_dhcp_option/tasks/main.yml create mode 100644 ansible_collections/cisco/aci/tests/integration/targets/aci_dhcp_option_policy/aliases create mode 100644 ansible_collections/cisco/aci/tests/integration/targets/aci_dhcp_option_policy/tasks/main.yml create mode 100644 ansible_collections/cisco/aci/tests/integration/targets/aci_epg_useg_attribute_block_statement/aliases create mode 100644 ansible_collections/cisco/aci/tests/integration/targets/aci_epg_useg_attribute_block_statement/tasks/main.yml create mode 100644 ansible_collections/cisco/aci/tests/integration/targets/aci_epg_useg_attribute_simple_statement/aliases create mode 100644 ansible_collections/cisco/aci/tests/integration/targets/aci_epg_useg_attribute_simple_statement/tasks/main.yml create mode 100644 ansible_collections/cisco/aci/tests/integration/targets/aci_epg_useg_attribute_simple_statement/tasks/simple_block_levels.yml create mode 100644 ansible_collections/cisco/aci/tests/integration/targets/aci_fabric_external_connection_profile/aliases create mode 100644 ansible_collections/cisco/aci/tests/integration/targets/aci_fabric_external_connection_profile/tasks/main.yml create mode 100644 ansible_collections/cisco/aci/tests/integration/targets/aci_fabric_external_routing_profile/aliases create mode 100644 ansible_collections/cisco/aci/tests/integration/targets/aci_fabric_external_routing_profile/tasks/main.yml create mode 100644 ansible_collections/cisco/aci/tests/integration/targets/aci_fabric_management_access/aliases create mode 100644 ansible_collections/cisco/aci/tests/integration/targets/aci_fabric_management_access/pki/admin.crt create mode 100644 ansible_collections/cisco/aci/tests/integration/targets/aci_fabric_management_access/pki/admin.key create mode 100644 ansible_collections/cisco/aci/tests/integration/targets/aci_fabric_management_access/tasks/main.yml create mode 100644 ansible_collections/cisco/aci/tests/integration/targets/aci_fabric_management_access_https_cipher/aliases create mode 100644 ansible_collections/cisco/aci/tests/integration/targets/aci_fabric_management_access_https_cipher/pki/admin.crt create mode 100644 ansible_collections/cisco/aci/tests/integration/targets/aci_fabric_management_access_https_cipher/pki/admin.key create mode 100644 ansible_collections/cisco/aci/tests/integration/targets/aci_fabric_management_access_https_cipher/tasks/main.yml create mode 100644 ansible_collections/cisco/aci/tests/integration/targets/aci_fabric_pod/aliases create mode 100644 ansible_collections/cisco/aci/tests/integration/targets/aci_fabric_pod/tasks/main.yml create mode 100644 ansible_collections/cisco/aci/tests/integration/targets/aci_fabric_pod_connectivity_profile/aliases create mode 100644 ansible_collections/cisco/aci/tests/integration/targets/aci_fabric_pod_connectivity_profile/tasks/main.yml create mode 100644 ansible_collections/cisco/aci/tests/integration/targets/aci_fabric_pod_external_tep/aliases create mode 100644 ansible_collections/cisco/aci/tests/integration/targets/aci_fabric_pod_external_tep/tasks/main.yml create mode 100644 ansible_collections/cisco/aci/tests/integration/targets/aci_fabric_pod_profile/aliases create mode 100644 ansible_collections/cisco/aci/tests/integration/targets/aci_fabric_pod_profile/tasks/main.yml create mode 100644 ansible_collections/cisco/aci/tests/integration/targets/aci_fabric_pod_remote_pool/aliases create mode 100644 ansible_collections/cisco/aci/tests/integration/targets/aci_fabric_pod_remote_pool/tasks/main.yml create mode 100644 ansible_collections/cisco/aci/tests/integration/targets/aci_filter_listify/aliases create mode 100644 ansible_collections/cisco/aci/tests/integration/targets/aci_filter_listify/tasks/main.yml create mode 100644 ansible_collections/cisco/aci/tests/integration/targets/aci_interface_policy_bfd/aliases create mode 100644 ansible_collections/cisco/aci/tests/integration/targets/aci_interface_policy_bfd/tasks/main.yml create mode 100644 ansible_collections/cisco/aci/tests/integration/targets/aci_interface_policy_bfd_multihop/aliases create mode 100644 ansible_collections/cisco/aci/tests/integration/targets/aci_interface_policy_bfd_multihop/tasks/main.yml create mode 100644 ansible_collections/cisco/aci/tests/integration/targets/aci_interface_policy_eigrp/aliases create mode 100644 ansible_collections/cisco/aci/tests/integration/targets/aci_interface_policy_eigrp/tasks/main.yml create mode 100644 ansible_collections/cisco/aci/tests/integration/targets/aci_interface_policy_hsrp/aliases create mode 100644 ansible_collections/cisco/aci/tests/integration/targets/aci_interface_policy_hsrp/tasks/main.yml create mode 100644 ansible_collections/cisco/aci/tests/integration/targets/aci_interface_policy_pim/aliases create mode 100644 ansible_collections/cisco/aci/tests/integration/targets/aci_interface_policy_pim/tasks/main.yml create mode 100644 ansible_collections/cisco/aci/tests/integration/targets/aci_interface_policy_storm_control/aliases create mode 100644 ansible_collections/cisco/aci/tests/integration/targets/aci_interface_policy_storm_control/tasks/main.yml create mode 100644 ansible_collections/cisco/aci/tests/integration/targets/aci_key_policy/aliases create mode 100644 ansible_collections/cisco/aci/tests/integration/targets/aci_key_policy/tasks/main.yml create mode 100644 ansible_collections/cisco/aci/tests/integration/targets/aci_keychain_policy/aliases create mode 100644 ansible_collections/cisco/aci/tests/integration/targets/aci_keychain_policy/tasks/main.yml create mode 100644 ansible_collections/cisco/aci/tests/integration/targets/aci_l3out_bfd_interface_profile/aliases create mode 100644 ansible_collections/cisco/aci/tests/integration/targets/aci_l3out_bfd_interface_profile/tasks/main.yml create mode 100644 ansible_collections/cisco/aci/tests/integration/targets/aci_l3out_bfd_multihop_interface_profile/aliases create mode 100644 ansible_collections/cisco/aci/tests/integration/targets/aci_l3out_bfd_multihop_interface_profile/tasks/main.yml create mode 100644 ansible_collections/cisco/aci/tests/integration/targets/aci_l3out_dhcp_relay_label/aliases create mode 100644 ansible_collections/cisco/aci/tests/integration/targets/aci_l3out_dhcp_relay_label/tasks/main.yml create mode 100644 ansible_collections/cisco/aci/tests/integration/targets/aci_l3out_eigrp_interface_profile/aliases create mode 100644 ansible_collections/cisco/aci/tests/integration/targets/aci_l3out_eigrp_interface_profile/tasks/main.yml create mode 100644 ansible_collections/cisco/aci/tests/integration/targets/aci_l3out_floating_svi/aliases create mode 100644 ansible_collections/cisco/aci/tests/integration/targets/aci_l3out_floating_svi/tasks/main.yml create mode 100644 ansible_collections/cisco/aci/tests/integration/targets/aci_l3out_floating_svi_path/aliases create mode 100644 ansible_collections/cisco/aci/tests/integration/targets/aci_l3out_floating_svi_path/tasks/main.yml create mode 100644 ansible_collections/cisco/aci/tests/integration/targets/aci_l3out_floating_svi_path_secondary_ip/aliases create mode 100644 ansible_collections/cisco/aci/tests/integration/targets/aci_l3out_floating_svi_path_secondary_ip/tasks/main.yml create mode 100644 ansible_collections/cisco/aci/tests/integration/targets/aci_l3out_floating_svi_secondary_ip/aliases create mode 100644 ansible_collections/cisco/aci/tests/integration/targets/aci_l3out_floating_svi_secondary_ip/tasks/main.yml create mode 100644 ansible_collections/cisco/aci/tests/integration/targets/aci_l3out_hsrp_group/aliases create mode 100644 ansible_collections/cisco/aci/tests/integration/targets/aci_l3out_hsrp_group/tasks/main.yml create mode 100644 ansible_collections/cisco/aci/tests/integration/targets/aci_l3out_hsrp_interface_profile/aliases create mode 100644 ansible_collections/cisco/aci/tests/integration/targets/aci_l3out_hsrp_interface_profile/tasks/main.yml create mode 100644 ansible_collections/cisco/aci/tests/integration/targets/aci_l3out_hsrp_secondary_vip/aliases create mode 100644 ansible_collections/cisco/aci/tests/integration/targets/aci_l3out_hsrp_secondary_vip/tasks/main.yml create mode 100644 ansible_collections/cisco/aci/tests/integration/targets/aci_l3out_to_sr_mpls_infra_l3out/aliases create mode 100644 ansible_collections/cisco/aci/tests/integration/targets/aci_l3out_to_sr_mpls_infra_l3out/tasks/main.yml create mode 100644 ansible_collections/cisco/aci/tests/integration/targets/aci_netflow_exporter_policy/aliases create mode 100644 ansible_collections/cisco/aci/tests/integration/targets/aci_netflow_exporter_policy/tasks/main.yml create mode 100644 ansible_collections/cisco/aci/tests/integration/targets/aci_netflow_monitor_policy/aliases create mode 100644 ansible_collections/cisco/aci/tests/integration/targets/aci_netflow_monitor_policy/tasks/main.yml create mode 100644 ansible_collections/cisco/aci/tests/integration/targets/aci_netflow_monitor_to_exporter/aliases create mode 100644 ansible_collections/cisco/aci/tests/integration/targets/aci_netflow_monitor_to_exporter/tasks/main.yml create mode 100644 ansible_collections/cisco/aci/tests/integration/targets/aci_netflow_record_policy/aliases create mode 100644 ansible_collections/cisco/aci/tests/integration/targets/aci_netflow_record_policy/tasks/main.yml create mode 100644 ansible_collections/cisco/aci/tests/integration/targets/aci_node_block/aliases create mode 100644 ansible_collections/cisco/aci/tests/integration/targets/aci_node_block/tasks/main.yml create mode 100644 ansible_collections/cisco/aci/tests/integration/targets/aci_pim_route_map_entry/aliases create mode 100644 ansible_collections/cisco/aci/tests/integration/targets/aci_pim_route_map_entry/tasks/main.yml create mode 100644 ansible_collections/cisco/aci/tests/integration/targets/aci_pim_route_map_policy/aliases create mode 100644 ansible_collections/cisco/aci/tests/integration/targets/aci_pim_route_map_policy/tasks/main.yml create mode 100644 ansible_collections/cisco/aci/tests/integration/targets/aci_qos_custom_policy/aliases create mode 100644 ansible_collections/cisco/aci/tests/integration/targets/aci_qos_custom_policy/tasks/main.yml create mode 100644 ansible_collections/cisco/aci/tests/integration/targets/aci_qos_dot1p_class/aliases create mode 100644 ansible_collections/cisco/aci/tests/integration/targets/aci_qos_dot1p_class/tasks/main.yml create mode 100644 ansible_collections/cisco/aci/tests/integration/targets/aci_qos_dscp_class/aliases create mode 100644 ansible_collections/cisco/aci/tests/integration/targets/aci_qos_dscp_class/tasks/main.yml create mode 100644 ansible_collections/cisco/aci/tests/integration/targets/aci_rest/tasks/xml_files/tag.xml create mode 100644 ansible_collections/cisco/aci/tests/integration/targets/aci_rest/tasks/xml_files/tn-ans_test_annotation.xml create mode 100644 ansible_collections/cisco/aci/tests/integration/targets/aci_rest/tasks/xml_files/tn-ans_test_annotation_children.xml create mode 100644 ansible_collections/cisco/aci/tests/integration/targets/aci_subject_label/aliases create mode 100644 ansible_collections/cisco/aci/tests/integration/targets/aci_subject_label/tasks/main.yml create mode 100644 ansible_collections/cisco/aci/tests/integration/targets/aci_subject_label/tasks/subject_label.yml create mode 100644 ansible_collections/cisco/aci/tests/integration/targets/aci_vrf_multicast/aliases create mode 100644 ansible_collections/cisco/aci/tests/integration/targets/aci_vrf_multicast/tasks/main.yml create mode 100644 ansible_collections/cisco/dnac/.github/workflows/sanity_tests_devel.yml delete mode 100644 ansible_collections/cisco/ise/.DS_Store delete mode 100644 ansible_collections/cisco/ise/.vscode/launch.json delete mode 100644 ansible_collections/cisco/ise/.vscode/settings.json create mode 100644 ansible_collections/cisco/ise/Pipfile delete mode 100644 ansible_collections/cisco/ise/plugins/.DS_Store delete mode 100644 ansible_collections/cisco/meraki/.vscode/settings.json create mode 100644 ansible_collections/cisco/meraki/plugins/action/administered_licensing_subscription_entitlements_info.py create mode 100644 ansible_collections/cisco/meraki/plugins/action/administered_licensing_subscription_subscriptions_bind.py create mode 100644 ansible_collections/cisco/meraki/plugins/action/administered_licensing_subscription_subscriptions_claim.py create mode 100644 ansible_collections/cisco/meraki/plugins/action/administered_licensing_subscription_subscriptions_claim_key_validate.py create mode 100644 ansible_collections/cisco/meraki/plugins/action/administered_licensing_subscription_subscriptions_compliance_statuses_info.py create mode 100644 ansible_collections/cisco/meraki/plugins/action/administered_licensing_subscription_subscriptions_info.py create mode 100644 ansible_collections/cisco/meraki/plugins/action/devices_appliance_radio_settings.py create mode 100644 ansible_collections/cisco/meraki/plugins/action/devices_appliance_radio_settings_info.py create mode 100644 ansible_collections/cisco/meraki/plugins/action/devices_live_tools_arp_table.py create mode 100644 ansible_collections/cisco/meraki/plugins/action/devices_live_tools_arp_table_info.py create mode 100644 ansible_collections/cisco/meraki/plugins/action/devices_live_tools_cable_test.py create mode 100644 ansible_collections/cisco/meraki/plugins/action/devices_live_tools_cable_test_info.py create mode 100644 ansible_collections/cisco/meraki/plugins/action/devices_live_tools_throughput_test.py create mode 100644 ansible_collections/cisco/meraki/plugins/action/devices_live_tools_throughput_test_info.py create mode 100644 ansible_collections/cisco/meraki/plugins/action/devices_live_tools_wake_on_lan.py create mode 100644 ansible_collections/cisco/meraki/plugins/action/devices_live_tools_wake_on_lan_info.py create mode 100644 ansible_collections/cisco/meraki/plugins/action/devices_wireless_alternate_management_interface_ipv6.py create mode 100644 ansible_collections/cisco/meraki/plugins/action/networks_appliance_rf_profiles.py create mode 100644 ansible_collections/cisco/meraki/plugins/action/networks_appliance_rf_profiles_info.py create mode 100644 ansible_collections/cisco/meraki/plugins/action/networks_appliance_traffic_shaping_vpn_exclusions.py create mode 100644 ansible_collections/cisco/meraki/plugins/action/networks_sm_devices_install_apps.py create mode 100644 ansible_collections/cisco/meraki/plugins/action/networks_sm_devices_reboot.py create mode 100644 ansible_collections/cisco/meraki/plugins/action/networks_sm_devices_shutdown.py create mode 100644 ansible_collections/cisco/meraki/plugins/action/networks_sm_devices_uninstall_apps.py create mode 100644 ansible_collections/cisco/meraki/plugins/action/networks_vlan_profiles.py create mode 100644 ansible_collections/cisco/meraki/plugins/action/networks_vlan_profiles_assignments_by_device_info.py create mode 100644 ansible_collections/cisco/meraki/plugins/action/networks_vlan_profiles_assignments_reassign.py create mode 100644 ansible_collections/cisco/meraki/plugins/action/networks_vlan_profiles_info.py create mode 100644 ansible_collections/cisco/meraki/plugins/action/networks_wireless_ethernet_ports_profiles.py create mode 100644 ansible_collections/cisco/meraki/plugins/action/networks_wireless_ethernet_ports_profiles_assign.py create mode 100644 ansible_collections/cisco/meraki/plugins/action/networks_wireless_ethernet_ports_profiles_info.py create mode 100644 ansible_collections/cisco/meraki/plugins/action/networks_wireless_ethernet_ports_profiles_set_default.py create mode 100644 ansible_collections/cisco/meraki/plugins/action/organizations_appliance_traffic_shaping_vpn_exclusions_by_network_info.py create mode 100644 ansible_collections/cisco/meraki/plugins/action/organizations_appliance_uplinks_statuses_overview_info.py create mode 100644 ansible_collections/cisco/meraki/plugins/action/organizations_appliance_uplinks_usage_by_network_info.py create mode 100644 ansible_collections/cisco/meraki/plugins/action/organizations_camera_boundaries_areas_by_device_info.py create mode 100644 ansible_collections/cisco/meraki/plugins/action/organizations_camera_boundaries_lines_by_device_info.py create mode 100644 ansible_collections/cisco/meraki/plugins/action/organizations_camera_detections_history_by_boundary_by_interval_info.py create mode 100644 ansible_collections/cisco/meraki/plugins/action/organizations_camera_permissions_info.py create mode 100644 ansible_collections/cisco/meraki/plugins/action/organizations_camera_roles.py create mode 100644 ansible_collections/cisco/meraki/plugins/action/organizations_camera_roles_info.py create mode 100644 ansible_collections/cisco/meraki/plugins/action/organizations_devices_availabilities_change_history_info.py create mode 100644 ansible_collections/cisco/meraki/plugins/action/organizations_devices_boots_history_info.py create mode 100644 ansible_collections/cisco/meraki/plugins/action/organizations_sm_admins_roles.py create mode 100644 ansible_collections/cisco/meraki/plugins/action/organizations_sm_admins_roles_info.py create mode 100644 ansible_collections/cisco/meraki/plugins/action/organizations_sm_sentry_policies_assignments.py create mode 100644 ansible_collections/cisco/meraki/plugins/action/organizations_sm_sentry_policies_assignments_by_network_info.py create mode 100644 ansible_collections/cisco/meraki/plugins/action/organizations_summary_top_networks_by_status_info.py create mode 100644 ansible_collections/cisco/meraki/plugins/action/organizations_webhooks_callbacks_statuses_info.py create mode 100644 ansible_collections/cisco/meraki/plugins/action/organizations_wireless_devices_channel_utilization_by_device_info.py create mode 100644 ansible_collections/cisco/meraki/plugins/action/organizations_wireless_devices_channel_utilization_by_network_info.py create mode 100644 ansible_collections/cisco/meraki/plugins/action/organizations_wireless_devices_channel_utilization_history_by_device_by_interval_info.py create mode 100644 ansible_collections/cisco/meraki/plugins/action/organizations_wireless_devices_channel_utilization_history_by_network_by_interval_info.py create mode 100644 ansible_collections/cisco/meraki/plugins/action/organizations_wireless_devices_packet_loss_by_client_info.py create mode 100644 ansible_collections/cisco/meraki/plugins/action/organizations_wireless_devices_packet_loss_by_device_info.py create mode 100644 ansible_collections/cisco/meraki/plugins/action/organizations_wireless_devices_packet_loss_by_network_info.py create mode 100644 ansible_collections/cisco/meraki/plugins/modules/administered_licensing_subscription_entitlements_info.py create mode 100644 ansible_collections/cisco/meraki/plugins/modules/administered_licensing_subscription_subscriptions_bind.py create mode 100644 ansible_collections/cisco/meraki/plugins/modules/administered_licensing_subscription_subscriptions_claim.py create mode 100644 ansible_collections/cisco/meraki/plugins/modules/administered_licensing_subscription_subscriptions_claim_key_validate.py create mode 100644 ansible_collections/cisco/meraki/plugins/modules/administered_licensing_subscription_subscriptions_compliance_statuses_info.py create mode 100644 ansible_collections/cisco/meraki/plugins/modules/administered_licensing_subscription_subscriptions_info.py create mode 100644 ansible_collections/cisco/meraki/plugins/modules/devices_appliance_radio_settings.py create mode 100644 ansible_collections/cisco/meraki/plugins/modules/devices_appliance_radio_settings_info.py create mode 100644 ansible_collections/cisco/meraki/plugins/modules/devices_live_tools_arp_table.py create mode 100644 ansible_collections/cisco/meraki/plugins/modules/devices_live_tools_arp_table_info.py create mode 100644 ansible_collections/cisco/meraki/plugins/modules/devices_live_tools_cable_test.py create mode 100644 ansible_collections/cisco/meraki/plugins/modules/devices_live_tools_cable_test_info.py create mode 100644 ansible_collections/cisco/meraki/plugins/modules/devices_live_tools_throughput_test.py create mode 100644 ansible_collections/cisco/meraki/plugins/modules/devices_live_tools_throughput_test_info.py create mode 100644 ansible_collections/cisco/meraki/plugins/modules/devices_live_tools_wake_on_lan.py create mode 100644 ansible_collections/cisco/meraki/plugins/modules/devices_live_tools_wake_on_lan_info.py create mode 100644 ansible_collections/cisco/meraki/plugins/modules/devices_wireless_alternate_management_interface_ipv6.py create mode 100644 ansible_collections/cisco/meraki/plugins/modules/networks_appliance_rf_profiles.py create mode 100644 ansible_collections/cisco/meraki/plugins/modules/networks_appliance_rf_profiles_info.py create mode 100644 ansible_collections/cisco/meraki/plugins/modules/networks_appliance_traffic_shaping_vpn_exclusions.py create mode 100644 ansible_collections/cisco/meraki/plugins/modules/networks_sm_devices_install_apps.py create mode 100644 ansible_collections/cisco/meraki/plugins/modules/networks_sm_devices_reboot.py create mode 100644 ansible_collections/cisco/meraki/plugins/modules/networks_sm_devices_shutdown.py create mode 100644 ansible_collections/cisco/meraki/plugins/modules/networks_sm_devices_uninstall_apps.py create mode 100644 ansible_collections/cisco/meraki/plugins/modules/networks_vlan_profiles.py create mode 100644 ansible_collections/cisco/meraki/plugins/modules/networks_vlan_profiles_assignments_by_device_info.py create mode 100644 ansible_collections/cisco/meraki/plugins/modules/networks_vlan_profiles_assignments_reassign.py create mode 100644 ansible_collections/cisco/meraki/plugins/modules/networks_vlan_profiles_info.py create mode 100644 ansible_collections/cisco/meraki/plugins/modules/networks_wireless_ethernet_ports_profiles.py create mode 100644 ansible_collections/cisco/meraki/plugins/modules/networks_wireless_ethernet_ports_profiles_assign.py create mode 100644 ansible_collections/cisco/meraki/plugins/modules/networks_wireless_ethernet_ports_profiles_info.py create mode 100644 ansible_collections/cisco/meraki/plugins/modules/networks_wireless_ethernet_ports_profiles_set_default.py create mode 100644 ansible_collections/cisco/meraki/plugins/modules/organizations_appliance_traffic_shaping_vpn_exclusions_by_network_info.py create mode 100644 ansible_collections/cisco/meraki/plugins/modules/organizations_appliance_uplinks_statuses_overview_info.py create mode 100644 ansible_collections/cisco/meraki/plugins/modules/organizations_appliance_uplinks_usage_by_network_info.py create mode 100644 ansible_collections/cisco/meraki/plugins/modules/organizations_camera_boundaries_areas_by_device_info.py create mode 100644 ansible_collections/cisco/meraki/plugins/modules/organizations_camera_boundaries_lines_by_device_info.py create mode 100644 ansible_collections/cisco/meraki/plugins/modules/organizations_camera_detections_history_by_boundary_by_interval_info.py create mode 100644 ansible_collections/cisco/meraki/plugins/modules/organizations_camera_permissions_info.py create mode 100644 ansible_collections/cisco/meraki/plugins/modules/organizations_camera_roles.py create mode 100644 ansible_collections/cisco/meraki/plugins/modules/organizations_camera_roles_info.py create mode 100644 ansible_collections/cisco/meraki/plugins/modules/organizations_devices_availabilities_change_history_info.py create mode 100644 ansible_collections/cisco/meraki/plugins/modules/organizations_devices_boots_history_info.py create mode 100644 ansible_collections/cisco/meraki/plugins/modules/organizations_sm_admins_roles.py create mode 100644 ansible_collections/cisco/meraki/plugins/modules/organizations_sm_admins_roles_info.py create mode 100644 ansible_collections/cisco/meraki/plugins/modules/organizations_sm_sentry_policies_assignments.py create mode 100644 ansible_collections/cisco/meraki/plugins/modules/organizations_sm_sentry_policies_assignments_by_network_info.py create mode 100644 ansible_collections/cisco/meraki/plugins/modules/organizations_summary_top_networks_by_status_info.py create mode 100644 ansible_collections/cisco/meraki/plugins/modules/organizations_webhooks_callbacks_statuses_info.py create mode 100644 ansible_collections/cisco/meraki/plugins/modules/organizations_wireless_devices_channel_utilization_by_device_info.py create mode 100644 ansible_collections/cisco/meraki/plugins/modules/organizations_wireless_devices_channel_utilization_by_network_info.py create mode 100644 ansible_collections/cisco/meraki/plugins/modules/organizations_wireless_devices_channel_utilization_history_by_device_by_interval_info.py create mode 100644 ansible_collections/cisco/meraki/plugins/modules/organizations_wireless_devices_channel_utilization_history_by_network_by_interval_info.py create mode 100644 ansible_collections/cisco/meraki/plugins/modules/organizations_wireless_devices_packet_loss_by_client_info.py create mode 100644 ansible_collections/cisco/meraki/plugins/modules/organizations_wireless_devices_packet_loss_by_device_info.py create mode 100644 ansible_collections/cisco/meraki/plugins/modules/organizations_wireless_devices_packet_loss_by_network_info.py create mode 100644 ansible_collections/cisco/mso/plugins/modules/mso_schema_site_contract_service_graph.py create mode 100644 ansible_collections/cisco/mso/plugins/modules/mso_schema_site_contract_service_graph_listener.py create mode 100644 ansible_collections/cisco/mso/tests/integration/targets/mso_schema_site_contract_service_graph/aliases create mode 100644 ansible_collections/cisco/mso/tests/integration/targets/mso_schema_site_contract_service_graph/tasks/l4_l7_devices.yml create mode 100644 ansible_collections/cisco/mso/tests/integration/targets/mso_schema_site_contract_service_graph/tasks/main.yml create mode 100644 ansible_collections/cisco/mso/tests/integration/targets/mso_schema_site_contract_service_graph_listener/aliases create mode 100644 ansible_collections/cisco/mso/tests/integration/targets/mso_schema_site_contract_service_graph_listener/tasks/l4_l7_devices.yml create mode 100644 ansible_collections/cisco/mso/tests/integration/targets/mso_schema_site_contract_service_graph_listener/tasks/main.yml create mode 100644 ansible_collections/cisco/mso/tests/integration/targets/mso_schema_site_contract_service_graph_listener/tasks/pki/admin.crt create mode 100644 ansible_collections/cisco/mso/tests/integration/targets/mso_schema_site_service_graph/tasks/l4_l7_devices.yml create mode 100644 ansible_collections/community/aws/plugins/modules/dynamodb_table_info.py create mode 100644 ansible_collections/community/crypto/docs/docsite/config.yml create mode 100644 ansible_collections/community/crypto/plugins/modules/x509_certificate_convert.py create mode 100644 ansible_collections/community/crypto/tests/integration/targets/x509_certificate_convert/aliases create mode 100644 ansible_collections/community/crypto/tests/integration/targets/x509_certificate_convert/meta/main.yml create mode 100644 ansible_collections/community/crypto/tests/integration/targets/x509_certificate_convert/tasks/impl.yml create mode 100644 ansible_collections/community/crypto/tests/integration/targets/x509_certificate_convert/tasks/main.yml create mode 100644 ansible_collections/community/crypto/tests/sanity/ignore-2.18.txt create mode 100644 ansible_collections/community/crypto/tests/sanity/ignore-2.18.txt.license create mode 100644 ansible_collections/community/dns/docs/docsite/config.yml create mode 100644 ansible_collections/community/dns/plugins/filter/quote_txt.yml create mode 100644 ansible_collections/community/dns/plugins/filter/txt.py create mode 100644 ansible_collections/community/dns/plugins/filter/unquote_txt.yml create mode 100644 ansible_collections/community/dns/plugins/plugin_utils/unsafe.py create mode 100644 ansible_collections/community/dns/tests/integration/targets/filter_txt/aliases create mode 100644 ansible_collections/community/dns/tests/integration/targets/filter_txt/tasks/main.yml create mode 100644 ansible_collections/community/dns/tests/sanity/ignore-2.18.txt create mode 100644 ansible_collections/community/dns/tests/sanity/ignore-2.18.txt.license create mode 100644 ansible_collections/community/docker/plugins/plugin_utils/unsafe.py create mode 100644 ansible_collections/community/docker/tests/integration/targets/docker_compose_v2/tasks/tests/definition.yml create mode 100644 ansible_collections/community/docker/tests/sanity/ignore-2.18.txt create mode 100644 ansible_collections/community/docker/tests/sanity/ignore-2.18.txt.license create mode 100644 ansible_collections/community/general/docs/docsite/config.yml create mode 100644 ansible_collections/community/general/plugins/module_utils/datetime.py create mode 100644 ansible_collections/community/general/plugins/modules/keycloak_client_rolescope.py create mode 100644 ansible_collections/community/general/plugins/plugin_utils/unsafe.py create mode 100644 ansible_collections/community/general/tests/integration/targets/ini_file/tasks/tests/08-section.yml create mode 100644 ansible_collections/community/general/tests/integration/targets/keycloak_client_rolescope/README.md create mode 100644 ansible_collections/community/general/tests/integration/targets/keycloak_client_rolescope/aliases create mode 100644 ansible_collections/community/general/tests/integration/targets/keycloak_client_rolescope/tasks/main.yml create mode 100644 ansible_collections/community/general/tests/integration/targets/keycloak_client_rolescope/vars/main.yml create mode 100644 ansible_collections/community/general/tests/sanity/ignore-2.18.txt create mode 100644 ansible_collections/community/general/tests/sanity/ignore-2.18.txt.license create mode 100644 ansible_collections/community/hrobot/docs/docsite/config.yml create mode 100644 ansible_collections/community/hrobot/plugins/plugin_utils/unsafe.py create mode 100644 ansible_collections/community/hrobot/tests/sanity/ignore-2.18.txt create mode 100644 ansible_collections/community/hrobot/tests/sanity/ignore-2.18.txt.license create mode 100644 ansible_collections/community/library_inventory_filtering_v1/.github/workflows/docs-pr.yml create mode 100644 ansible_collections/community/library_inventory_filtering_v1/.github/workflows/docs-push.yml create mode 100644 ansible_collections/community/library_inventory_filtering_v1/CHANGELOG.md create mode 100644 ansible_collections/community/library_inventory_filtering_v1/CHANGELOG.md.license create mode 100644 ansible_collections/community/library_inventory_filtering_v1/docs/docsite/config.yml create mode 100644 ansible_collections/community/library_inventory_filtering_v1/docs/docsite/extra-docs.yml create mode 100644 ansible_collections/community/library_inventory_filtering_v1/docs/docsite/links.yml create mode 100644 ansible_collections/community/library_inventory_filtering_v1/docs/docsite/rst/usage_guide.rst create mode 100644 ansible_collections/community/rabbitmq/tests/integration/targets/rabbitmq_user/tasks/tests_api.yml delete mode 100644 ansible_collections/community/rabbitmq/tests/sanity/ignore-2.10.txt delete mode 100644 ansible_collections/community/rabbitmq/tests/sanity/ignore-2.11.txt create mode 100644 ansible_collections/community/rabbitmq/tests/sanity/ignore-2.16.txt create mode 100644 ansible_collections/community/rabbitmq/tests/sanity/ignore-2.17.txt delete mode 100644 ansible_collections/community/rabbitmq/tests/sanity/ignore-2.9.txt delete mode 100644 ansible_collections/community/rabbitmq/tests/sanity/ignore.txt create mode 100644 ansible_collections/community/routeros/docs/docsite/config.yml create mode 100644 ansible_collections/community/routeros/tests/sanity/ignore-2.18.txt create mode 100644 ansible_collections/community/routeros/tests/sanity/ignore-2.18.txt.license delete mode 100644 ansible_collections/community/vmware/docs/docsite/rst/scenario_guide.rst delete mode 100644 ansible_collections/community/vmware/docs/docsite/rst/vmware_scenarios/faq.rst delete mode 100644 ansible_collections/community/vmware/docs/docsite/rst/vmware_scenarios/scenario_clone_template.rst delete mode 100644 ansible_collections/community/vmware/docs/docsite/rst/vmware_scenarios/scenario_find_vm_folder.rst delete mode 100644 ansible_collections/community/vmware/docs/docsite/rst/vmware_scenarios/scenario_remove_vm.rst delete mode 100644 ansible_collections/community/vmware/docs/docsite/rst/vmware_scenarios/scenario_rename_vm.rst delete mode 100644 ansible_collections/community/vmware/docs/docsite/rst/vmware_scenarios/scenario_vmware_http.rst delete mode 100644 ansible_collections/community/vmware/docs/docsite/rst/vmware_scenarios/scenario_vmware_tools_connection.rst delete mode 100644 ansible_collections/community/vmware/docs/docsite/rst/vmware_scenarios/vmware_concepts.rst delete mode 100644 ansible_collections/community/vmware/docs/docsite/rst/vmware_scenarios/vmware_external_doc_links.rst delete mode 100644 ansible_collections/community/vmware/docs/docsite/rst/vmware_scenarios/vmware_getting_started.rst delete mode 100644 ansible_collections/community/vmware/docs/docsite/rst/vmware_scenarios/vmware_intro.rst delete mode 100644 ansible_collections/community/vmware/docs/docsite/rst/vmware_scenarios/vmware_inventory.rst delete mode 100644 ansible_collections/community/vmware/docs/docsite/rst/vmware_scenarios/vmware_inventory_filters.rst delete mode 100644 ansible_collections/community/vmware/docs/docsite/rst/vmware_scenarios/vmware_inventory_hostnames.rst delete mode 100644 ansible_collections/community/vmware/docs/docsite/rst/vmware_scenarios/vmware_inventory_vm_attributes.rst delete mode 100644 ansible_collections/community/vmware/docs/docsite/rst/vmware_scenarios/vmware_module_reference.rst delete mode 100644 ansible_collections/community/vmware/docs/docsite/rst/vmware_scenarios/vmware_requirements.rst delete mode 100644 ansible_collections/community/vmware/docs/docsite/rst/vmware_scenarios/vmware_scenarios.rst delete mode 100644 ansible_collections/community/vmware/docs/docsite/rst/vmware_scenarios/vmware_troubleshooting.rst create mode 100644 ansible_collections/community/vmware/plugins/modules/vmware_all_snapshots_info.py create mode 100644 ansible_collections/community/vmware/tests/sanity/ignore-2.18.txt create mode 100644 ansible_collections/containers/podman/plugins/module_utils/podman/quadlet.py create mode 100644 ansible_collections/containers/podman/tests/integration/targets/podman_play/tasks/files/multi-yaml.yml create mode 100644 ansible_collections/containers/podman/tests/integration/targets/podman_play/tasks/play-multi-yaml.yml create mode 100644 ansible_collections/dellemc/powerflex/docs/modules/resource_group.rst create mode 100644 ansible_collections/dellemc/powerflex/playbooks/modules/resource_group.yml create mode 100644 ansible_collections/dellemc/powerflex/plugins/modules/resource_group.py create mode 100644 ansible_collections/dellemc/powerflex/tests/unit/plugins/module_utils/mock_resource_group_api.py create mode 100644 ansible_collections/dellemc/powerflex/tests/unit/plugins/modules/test_resource_group.py create mode 100644 ansible_collections/fortinet/fortios/plugins/modules/fortios_diameter_filter_profile.py create mode 100644 ansible_collections/fortinet/fortios/plugins/modules/fortios_dlp_exact_data_match.py create mode 100644 ansible_collections/fortinet/fortios/plugins/modules/fortios_system_npu_vlink.py create mode 100644 ansible_collections/fortinet/fortios/plugins/modules/fortios_user_external_identity_provider.py create mode 100644 ansible_collections/fortinet/fortios/plugins/modules/fortios_videofilter_keyword.py create mode 100644 ansible_collections/fortinet/fortios/plugins/modules/fortios_vpn_qkd.py create mode 100644 ansible_collections/infinidat/infinibox/plugins/modules/infini_infinimetrics.py create mode 100644 ansible_collections/infinidat/infinibox/tests/hacking/infini_infinimetrics_absent.json create mode 100644 ansible_collections/infinidat/infinibox/tests/hacking/infini_infinimetrics_present.json create mode 100644 ansible_collections/infinidat/infinibox/tests/hacking/infini_notification_rule_absent_1521.json create mode 100644 ansible_collections/infinidat/infinibox/tests/hacking/infini_notification_rule_absent_vibox.json create mode 100644 ansible_collections/infinidat/infinibox/tests/hacking/infini_notification_rule_present_1521.json create mode 100644 ansible_collections/infinidat/infinibox/tests/hacking/infini_notification_rule_present_vibox.json create mode 100644 ansible_collections/infinidat/infinibox/tests/hacking/infini_pool_absent.json create mode 100644 ansible_collections/infinidat/infinibox/tests/hacking/infini_pool_present.json create mode 100644 ansible_collections/infinidat/infinibox/tests/hacking/infini_pool_stat.json create mode 100644 ansible_collections/infinidat/infinibox/tests/hacking/infini_sso_present_1521.json create mode 100644 ansible_collections/infinidat/infinibox/tests/hacking/infini_sso_present_vibox.json delete mode 100644 ansible_collections/netapp/ontap/changelogs/.DS_Store create mode 100644 ansible_collections/netapp/ontap/changelogs/fragments/DEVOPS-6356.yaml create mode 100644 ansible_collections/netapp/ontap/changelogs/fragments/DEVOPS-6691.yaml create mode 100644 ansible_collections/netapp/ontap/changelogs/fragments/DEVOPS-6715.yaml create mode 100644 ansible_collections/netapp/ontap/changelogs/fragments/DEVOPS-6721.yaml create mode 100644 ansible_collections/netapp/ontap/changelogs/fragments/DEVOPS-6747.yaml create mode 100644 ansible_collections/netapp/ontap/changelogs/fragments/DEVOPS-6807.yaml create mode 100644 ansible_collections/netapp/ontap/changelogs/fragments/DEVOPS-6825.yaml delete mode 100644 ansible_collections/netapp/ontap/tests/unit/plugins/modules/.pytest_cache/.gitignore delete mode 100644 ansible_collections/netapp/ontap/tests/unit/plugins/modules/.pytest_cache/CACHEDIR.TAG delete mode 100644 ansible_collections/netapp/ontap/tests/unit/plugins/modules/.pytest_cache/README.md delete mode 100644 ansible_collections/netapp/ontap/tests/unit/plugins/modules/.pytest_cache/v/cache/lastfailed delete mode 100644 ansible_collections/netapp/ontap/tests/unit/plugins/modules/.pytest_cache/v/cache/nodeids delete mode 100644 ansible_collections/netapp/ontap/tests/unit/plugins/modules/.pytest_cache/v/cache/stepwise create mode 100644 ansible_collections/purestorage/flashblade/changelogs/fragments/270_add_go.yaml create mode 100644 ansible_collections/purestorage/flashblade/changelogs/fragments/271_add_worm.yaml create mode 100644 ansible_collections/purestorage/flashblade/changelogs/fragments/273_add_nap.yaml create mode 100644 ansible_collections/purestorage/flashblade/changelogs/fragments/274_fan_in.yaml diff --git a/CHANGELOG-v9.md b/CHANGELOG-v9.md index 5168c5627..00795de78 100644 --- a/CHANGELOG-v9.md +++ b/CHANGELOG-v9.md @@ -2,136 +2,789 @@ This changelog describes changes since Ansible 8\.0\.0\. -- v9\.4\.0 +- v9\.5\.1 - Release Summary - Ansible\-core - Changed Collections + - Major Changes - Minor Changes - Deprecated Features - - Security Fixes - Bugfixes - New Plugins - New Modules - Unchanged Collections -- v9\.3\.0 +- v9\.4\.0 - Release Summary - - Ansible\-core + - Ansible\-core - Changed Collections - - Major Changes - Minor Changes - Deprecated Features + - Security Fixes - Bugfixes - New Plugins - New Modules - Unchanged Collections -- v9\.2\.0 +- v9\.3\.0 - Release Summary - - Added Collections - Ansible\-core - Changed Collections - Major Changes - Minor Changes - Deprecated Features - - Security Fixes - Bugfixes - - Known Issues - New Plugins - New Modules - Unchanged Collections -- v9\.1\.0 +- v9\.2\.0 - Release Summary - - Ansible\-core + - Added Collections + - Ansible\-core - Changed Collections + - Major Changes - Minor Changes - - Breaking Changes / Porting Guide - - Security Fixes + - Deprecated Features + - Security Fixes - Bugfixes - - Known Issues + - Known Issues - New Plugins - New Modules - Unchanged Collections -- v9\.0\.1 +- v9\.1\.0 - Release Summary - - Ansible\-core + - Ansible\-core + - Changed Collections + - Minor Changes + - Breaking Changes / Porting Guide + - Security Fixes - Bugfixes + - Known Issues + - New Plugins + - New Modules - Unchanged Collections -- v9\.0\.0 +- v9\.0\.1 - Release Summary + - Ansible\-core + - Bugfixes + - Unchanged Collections +- v9\.0\.0 + - Release Summary - Removed Collections - Added Collections - - Ansible\-core + - Ansible\-core - Included Collections - - Major Changes - - Minor Changes + - Major Changes + - Minor Changes - Breaking Changes / Porting Guide - - Deprecated Features + - Deprecated Features - Removed Features \(previously deprecated\) - Security Fixes - - Bugfixes + - Bugfixes - Known Issues - - New Plugins - - New Modules + - New Plugins + - New Modules - New Roles - - Unchanged Collections + - Unchanged Collections + + +## v9\.5\.1 + +- Release Summary +- Ansible\-core +- Changed Collections +- Major Changes + - containers\.podman + - fortinet\.fortios +- Minor Changes + - amazon\.aws + - cisco\.aci + - cisco\.dnac + - cisco\.meraki + - cisco\.mso + - community\.aws + - community\.crypto + - community\.docker + - community\.general + - community\.rabbitmq + - community\.routeros + - community\.vmware + - containers\.podman + - dellemc\.powerflex + - netapp\.ontap + - purestorage\.flashblade +- Deprecated Features + - community\.crypto + - community\.general + - community\.vmware +- Bugfixes + - Ansible\-core + - amazon\.aws + - cisco\.aci + - cisco\.ise + - cisco\.mso + - community\.aws + - community\.crypto + - community\.dns + - community\.docker + - community\.general + - community\.hrobot + - community\.vmware + - containers\.podman + - fortinet\.fortios + - netapp\.ontap +- New Plugins + - Filter +- New Modules + - community\.aws + - community\.crypto + - community\.general + - dellemc\.powerflex +- Unchanged Collections + + +### Release Summary + +Release Date\: 2024\-04\-24 + +[Porting Guide](https\://docs\.ansible\.com/ansible/devel/porting\_guides\.html) + +Please note that this release replaces a mistakenly released 9\.5\.0 that included a breaking change\. The 9\.5\.0 release has been yanked from PyPI and is not part of the official release history\. + + +### Ansible\-core + +Ansible 9\.5\.1 contains ansible\-core version 2\.16\.6\. +This is a newer version than version 2\.16\.5 contained in the previous Ansible release\. + +The changes are reported in the combined changelog below\. + + +### Changed Collections + +If not mentioned explicitly\, the changes are reported in the combined changelog below\. + +| Collection | Ansible 9.4.0 | Ansible 9.5.1 | Notes | +| ---------------------------------------- | ------------- | ------------- | ---------------------------------------------------------------------------------------------------------------------------- | +| amazon.aws | 7.4.0 | 7.5.0 | | +| cisco.aci | 2.8.0 | 2.9.0 | | +| cisco.dnac | 6.13.1 | 6.13.3 | | +| cisco.intersight | 2.0.7 | 2.0.8 | Unfortunately, this collection does not provide changelog data in a format that can be processed by the changelog generator. | +| cisco.ise | 2.8.0 | 2.8.1 | | +| cisco.meraki | 2.17.2 | 2.18.0 | | +| cisco.mso | 2.5.0 | 2.6.0 | | +| community.aws | 7.1.0 | 7.2.0 | | +| community.crypto | 2.18.0 | 2.19.0 | | +| community.dns | 2.8.3 | 2.9.0 | | +| community.docker | 3.8.1 | 3.9.0 | | +| community.general | 8.5.0 | 8.6.0 | | +| community.hrobot | 1.9.1 | 1.9.2 | | +| community.library_inventory_filtering_v1 | 1.0.0 | 1.0.1 | | +| community.mongodb | 1.7.2 | 1.7.3 | There are no changes recorded in the changelog. | +| community.rabbitmq | 1.2.3 | 1.3.0 | | +| community.routeros | 2.14.0 | 2.15.0 | | +| community.vmware | 4.2.0 | 4.3.0 | | +| containers.podman | 1.12.0 | 1.13.0 | | +| dellemc.powerflex | 2.2.0 | 2.3.0 | | +| fortinet.fortios | 2.3.5 | 2.3.6 | | +| infinidat.infinibox | 1.4.3 | 1.4.5 | Unfortunately, this collection does not provide changelog data in a format that can be processed by the changelog generator. | +| netapp.ontap | 22.10.0 | 22.11.0 | | +| purestorage.flashblade | 1.16.0 | 1.17.0 | | + + +### Major Changes + + +#### containers\.podman + +* Add quadlet support for Podman modules + + +#### fortinet\.fortios + +* Add notes for backup modules in the documentation in both monitor and monitor\_fact modules\. +* Supported new FOS versions 7\.4\.2 and 7\.4\.3\, and support data type mac\_address in the collection\. +* Update the documentation for the supported versions from latest to a fix version number\. +* Update the required ansible version to 2\.15\. + + +### Minor Changes + + +#### amazon\.aws + +* iam\_user\_info \- Add login\_profile to return info that is get from a user\, to know if they can login from AWS console \([https\://github\.com/ansible\-collections/amazon\.aws/pull/2012](https\://github\.com/ansible\-collections/amazon\.aws/pull/2012)\)\. +* module\_utils\.iam \- refactored normalization functions to use boto3\_resource\_to\_ansible\_dict\(\) and boto3\_resource\_list\_to\_ansible\_dict\(\) \([https\://github\.com/ansible\-collections/amazon\.aws/pull/2006](https\://github\.com/ansible\-collections/amazon\.aws/pull/2006)\)\. +* module\_utils\.transformations \- add boto3\_resource\_to\_ansible\_dict\(\) and boto3\_resource\_list\_to\_ansible\_dict\(\) helpers \([https\://github\.com/ansible\-collections/amazon\.aws/pull/2006](https\://github\.com/ansible\-collections/amazon\.aws/pull/2006)\)\. + + +#### cisco\.aci + +* Add Authentification option for EIGRP interface profile\. +* Add L3out Floating SVI modules \(aci\_l3out\_floating\_svi\, aci\_l3out\_floating\_svi\_path\, aci\_l3out\_floating\_svi\_path\_secondary\_ip and aci\_l3out\_floating\_svi\_secondary\_ip\) \(\#478\) +* Add No\-verification flag option to reduce the number of API calls\. If true\, a verifying GET will not be sent after a POST update to APIC +* Add access spine interface selector and port block binding in aci\_access\_port\_block\_to\_access\_port +* Add aci\_access\_spine\_interface\_selector module +* Add aci\_action\_rule\_additional\_communities module +* Add aci\_action\_rule\_set\_as\_path and aci\_action\_rule\_set\_as\_path\_asn modules +* Add aci\_bgp\_peer\_prefix\_policy\, aci\_bgp\_route\_summarization\_policy and aci\_bgp\_address\_family\_context\_policy modules +* Add aci\_fabric\_pod\, aci\_fabric\_pod\_external\_tep\, aci\_fabric\_pod\_profile\, aci\_fabric\_pod\_remote\_pool modules \(\#558\) +* Add aci\_hsrp\_interface\_policy\, aci\_l3out\_hsrp\_group\, aci\_l3out\_hsrp\_interface\_profile and aci\_l3out\_hsrp\_secondary\_vip modules \(\#505\) +* Add aci\_interface\_policy\_eigrp \(class\:eigrpIfPol\) module +* Add aci\_interface\_policy\_pim module +* Add aci\_interface\_policy\_storm\_control module +* Add aci\_keychain\_policy and aci\_key\_policy modules +* Add aci\_l3out\_bfd\_multihop\_interface\_profile\, aci\_l3out\_bfd\_interface\_profile\, aci\_interface\_policy\_bfd\_multihop\, aci\_interface\_policy\_bfd and aci\_bfd\_multihop\_node\_policy modules \(\#492\) +* Add aci\_l3out\_dhcp\_relay\_label\, aci\_dhcp\_option\_policy and aci\_dhcp\_option modules +* Add aci\_l3out\_eigrp\_interface\_profile module +* Add aci\_listify filter plugin to flattens nested dictionaries +* Add aci\_netflow\_exporter\_policy module +* Add aci\_netflow\_monitor\_policy and aci\_netflow\_record\_policy modules +* Add aci\_netflow\_monitor\_to\_exporter module +* Add aci\_node\_block module +* Add aci\_pim\_route\_map\_policy and aci\_pim\_route\_map\_entry modules +* Add aci\_qos\_custom\_policy and aci\_qos\_dscp\_class modules +* Add aci\_qos\_dot1p\_class module +* Add action rules attributes to aci\_tenant\_action\_rule\_profile\. +* Add auto to speed attribute options in aci\_interface\_policy\_link\_level module \(\#577\) +* Add missing options to aci\_bd module +* Add modules aci\_bd\_to\_netflow\_monitor\_policy and aci\_bd\_rogue\_exception\_mac \(\#600\) +* Add modules for Fabric External Connection Policies and its childs +* Add option to set delimiter to \_ in aci\_epg\_to\_domain module +* Add qos\_custom\_policy\, pim\_interface\_policy and igmp\_interface\_policy as new child\_classes for aci\_l3out\_logical\_interface\_profile\. +* Add support for annotation in aci\_rest module \(\#437\) +* Add support for block statements in useg attributes with the aci\_epg\_useg\_attribute\_block\_statement module +* Add support for configuration of access switch policy groups with aci\_access\_switch\_policy\_group module +* Add support for configuration of certificate authorities in aci\_aaa\_certificate\_authority +* Add support for configuration of fabric management access policies in aci\_fabric\_management\_access +* Add support for configuration of vrf multicast with aci\_vrf\_multicast module +* Add support for configuring Azure cloud subnets using the aci\_cloud\_subnet module +* Add support for encap scope in aci\_l3out\_interface +* Add support for https ssl cipher configuration in aci\_fabric\_management\_access\_https\_cipher +* Add support for infra l3out nodes bgp\-evpn loopback\, mpls transport loopback and segment id in aci\_l3out\_logical\_node +* Add support for infra sr mpls micro bfd in aci\_l3out\_interface +* Add support for intra epg\, taboo\, and contract interface in aci\_epg\_to\_contract +* Add support for key ring configuration in aci\_aaa\_key\_ring +* Add support for mac and description in aci\_l3out\_interface +* Add support for mpls custom qos policy for infra sr mpls l3outs node profiles in aci\_l3out\_logical\_node\_profile +* Add support for security default settings configuration in aci\_aaa\_security\_default\_settings +* Add support for simple statements in useg attributes with the aci\_epg\_useg\_attribute\_simple\_statement module +* Add support for sr\-mpls bgpInfraPeerP and bgp\_password in aci\_l3out\_bgp\_peer module \(\#543\) +* Add support for sr\-mpls in aci\_l3out module +* Add support for sr\-mpls l3out to infra l3out in aci\_l3out\_to\_sr\_mpls\_infra\_l3out +* Add support for subject labels for EPG\, EPG Contract\, ESG\, Contract Subject\, L2Out External EPG\, L3out External EPG\, and L3out External EPG Contract with the aci\_subject\_label module +* Add support for taboo contract\, contract interface and intra\_epg contract in aci\_l3out\_extepg\_to\_contract +* Add support for useg default block statement configuration for useg epg in aci\_epg +* Modify child class node block conditions to be optional in aci\_switch\_leaf\_selector + + +#### cisco\.dnac + +* Added a method to validate IP addresses\. +* Added the op\_modifies\=True when calling SDK APIs in the workflow manager modules\. +* Adding support to importing a template using JSON file +* Changes in discovery workflow manager modules relating to different states of the discovery job +* Changes in inventory and swim workflow manager modules\. +* Fixed a minor issue in the site workflow manager module\. +* Updating galaxy\.yml ansible\.utils dependencies\. + + +#### cisco\.meraki + +* Ansible collection now support v1\.44\.1 of Dashboard Api\. +* administered\_licensing\_subscription\_entitlements\_info \- new plugin\. +* administered\_licensing\_subscription\_subscriptions\_bind \- new plugin\. +* administered\_licensing\_subscription\_subscriptions\_claim \- new plugin\. +* administered\_licensing\_subscription\_subscriptions\_claim\_key\_validate \- new plugin\. +* administered\_licensing\_subscription\_subscriptions\_compliance\_statuses\_info \- new plugin\. +* administered\_licensing\_subscription\_subscriptions\_info \- new plugin\. +* devices\_appliance\_radio\_settings \- new plugin\. +* devices\_appliance\_radio\_settings\_info \- new plugin\. +* devices\_live\_tools\_arp\_table \- new plugin\. +* devices\_live\_tools\_arp\_table\_info \- new plugin\. +* devices\_live\_tools\_cable\_test \- new plugin\. +* devices\_live\_tools\_cable\_test\_info \- new plugin\. +* devices\_live\_tools\_throughput\_test \- new plugin\. +* devices\_live\_tools\_throughput\_test\_info \- new plugin\. +* devices\_live\_tools\_wake\_on\_lan \- new plugin\. +* devices\_live\_tools\_wake\_on\_lan\_info \- new plugin\. +* devices\_wireless\_alternate\_management\_interface\_ipv6 \- new plugin\. +* networks\_appliance\_rf\_profiles \- new plugin\. +* networks\_appliance\_rf\_profiles\_info \- new plugin\. +* networks\_appliance\_traffic\_shaping\_vpn\_exclusions \- new plugin\. +* networks\_sm\_devices\_install\_apps \- new plugin\. +* networks\_sm\_devices\_reboot \- new plugin\. +* networks\_sm\_devices\_shutdown \- new plugin\. +* networks\_sm\_devices\_uninstall\_apps \- new plugin\. +* networks\_vlan\_profiles \- new plugin\. +* networks\_vlan\_profiles\_assignments\_by\_device\_info \- new plugin\. +* networks\_vlan\_profiles\_assignments\_reassign \- new plugin\. +* networks\_vlan\_profiles\_info \- new plugin\. +* networks\_wireless\_ethernet\_ports\_profiles \- new plugin\. +* networks\_wireless\_ethernet\_ports\_profiles\_assign \- new plugin\. +* networks\_wireless\_ethernet\_ports\_profiles\_info \- new plugin\. +* networks\_wireless\_ethernet\_ports\_profiles\_set\_default \- new plugin\. +* organizations\_appliance\_traffic\_shaping\_vpn\_exclusions\_by\_network\_info \- new plugin\. +* organizations\_appliance\_uplinks\_statuses\_overview\_info \- new plugin\. +* organizations\_appliance\_uplinks\_usage\_by\_network\_info \- new plugin\. +* organizations\_camera\_boundaries\_areas\_by\_device\_info \- new plugin\. +* organizations\_camera\_boundaries\_lines\_by\_device\_info \- new plugin\. +* organizations\_camera\_detections\_history\_by\_boundary\_by\_interval\_info \- new plugin\. +* organizations\_camera\_permissions\_info \- new plugin\. +* organizations\_camera\_roles \- new plugin\. +* organizations\_camera\_roles\_info \- new plugin\. +* organizations\_devices\_availabilities\_change\_history\_info \- new plugin\. +* organizations\_devices\_boots\_history\_info \- new plugin\. +* organizations\_sm\_admins\_roles \- new plugin\. +* organizations\_sm\_admins\_roles\_info \- new plugin\. +* organizations\_sm\_sentry\_policies\_assignments \- new plugin\. +* organizations\_sm\_sentry\_policies\_assignments\_by\_network\_info \- new plugin\. +* organizations\_summary\_top\_networks\_by\_status\_info \- new plugin\. +* organizations\_webhooks\_callbacks\_statuses\_info \- new plugin\. +* organizations\_wireless\_devices\_channel\_utilization\_by\_device\_info \- new plugin\. +* organizations\_wireless\_devices\_channel\_utilization\_by\_network\_info \- new plugin\. +* organizations\_wireless\_devices\_channel\_utilization\_history\_by\_device\_by\_interval\_info \- new plugin\. +* organizations\_wireless\_devices\_channel\_utilization\_history\_by\_network\_by\_interval\_info \- new plugin\. +* organizations\_wireless\_devices\_packet\_loss\_by\_client\_info \- new plugin\. +* organizations\_wireless\_devices\_packet\_loss\_by\_device\_info \- new plugin\. +* organizations\_wireless\_devices\_packet\_loss\_by\_network\_info \- new plugin\. + + +#### cisco\.mso + +* Add Azure Cloud site support to mso\_schema\_site\_contract\_service\_graph +* Add Azure Cloud site support to mso\_schema\_site\_service\_graph +* Add functionality to resolve same name in remote and local user\. +* Add l3out\_template and l3out\_schema arguments to mso\_schema\_site\_external\_epg \(\#394\) +* Add mso\_schema\_site\_contract\_service\_graph module to manage site contract service graph +* Add mso\_schema\_site\_contract\_service\_graph\_listener module to manage Azure site contract service graph listeners and update other modules +* Add new parameter remote\_user to add multiple remote users associated with multiple login domains +* Add support for replacing all existing contracts with new provided contracts in a single operation with one request and adding/removing multiple contracts in multiple operations with a single request in mso\_schema\_template\_anp\_epg\_contract module +* Add support for replacing all existing static ports with new provided static ports in a single operation with one request and adding/removing multiple static ports in multiple operations with a single request in mso\_schema\_template\_anp\_epg\_staticport module +* Add support for required attributes introduced in NDO 4\.2 for mso\_schema\_site\_anp\_epg\_domain +* Support for creation of schemas without templates with the mso\_schema module + + +#### community\.aws + +* glue\_job \- add support for 2 new instance types which are G\.4X and G\.8X \([https\://github\.com/ansible\-collections/community\.aws/pull/2048](https\://github\.com/ansible\-collections/community\.aws/pull/2048)\)\. +* msk\_cluster \- Support for additional m5 and m7g types of MSK clusters \([https\://github\.com/ansible\-collections/community\.aws/pull/1947](https\://github\.com/ansible\-collections/community\.aws/pull/1947)\)\. + + +#### community\.crypto + +* When using cryptography \>\= 42\.0\.0\, use offset\-aware datetime\.datetime objects \(with timezone UTC\) instead of offset\-naive UTC timestamps \([https\://github\.com/ansible\-collections/community\.crypto/issues/726](https\://github\.com/ansible\-collections/community\.crypto/issues/726)\, [https\://github\.com/ansible\-collections/community\.crypto/pull/727](https\://github\.com/ansible\-collections/community\.crypto/pull/727)\)\. +* openssh\_cert \- avoid UTC functions deprecated in Python 3\.12 when using Python 3 \([https\://github\.com/ansible\-collections/community\.crypto/pull/727](https\://github\.com/ansible\-collections/community\.crypto/pull/727)\)\. + + +#### community\.docker + +* The EE requirements now include PyYAML\, since the docker\_compose\_v2\* modules depend on it when the definition option is used\. This should not have a noticable effect on generated EEs since ansible\-core itself depends on PyYAML as well\, and ansible\-builder explicitly ignores this dependency \([https\://github\.com/ansible\-collections/community\.docker/pull/832](https\://github\.com/ansible\-collections/community\.docker/pull/832)\)\. +* docker\_compose\_v2\* \- the new option check\_files\_existing allows to disable the check for one of the files compose\.yaml\, compose\.yml\, docker\-compose\.yaml\, and docker\-compose\.yml in project\_src if files is not specified\. This is necessary if a non\-standard compose filename is specified through other means\, like the COMPOSE\_FILE environment variable \([https\://github\.com/ansible\-collections/community\.docker/issues/838](https\://github\.com/ansible\-collections/community\.docker/issues/838)\, [https\://github\.com/ansible\-collections/community\.docker/pull/839](https\://github\.com/ansible\-collections/community\.docker/pull/839)\)\. +* docker\_compose\_v2\* modules \- allow to provide an inline definition of the compose content instead of having to provide a project\_src directory with the compose file written into it \([https\://github\.com/ansible\-collections/community\.docker/issues/829](https\://github\.com/ansible\-collections/community\.docker/issues/829)\, [https\://github\.com/ansible\-collections/community\.docker/pull/832](https\://github\.com/ansible\-collections/community\.docker/pull/832)\)\. +* vendored Docker SDK for Python \- remove unused code that relies on functionality deprecated in Python 3\.12 \([https\://github\.com/ansible\-collections/community\.docker/pull/834](https\://github\.com/ansible\-collections/community\.docker/pull/834)\)\. + + +#### community\.general + +* Use offset\-aware datetime\.datetime objects \(with timezone UTC\) instead of offset\-naive UTC timestamps\, which are deprecated in Python 3\.12 \([https\://github\.com/ansible\-collections/community\.general/pull/8222](https\://github\.com/ansible\-collections/community\.general/pull/8222)\)\. +* apt\_rpm \- add new states latest and present\_not\_latest\. The value latest is equivalent to the current behavior of present\, which will upgrade a package if a newer version exists\. present\_not\_latest does what most users would expect present to do\: it does not upgrade if the package is already installed\. The current behavior of present will be deprecated in a later version\, and eventually changed to that of present\_not\_latest \([https\://github\.com/ansible\-collections/community\.general/issues/8217](https\://github\.com/ansible\-collections/community\.general/issues/8217)\, [https\://github\.com/ansible\-collections/community\.general/pull/8247](https\://github\.com/ansible\-collections/community\.general/pull/8247)\)\. +* bitwarden lookup plugin \- add support to filter by organization ID \([https\://github\.com/ansible\-collections/community\.general/pull/8188](https\://github\.com/ansible\-collections/community\.general/pull/8188)\)\. +* filesystem \- add bcachefs support \([https\://github\.com/ansible\-collections/community\.general/pull/8126](https\://github\.com/ansible\-collections/community\.general/pull/8126)\)\. +* ini\_file \- add an optional parameter section\_has\_values\. If the target ini file contains more than one section\, use section\_has\_values to specify which one should be updated \([https\://github\.com/ansible\-collections/community\.general/pull/7505](https\://github\.com/ansible\-collections/community\.general/pull/7505)\)\. +* java\_cert \- add cert\_content argument \([https\://github\.com/ansible\-collections/community\.general/pull/8153](https\://github\.com/ansible\-collections/community\.general/pull/8153)\)\. +* keycloak\_client\, keycloak\_clientscope\, keycloak\_clienttemplate \- added docker\-v2 protocol support\, enhancing alignment with Keycloak\'s protocol options \([https\://github\.com/ansible\-collections/community\.general/issues/8215](https\://github\.com/ansible\-collections/community\.general/issues/8215)\, [https\://github\.com/ansible\-collections/community\.general/pull/8216](https\://github\.com/ansible\-collections/community\.general/pull/8216)\)\. +* nmcli \- adds OpenvSwitch support with new type values ovs\-port\, ovs\-interface\, and ovs\-bridge\, and new slave\_type value ovs\-port \([https\://github\.com/ansible\-collections/community\.general/pull/8154](https\://github\.com/ansible\-collections/community\.general/pull/8154)\)\. +* osx\_defaults \- add option check\_types to enable changing the type of existing defaults on the fly \([https\://github\.com/ansible\-collections/community\.general/pull/8173](https\://github\.com/ansible\-collections/community\.general/pull/8173)\)\. +* passwordstore lookup \- add missing\_subkey parameter defining the behavior of the lookup when a passwordstore subkey is missing \([https\://github\.com/ansible\-collections/community\.general/pull/8166](https\://github\.com/ansible\-collections/community\.general/pull/8166)\)\. +* portage \- adds the possibility to explicitely tell portage to write packages to world file \([https\://github\.com/ansible\-collections/community\.general/issues/6226](https\://github\.com/ansible\-collections/community\.general/issues/6226)\, [https\://github\.com/ansible\-collections/community\.general/pull/8236](https\://github\.com/ansible\-collections/community\.general/pull/8236)\)\. +* redfish\_command \- add command ResetToDefaults to reset manager to default state \([https\://github\.com/ansible\-collections/community\.general/issues/8163](https\://github\.com/ansible\-collections/community\.general/issues/8163)\)\. +* redfish\_info \- add boolean return value MultipartHttpPush to GetFirmwareUpdateCapabilities \([https\://github\.com/ansible\-collections/community\.general/issues/8194](https\://github\.com/ansible\-collections/community\.general/issues/8194)\, [https\://github\.com/ansible\-collections/community\.general/pull/8195](https\://github\.com/ansible\-collections/community\.general/pull/8195)\)\. +* ssh\_config \- allow accept\-new as valid value for strict\_host\_key\_checking \([https\://github\.com/ansible\-collections/community\.general/pull/8257](https\://github\.com/ansible\-collections/community\.general/pull/8257)\)\. + + +#### community\.rabbitmq + +* rabbitmq\_user \- add support to user manipulation through RabbitMQ API \([https\://github\.com/ansible\-collections/community\.rabbitmq/issues/76](https\://github\.com/ansible\-collections/community\.rabbitmq/issues/76)\) + + +#### community\.routeros + +* api\_info\, api\_modify \- Add RouterOS 7\.x support to /mpls ldp path \([https\://github\.com/ansible\-collections/community\.routeros/pull/271](https\://github\.com/ansible\-collections/community\.routeros/pull/271)\)\. +* api\_info\, api\_modify \- add /ip route rule path for RouterOS 6\.x \([https\://github\.com/ansible\-collections/community\.routeros/pull/278](https\://github\.com/ansible\-collections/community\.routeros/pull/278)\)\. +* api\_info\, api\_modify \- add /routing filter path for RouterOS 6\.x \([https\://github\.com/ansible\-collections/community\.routeros/pull/279](https\://github\.com/ansible\-collections/community\.routeros/pull/279)\)\. +* api\_info\, api\_modify \- add default value for from\-pool field in /ipv6 address \([https\://github\.com/ansible\-collections/community\.routeros/pull/270](https\://github\.com/ansible\-collections/community\.routeros/pull/270)\)\. +* api\_info\, api\_modify \- add missing path /interface pppoe\-server server \([https\://github\.com/ansible\-collections/community\.routeros/pull/273](https\://github\.com/ansible\-collections/community\.routeros/pull/273)\)\. +* api\_info\, api\_modify \- add missing path /ip dhcp\-relay \([https\://github\.com/ansible\-collections/community\.routeros/pull/276](https\://github\.com/ansible\-collections/community\.routeros/pull/276)\)\. +* api\_info\, api\_modify \- add missing path /queue simple \([https\://github\.com/ansible\-collections/community\.routeros/pull/269](https\://github\.com/ansible\-collections/community\.routeros/pull/269)\)\. +* api\_info\, api\_modify \- add missing path /queue type \([https\://github\.com/ansible\-collections/community\.routeros/pull/274](https\://github\.com/ansible\-collections/community\.routeros/pull/274)\)\. +* api\_info\, api\_modify \- add missing paths /routing bgp aggregate\, /routing bgp network and /routing bgp peer \([https\://github\.com/ansible\-collections/community\.routeros/pull/277](https\://github\.com/ansible\-collections/community\.routeros/pull/277)\)\. +* api\_info\, api\_modify \- add support for paths /mpls interface\, /mpls ldp accept\-filter\, /mpls ldp advertise\-filter and mpls ldp interface \([https\://github\.com/ansible\-collections/community\.routeros/pull/272](https\://github\.com/ansible\-collections/community\.routeros/pull/272)\)\. + + +#### community\.vmware + +* Document that all parameters and VMware object names are case sensitive \([https\://github\.com/ansible\-collections/community\.vmware/issues/2019](https\://github\.com/ansible\-collections/community\.vmware/issues/2019)\)\. +* Drop the outdated \(and actually unmaintained\) scenario guides \([https\://github\.com/ansible\-collections/community\.vmware/pull/2022](https\://github\.com/ansible\-collections/community\.vmware/pull/2022)\)\. +* vmware\_dvswitch \- Add switchIpAddress/switch\_ip parameter for netflow config +* vmware\_guest\_tools\_info \- Use toolsVersionStatus2 instead of toolsVersionStatus \([https\://github\.com/ansible\-collections/community\.vmware/issues/2033](https\://github\.com/ansible\-collections/community\.vmware/issues/2033)\)\. + + +#### containers\.podman + +* CI \- Fix rootfs test in CI +* CI \- add custom podman path to tasks +* CI \- add parametrized executables to tests +* podman\_container \- Add pasta as default network mode after v5 +* podman\_container\_exec \- Return data for podman exec module +* podman\_generate\_systemd \- Fix broken example for podman\_generate\_systemd \(\#708\) +* podman\_login \- Update podman\_login\.py +* podman\_play \- Add support for kube yaml files with multi\-documents \(\#724\) +* podman\_play \- Update the logic for deleting pods/containers in podman\_play +* podman\_pod\_info \- handle return being list in Podman 5 \(\#713\) + + +#### dellemc\.powerflex + +* Added support for PowerFlex ansible modules and roles on Azure\. +* Added support for resource group provisioning to validate\, deploy\, edit\, add nodes and delete a resource group\. +* The Info module is enhanced to list the firmware repositories\. + + +#### netapp\.ontap + +* na\_ontap\_cifs \- new option offline\_files added in REST\, requires ONTAP 9\.10 or later\. +* na\_ontap\_net\_ifgrp \- updated documentation for parameter name\. +* na\_ontap\_vserver\_audit \- new options schedule\.\* added under log\.rotation\, requires ONTAP 9\.6 or later\. + + +#### purestorage\.flashblade + +* purefb\_bucket \- Add support for strict 17a\-4 WORM compliance\. +* purefb\_connect \- Increase Fan\-In and Fan\-Out maximums +* purefb\_fs \- Add group\_ownership parameter from Purity//FB 4\.4\.0\. +* purefb\_info \- Show array network access policy from Purity//FB 4\.4\.0 +* purefb\_policy \- Add support for network access policies from Purity//FB 4\.4\.0 + + +### Deprecated Features + + +#### community\.crypto + +* acme\.backends module utils \- from community\.crypto on\, all implementations of CryptoBackend must override get\_ordered\_csr\_identifiers\(\)\. The current default implementation\, which simply sorts the result of get\_csr\_identifiers\(\)\, will then be removed \([https\://github\.com/ansible\-collections/community\.crypto/pull/725](https\://github\.com/ansible\-collections/community\.crypto/pull/725)\)\. + + +#### community\.general + +* hipchat callback plugin \- the hipchat service has been discontinued and the self\-hosted variant has been End of Life since 2020\. The callback plugin is therefore deprecated and will be removed from community\.general 10\.0\.0 if nobody provides compelling reasons to still keep it \([https\://github\.com/ansible\-collections/community\.general/issues/8184](https\://github\.com/ansible\-collections/community\.general/issues/8184)\, [https\://github\.com/ansible\-collections/community\.general/pull/8189](https\://github\.com/ansible\-collections/community\.general/pull/8189)\)\. + + +#### community\.vmware + +* vmware\_guest\_tools\_info \- vm\_tools\_install\_status will be removed from next major version \(5\.0\.0\) of the collection since the API call that provides this information has been deprecated by VMware\. Use vm\_tools\_running\_status / vm\_tools\_version\_status instead \([https\://github\.com/ansible\-collections/community\.vmware/issues/2033](https\://github\.com/ansible\-collections/community\.vmware/issues/2033)\)\. + + +### Bugfixes + + +#### Ansible\-core + +* Consolidated the list of internal static vars\, centralized them as constant and completed from some missing entries\. +* Fix check for missing \_sub\_plugin attribute in older connection plugins \([https\://github\.com/ansible/ansible/pull/82954](https\://github\.com/ansible/ansible/pull/82954)\) +* Fixes permission for cache json file from 600 to 644 \([https\://github\.com/ansible/ansible/issues/82683](https\://github\.com/ansible/ansible/issues/82683)\)\. +* Slight optimization to hostvars \(instantiate template only once per host\, vs per call to var\)\. +* allow\_duplicates \- fix evaluating if the current role allows duplicates instead of using the initial value from the duplicate\'s cached role\. +* ansible\-config will now properly template defaults before dumping them\. +* ansible\-test ansible\-doc sanity test \- do not remove underscores from plugin names in collections before calling ansible\-doc \([https\://github\.com/ansible/ansible/pull/82574](https\://github\.com/ansible/ansible/pull/82574)\)\. +* async \- Fix bug that stopped running async task in \-\-check when check\_mode\: False was set as a task attribute \- [https\://github\.com/ansible/ansible/issues/82811](https\://github\.com/ansible/ansible/issues/82811) +* blockinfile \- when create\=true is used with a filename without path\, the module crashed \([https\://github\.com/ansible/ansible/pull/81638](https\://github\.com/ansible/ansible/pull/81638)\)\. +* dnf \- fix an issue when cached RPMs were left in the cache directory even when the keepcache setting was unset \([https\://github\.com/ansible/ansible/issues/81954](https\://github\.com/ansible/ansible/issues/81954)\) +* dnf5 \- replace removed API calls +* facts \- add a generic detection for VMware in product name\. +* fetch \- add error message when using dest with a trailing slash that becomes a local directory \- [https\://github\.com/ansible/ansible/issues/82878](https\://github\.com/ansible/ansible/issues/82878) +* find \- do not fail on Permission errors \([https\://github\.com/ansible/ansible/issues/82027](https\://github\.com/ansible/ansible/issues/82027)\)\. +* unarchive modules now uses zipinfo options without relying on implementation defaults\, making it more compatible with all OS/distributions\. +* winrm \- Do not raise another exception during cleanup when a task is timed out \- [https\://github\.com/ansible/ansible/issues/81095](https\://github\.com/ansible/ansible/issues/81095) + + +#### amazon\.aws + +* cloudwatchlogs\_log\_group\_info \- Implement exponential backoff when making API calls to prevent throttling exceptions \([https\://github\.com/ansible\-collections/amazon\.aws/issues/2011](https\://github\.com/ansible\-collections/amazon\.aws/issues/2011)\)\. +* plugin\_utils\.inventory \- Ensure templated options in lookup plugins are converted \([https\://github\.com/ansible\-collections/amazon\.aws/issues/1955](https\://github\.com/ansible\-collections/amazon\.aws/issues/1955)\)\. +* s3\_object \- Fix the issue when copying an object with overriding metadata\. \([https\://github\.com/ansible\-collections/amazon\.aws/issues/1991](https\://github\.com/ansible\-collections/amazon\.aws/issues/1991)\)\. + + +#### cisco\.aci + +* Fix auto logout issue in aci connection plugin to keep connection active between tasks +* Fix idempotency for l3out configuration when l3protocol is used in aci\_l3out +* Fix issues with new attributes in aci\_interface\_policy\_leaf\_policy\_group module by adding conditions to include attributes in the payload only when they are specified by the user \(\#578\) +* Fix query in aci\_vmm\_controller + + +#### cisco\.ise + +* ansible\.utils changes to \"\>\=2\.0\.0\,\<5\.0\" in galaxy\.yml dependencies\. + + +#### cisco\.mso + +* Fix TypeError for iteration on NoneType in mso\_schema\_template +* Fixed the useg\_subnet logic in mso\_schema\_template\_anp\_epg\_useg\_attribute + + +#### community\.aws + +* ssm\(connection\) \- fix bucket region logic when region is us\-east\-1 \([https\://github\.com/ansible\-collections/community\.aws/pull/1908](https\://github\.com/ansible\-collections/community\.aws/pull/1908)\)\. + + +#### community\.crypto + +* acme\_certificate \- respect the order of the CNAME and SAN identifiers that are passed on when creating an ACME order \([https\://github\.com/ansible\-collections/community\.crypto/issues/723](https\://github\.com/ansible\-collections/community\.crypto/issues/723)\, [https\://github\.com/ansible\-collections/community\.crypto/pull/725](https\://github\.com/ansible\-collections/community\.crypto/pull/725)\)\. + + +#### community\.dns + +* Update Public Suffix List\. +* inventory plugins \- add unsafe wrapper to avoid marking strings that do not contain \{ or \} as unsafe\, to work around a bug in AWX \([https\://github\.com/ansible\-collections/community\.dns/pull/197](https\://github\.com/ansible\-collections/community\.dns/pull/197)\)\. + + +#### community\.docker + +* docker\_compose\_v2\* \- allow project\_src to be a relative path\, by converting it to an absolute path before using it \([https\://github\.com/ansible\-collections/community\.docker/issues/827](https\://github\.com/ansible\-collections/community\.docker/issues/827)\, [https\://github\.com/ansible\-collections/community\.docker/pull/828](https\://github\.com/ansible\-collections/community\.docker/pull/828)\)\. +* docker\_compose\_v2\* modules \- abort with a nice error message instead of crash when the Docker Compose CLI plugin version is dev \([https\://github\.com/ansible\-collections/community\.docker/issues/825](https\://github\.com/ansible\-collections/community\.docker/issues/825)\, [https\://github\.com/ansible\-collections/community\.docker/pull/826](https\://github\.com/ansible\-collections/community\.docker/pull/826)\)\. +* inventory plugins \- add unsafe wrapper to avoid marking strings that do not contain \{ or \} as unsafe\, to work around a bug in AWX \([https\://github\.com/ansible\-collections/community\.docker/pull/835](https\://github\.com/ansible\-collections/community\.docker/pull/835)\)\. + + +#### community\.general + +* aix\_filesystem \- fix \_validate\_vg not passing VG name to lsvg\_cmd \([https\://github\.com/ansible\-collections/community\.general/issues/8151](https\://github\.com/ansible\-collections/community\.general/issues/8151)\)\. +* apt\_rpm \- when checking whether packages were installed after running apt\-get \-y install \\, only the last package name was checked \([https\://github\.com/ansible\-collections/community\.general/pull/8263](https\://github\.com/ansible\-collections/community\.general/pull/8263)\)\. +* bitwarden\_secrets\_manager lookup plugin \- implements retry with exponential backoff to avoid lookup errors when Bitwardn\'s API rate limiting is encountered \([https\://github\.com/ansible\-collections/community\.general/issues/8230](https\://github\.com/ansible\-collections/community\.general/issues/8230)\, [https\://github\.com/ansible\-collections/community\.general/pull/8238](https\://github\.com/ansible\-collections/community\.general/pull/8238)\)\. +* from\_ini filter plugin \- disabling interpolation of ConfigParser to allow converting values with a \% sign \([https\://github\.com/ansible\-collections/community\.general/issues/8183](https\://github\.com/ansible\-collections/community\.general/issues/8183)\, [https\://github\.com/ansible\-collections/community\.general/pull/8185](https\://github\.com/ansible\-collections/community\.general/pull/8185)\)\. +* gitlab\_issue\, gitlab\_label\, gitlab\_milestone \- avoid crash during version comparison when the python\-gitlab Python module is not installed \([https\://github\.com/ansible\-collections/community\.general/pull/8158](https\://github\.com/ansible\-collections/community\.general/pull/8158)\)\. +* haproxy \- fix an issue where HAProxy could get stuck in DRAIN mode when the backend was unreachable \([https\://github\.com/ansible\-collections/community\.general/issues/8092](https\://github\.com/ansible\-collections/community\.general/issues/8092)\)\. +* inventory plugins \- add unsafe wrapper to avoid marking strings that do not contain \{ or \} as unsafe\, to work around a bug in AWX \(\([https\://github\.com/ansible\-collections/community\.general/issues/8212](https\://github\.com/ansible\-collections/community\.general/issues/8212)\, [https\://github\.com/ansible\-collections/community\.general/pull/8225](https\://github\.com/ansible\-collections/community\.general/pull/8225)\)\. +* ipa \- fix get version regex in IPA module\_utils \([https\://github\.com/ansible\-collections/community\.general/pull/8175](https\://github\.com/ansible\-collections/community\.general/pull/8175)\)\. +* keycloak\_client \- add sorted defaultClientScopes and optionalClientScopes to normalizations \([https\://github\.com/ansible\-collections/community\.general/pull/8223](https\://github\.com/ansible\-collections/community\.general/pull/8223)\)\. +* keycloak\_realm \- add normalizations for enabledEventTypes and supportedLocales \([https\://github\.com/ansible\-collections/community\.general/pull/8224](https\://github\.com/ansible\-collections/community\.general/pull/8224)\)\. +* puppet \- add option environment\_lang to set the environment language encoding\. Defaults to lang C\. It is recommended to set it to C\.UTF\-8 or en\_US\.UTF\-8 depending on what is available on your system\. \([https\://github\.com/ansible\-collections/community\.general/issues/8000](https\://github\.com/ansible\-collections/community\.general/issues/8000)\) +* riak \- support riak admin sub\-command in newer Riak KV versions beside the legacy riak\-admin main command \([https\://github\.com/ansible\-collections/community\.general/pull/8211](https\://github\.com/ansible\-collections/community\.general/pull/8211)\)\. +* to\_ini filter plugin \- disabling interpolation of ConfigParser to allow converting values with a \% sign \([https\://github\.com/ansible\-collections/community\.general/issues/8183](https\://github\.com/ansible\-collections/community\.general/issues/8183)\, [https\://github\.com/ansible\-collections/community\.general/pull/8185](https\://github\.com/ansible\-collections/community\.general/pull/8185)\)\. +* xml \- make module work with lxml 5\.1\.1\, which removed some internals that the module was relying on \([https\://github\.com/ansible\-collections/community\.general/pull/8169](https\://github\.com/ansible\-collections/community\.general/pull/8169)\)\. + + +#### community\.hrobot + +* inventory plugins \- add unsafe wrapper to avoid marking strings that do not contain \{ or \} as unsafe\, to work around a bug in AWX \([https\://github\.com/ansible\-collections/community\.hrobot/pull/102](https\://github\.com/ansible\-collections/community\.hrobot/pull/102)\)\. + + +#### community\.vmware + +* Use isinstance\(\) instead of type\(\) for a typecheck \([https\://github\.com/ansible\-collections/community\.vmware/pull/2011](https\://github\.com/ansible\-collections/community\.vmware/pull/2011)\)\. +* vmware\_guest \- Fix a error while updating the VM by adding a new disk\. While adding a disk to an existing VM\, it leaves it in invalid state\. \([https\://github\.com/ansible\-collections/community\.vmware/pull/2044](https\://github\.com/ansible\-collections/community\.vmware/pull/2044)\)\. +* vmware\_guest \- Fix a missing error message while setting a template parameter with inconsistency guest\_os ID \([https\://github\.com/ansible\-collections/community\.vmware/pull/2036](https\://github\.com/ansible\-collections/community\.vmware/pull/2036)\)\. + + +#### containers\.podman + +* Fix pod info for non\-existant pods +* podman\_container \- Add check and fixed for v5 network diff +* podman\_container \- Fix pasta networking idempotency for v5 \(\#728\) +* podman\_container\_exec \- Remove unnecessary quotes in podman\_container\_exec module +* podman\_image\_info \- Fix wrong return data type in podman\_image\_info +* podman\_play \- Fix kube play annotations +* podman\_pod \- Fix broken info of pods in Podman v5 +* podman\_pod \- Fix pod for Podman v5 +* podman\_pod \- Fix podman pod v5 broken info issue + + +#### fortinet\.fortios + +* Fix the issue that ssl\-certificate cannot be set in fortios\_firewall\_vip and fortios\_firewall\_vip6\. +* Github issue +* mantis issue + + +#### netapp\.ontap + +* na\_ontap\_dns \- fix issue with modifying DNS servers in REST\. +* na\_ontap\_fpolicy\_policy \- fixed issue with idempotency in REST\. +* na\_ontap\_quotas \- fixed issue with idempotency in REST\. +* na\_ontap\_security\_config \- added warning for missing supported\_cipher\_suites to maintain idempotency in REST\. + + +### New Plugins + + +#### Filter + +* community\.dns\.quote\_txt \- Quotes a string to use as a TXT record entry +* community\.dns\.unquote\_txt \- Unquotes a TXT record entry to a string + + +### New Modules + + +#### community\.aws + +* community\.aws\.dynamodb\_table\_info \- Returns information about a Dynamo DB table + + +#### community\.crypto + +* community\.crypto\.x509\_certificate\_convert \- Convert X\.509 certificates + + +#### community\.general + +* community\.general\.keycloak\_client\_rolescope \- Allows administration of Keycloak client roles scope to restrict the usage of certain roles to a other specific client applications\. + + +#### dellemc\.powerflex + +* dellemc\.powerflex\.resource\_group \- Manage resource group deployments on Dell PowerFlex + + +### Unchanged Collections + +* ansible\.netcommon \(still version 5\.3\.0\) +* ansible\.posix \(still version 1\.5\.4\) +* ansible\.utils \(still version 2\.12\.0\) +* ansible\.windows \(still version 2\.3\.0\) +* arista\.eos \(still version 6\.2\.2\) +* awx\.awx \(still version 23\.9\.0\) +* azure\.azcollection \(still version 1\.19\.0\) +* check\_point\.mgmt \(still version 5\.2\.3\) +* chocolatey\.chocolatey \(still version 1\.5\.1\) +* cisco\.asa \(still version 4\.0\.3\) +* cisco\.ios \(still version 5\.3\.0\) +* cisco\.iosxr \(still version 6\.1\.1\) +* cisco\.nxos \(still version 5\.3\.0\) +* cisco\.ucs \(still version 1\.10\.0\) +* cloud\.common \(still version 2\.1\.4\) +* cloudscale\_ch\.cloud \(still version 2\.3\.1\) +* community\.azure \(still version 2\.0\.0\) +* community\.ciscosmb \(still version 1\.0\.7\) +* community\.digitalocean \(still version 1\.26\.0\) +* community\.grafana \(still version 1\.8\.0\) +* community\.hashi\_vault \(still version 6\.2\.0\) +* community\.libvirt \(still version 1\.3\.0\) +* community\.mysql \(still version 3\.9\.0\) +* community\.network \(still version 5\.0\.2\) +* community\.okd \(still version 2\.3\.0\) +* community\.postgresql \(still version 3\.4\.0\) +* community\.proxysql \(still version 1\.5\.1\) +* community\.sap \(still version 2\.0\.0\) +* community\.sap\_libs \(still version 1\.4\.2\) +* community\.sops \(still version 1\.6\.7\) +* community\.windows \(still version 2\.2\.0\) +* community\.zabbix \(still version 2\.3\.1\) +* cyberark\.conjur \(still version 1\.2\.2\) +* cyberark\.pas \(still version 1\.0\.25\) +* dellemc\.enterprise\_sonic \(still version 2\.4\.0\) +* dellemc\.openmanage \(still version 8\.7\.0\) +* dellemc\.unity \(still version 1\.7\.1\) +* f5networks\.f5\_modules \(still version 1\.28\.0\) +* fortinet\.fortimanager \(still version 2\.4\.0\) +* frr\.frr \(still version 2\.0\.2\) +* gluster\.gluster \(still version 1\.0\.2\) +* google\.cloud \(still version 1\.3\.0\) +* grafana\.grafana \(still version 2\.2\.5\) +* hetzner\.hcloud \(still version 2\.5\.0\) +* hpe\.nimble \(still version 1\.1\.4\) +* ibm\.qradar \(still version 2\.1\.0\) +* ibm\.spectrum\_virtualize \(still version 2\.0\.0\) +* ibm\.storage\_virtualize \(still version 2\.3\.1\) +* infoblox\.nios\_modules \(still version 1\.6\.1\) +* inspur\.ispim \(still version 2\.2\.0\) +* inspur\.sm \(still version 2\.3\.0\) +* junipernetworks\.junos \(still version 5\.3\.1\) +* kubernetes\.core \(still version 2\.4\.2\) +* lowlydba\.sqlserver \(still version 2\.3\.2\) +* microsoft\.ad \(still version 1\.5\.0\) +* netapp\.aws \(still version 21\.7\.1\) +* netapp\.azure \(still version 21\.10\.1\) +* netapp\.cloudmanager \(still version 21\.22\.1\) +* netapp\.elementsw \(still version 21\.7\.0\) +* netapp\.storagegrid \(still version 21\.12\.0\) +* netapp\.um\_info \(still version 21\.8\.1\) +* netapp\_eseries\.santricity \(still version 1\.4\.0\) +* netbox\.netbox \(still version 3\.17\.0\) +* ngine\_io\.cloudstack \(still version 2\.3\.0\) +* ngine\_io\.exoscale \(still version 1\.1\.0\) +* openstack\.cloud \(still version 2\.2\.0\) +* openvswitch\.openvswitch \(still version 2\.1\.1\) +* ovirt\.ovirt \(still version 3\.2\.0\) +* purestorage\.flasharray \(still version 1\.27\.0\) +* purestorage\.fusion \(still version 1\.6\.1\) +* sensu\.sensu\_go \(still version 1\.14\.0\) +* splunk\.es \(still version 2\.1\.2\) +* t\_systems\_mms\.icinga\_director \(still version 2\.0\.1\) +* telekom\_mms\.icinga\_director \(still version 1\.35\.0\) +* theforeman\.foreman \(still version 3\.15\.0\) +* vmware\.vmware\_rest \(still version 2\.3\.1\) +* vultr\.cloud \(still version 1\.12\.1\) +* vyos\.vyos \(still version 4\.1\.0\) +* wti\.remote \(still version 1\.0\.5\) ## v9\.4\.0 -- Release Summary -- Ansible\-core -- Changed Collections -- Minor Changes - - Ansible\-core - - amazon\.aws +- Release Summary +- Ansible\-core +- Changed Collections +- Minor Changes + - Ansible\-core + - amazon\.aws - ansible\.windows - - cisco\.dnac - - cisco\.ise - - community\.general + - cisco\.dnac + - cisco\.ise + - community\.general - community\.hashi\_vault - - community\.routeros + - community\.routeros - community\.windows - - dellemc\.powerflex + - dellemc\.powerflex - ibm\.storage\_virtualize - microsoft\.ad - purestorage\.flasharray - - purestorage\.flashblade -- Deprecated Features - - amazon\.aws + - purestorage\.flashblade +- Deprecated Features + - amazon\.aws - Security Fixes - - community\.dns - - community\.docker - - community\.general - - community\.hrobot -- Bugfixes - - Ansible\-core - - amazon\.aws - - ansible\.windows - community\.dns - - community\.docker - - community\.general + - community\.docker + - community\.general + - community\.hrobot +- Bugfixes + - Ansible\-core + - amazon\.aws + - ansible\.windows + - community\.dns + - community\.docker + - community\.general - community\.windows - ibm\.storage\_virtualize - kubernetes\.core - lowlydba\.sqlserver - microsoft\.ad - purestorage\.flasharray - - purestorage\.flashblade -- New Plugins - - Filter -- New Modules - - community\.general + - purestorage\.flashblade +- New Plugins + - Filter +- New Modules + - community\.general - community\.hashi\_vault - - dellemc\.powerflex -- Unchanged Collections + - dellemc\.powerflex +- Unchanged Collections - + ### Release Summary Release Date\: 2024\-03\-27 [Porting Guide](https\://docs\.ansible\.com/ansible/devel/porting\_guides\.html) - + ### Ansible\-core Ansible 9\.4\.0 contains ansible\-core version 2\.16\.5\. @@ -139,7 +792,7 @@ This is a newer version than version 2\.16\.4 contained in the previous Ansible The changes are reported in the combined changelog below\. - + ### Changed Collections If not mentioned explicitly\, the changes are reported in the combined changelog below\. @@ -168,15 +821,15 @@ If not mentioned explicitly\, the changes are reported in the combined changelog | purestorage.flasharray | 1.26.0 | 1.27.0 | | | purestorage.flashblade | 1.15.0 | 1.16.0 | | - + ### Minor Changes - + #### Ansible\-core * ansible\-test \- Add a work\-around for permission denied errors when using pytest \>\= 8 on multi\-user systems with an installed version of ansible\-test\. - + #### amazon\.aws * AnsibeAWSModule \- added fail\_json\_aws\_error\(\) as a wrapper for fail\_json\(\) and fail\_json\_aws\(\) when passed an AnsibleAWSError exception \([https\://github\.com/ansible\-collections/amazon\.aws/pull/1997](https\://github\.com/ansible\-collections/amazon\.aws/pull/1997)\)\. @@ -197,7 +850,7 @@ If not mentioned explicitly\, the changes are reported in the combined changelog * win\_uri \- Max depth for json object conversion used to be 2\. Can now send json objects with up to 20 levels of nesting - + #### cisco\.dnac * Added attributes \'dnac\_api\_task\_timeout\' and \'dnac\_task\_poll\_interval\' in intent and workflow\_manager modules\. @@ -211,12 +864,12 @@ If not mentioned explicitly\, the changes are reported in the combined changelog * inventory\_workflow\_manager \- Added attributes \'add\_user\_defined\_field\'\, \'update\_interface\_details\'\, \'export\_device\_list\' and \'admin\_status\' * inventory\_workflow\_manager \- Removed attributes \'provision\_wireless\_device\'\, \'reprovision\_wired\_device\' - + #### cisco\.ise * Changes the minimum supported version from Ansible v2\.9\.10 to v2\.14\.0 - + #### community\.general * bitwarden lookup plugin \- allows to fetch all records of a given collection ID\, by allowing to pass an empty value for search\_value when collection\_id is provided \([https\://github\.com/ansible\-collections/community\.general/pull/8013](https\://github\.com/ansible\-collections/community\.general/pull/8013)\)\. @@ -234,7 +887,7 @@ If not mentioned explicitly\, the changes are reported in the combined changelog * cert auth \- add option to set the cert\_auth\_public\_key and cert\_auth\_private\_key parameters using the variables ansible\_hashi\_vault\_cert\_auth\_public\_key and ansible\_hashi\_vault\_cert\_auth\_private\_key \([https\://github\.com/ansible\-collections/community\.hashi\_vault/issues/428](https\://github\.com/ansible\-collections/community\.hashi\_vault/issues/428)\)\. - + #### community\.routeros * api\_info\, api\_modify \- add read\-only fields installed\-version\, latest\-version and status in system package update \([https\://github\.com/ansible\-collections/community\.routeros/pull/263](https\://github\.com/ansible\-collections/community\.routeros/pull/263)\)\. @@ -246,7 +899,7 @@ If not mentioned explicitly\, the changes are reported in the combined changelog * win\_regmerge \- Add content \'content\' parameter for specifying registry file contents directly - + #### dellemc\.powerflex * The Info module is enhanced to retrieve lists related to fault sets\, service templates\, deployments\, and managed devices\. @@ -282,15 +935,15 @@ If not mentioned explicitly\, the changes are reported in the combined changelog * purefa\_syslog \- name becomes a required parameter as module converts to full REST 2 support * purefa\_vnc \- Convert to REST v2 - + #### purestorage\.flashblade * purefb\_ds \- Add force\_bind\_password parameter to allow module to be idempotent\. - + ### Deprecated Features - + #### amazon\.aws * iam\_role\_info \- in a release after 2026\-05\-01 paths must begin and end with / \([https\://github\.com/ansible\-collections/amazon\.aws/pull/1998](https\://github\.com/ansible\-collections/amazon\.aws/pull/1998)\)\. @@ -298,30 +951,30 @@ If not mentioned explicitly\, the changes are reported in the combined changelog ### Security Fixes - + #### community\.dns * hosttech\_dns\_records and hetzner\_dns\_records inventory plugins \- make sure all data received from the remote servers is marked as unsafe\, so remote code execution by obtaining texts that can be evaluated as templates is not possible \([https\://www\.die\-welt\.net/2024/03/remote\-code\-execution\-in\-ansible\-dynamic\-inventory\-plugins/](https\://www\.die\-welt\.net/2024/03/remote\-code\-execution\-in\-ansible\-dynamic\-inventory\-plugins/)\, [https\://github\.com/ansible\-collections/community\.dns/pull/189](https\://github\.com/ansible\-collections/community\.dns/pull/189)\)\. - + #### community\.docker * docker\_containers\, docker\_machine\, and docker\_swarm inventory plugins \- make sure all data received from the Docker daemon / Docker machine is marked as unsafe\, so remote code execution by obtaining texts that can be evaluated as templates is not possible \([https\://www\.die\-welt\.net/2024/03/remote\-code\-execution\-in\-ansible\-dynamic\-inventory\-plugins/](https\://www\.die\-welt\.net/2024/03/remote\-code\-execution\-in\-ansible\-dynamic\-inventory\-plugins/)\, [https\://github\.com/ansible\-collections/community\.docker/pull/815](https\://github\.com/ansible\-collections/community\.docker/pull/815)\)\. - + #### community\.general * cobbler\, gitlab\_runners\, icinga2\, linode\, lxd\, nmap\, online\, opennebula\, proxmox\, scaleway\, stackpath\_compute\, virtualbox\, and xen\_orchestra inventory plugin \- make sure all data received from the remote servers is marked as unsafe\, so remote code execution by obtaining texts that can be evaluated as templates is not possible \([https\://www\.die\-welt\.net/2024/03/remote\-code\-execution\-in\-ansible\-dynamic\-inventory\-plugins/](https\://www\.die\-welt\.net/2024/03/remote\-code\-execution\-in\-ansible\-dynamic\-inventory\-plugins/)\, [https\://github\.com/ansible\-collections/community\.general/pull/8098](https\://github\.com/ansible\-collections/community\.general/pull/8098)\)\. - + #### community\.hrobot * robot inventory plugin \- make sure all data received from the Hetzner robot service server is marked as unsafe\, so remote code execution by obtaining texts that can be evaluated as templates is not possible \([https\://www\.die\-welt\.net/2024/03/remote\-code\-execution\-in\-ansible\-dynamic\-inventory\-plugins/](https\://www\.die\-welt\.net/2024/03/remote\-code\-execution\-in\-ansible\-dynamic\-inventory\-plugins/)\, [https\://github\.com/ansible\-collections/community\.hrobot/pull/99](https\://github\.com/ansible\-collections/community\.hrobot/pull/99)\)\. - + ### Bugfixes - + #### Ansible\-core * Fix an issue when setting a plugin name from an unsafe source resulted in ValueError\: unmarshallable object \([https\://github\.com/ansible/ansible/issues/82708](https\://github\.com/ansible/ansible/issues/82708)\) @@ -330,7 +983,7 @@ If not mentioned explicitly\, the changes are reported in the combined changelog * template \- Fix error when templating an unsafe string which corresponds to an invalid type in Python \([https\://github\.com/ansible/ansible/issues/82600](https\://github\.com/ansible/ansible/issues/82600)\)\. * winrm \- does not hang when attempting to get process output when stdin write failed - + #### amazon\.aws * cloudwatchevent\_rule \- Fix to avoid adding quotes to JSON input for provided input\_template \([https\://github\.com/ansible\-collections/amazon\.aws/pull/1883](https\://github\.com/ansible\-collections/amazon\.aws/pull/1883)\)\. @@ -343,13 +996,13 @@ If not mentioned explicitly\, the changes are reported in the combined changelog * win\_get\_url \- Fix Tls1\.3 getting removed from the list of security protocols * win\_powershell \- Remove unecessary using in code causing stray error records in output \- [https\://github\.com/ansible\-collections/ansible\.windows/issues/571](https\://github\.com/ansible\-collections/ansible\.windows/issues/571) - + #### community\.dns * DNS record modules\, inventory plugins \- fix the TXT entry encoder to avoid splitting up escape sequences for quotes and backslashes over multiple TXT strings \([https\://github\.com/ansible\-collections/community\.dns/issues/190](https\://github\.com/ansible\-collections/community\.dns/issues/190)\, [https\://github\.com/ansible\-collections/community\.dns/pull/191](https\://github\.com/ansible\-collections/community\.dns/pull/191)\)\. * Update Public Suffix List\. - + #### community\.docker * docker\_compose\_v2 \- do not fail when non\-fatal errors occur\. This can happen when pulling an image fails\, but then the image can be built for another service\. Docker Compose emits an error in that case\, but docker compose up still completes successfully \([https\://github\.com/ansible\-collections/community\.docker/issues/807](https\://github\.com/ansible\-collections/community\.docker/issues/807)\, [https\://github\.com/ansible\-collections/community\.docker/pull/810](https\://github\.com/ansible\-collections/community\.docker/pull/810)\, [https\://github\.com/ansible\-collections/community\.docker/pull/811](https\://github\.com/ansible\-collections/community\.docker/pull/811)\)\. @@ -357,7 +1010,7 @@ If not mentioned explicitly\, the changes are reported in the combined changelog * docker\_compose\_v2\* modules \- parse logfmt warnings emitted by Docker Compose \([https\://github\.com/ansible\-collections/community\.docker/issues/787](https\://github\.com/ansible\-collections/community\.docker/issues/787)\, [https\://github\.com/ansible\-collections/community\.docker/pull/811](https\://github\.com/ansible\-collections/community\.docker/pull/811)\)\. * docker\_compose\_v2\_pull \- fixing idempotence by checking actual pull progress events instead of service\-level pull request when policy\=always\. This stops the module from reporting changed\=true if no actual change happened when pulling\. In check mode\, it has to assume that a change happens though \([https\://github\.com/ansible\-collections/community\.docker/issues/813](https\://github\.com/ansible\-collections/community\.docker/issues/813)\, [https\://github\.com/ansible\-collections/community\.docker/pull/814](https\://github\.com/ansible\-collections/community\.docker/pull/814)\)\. - + #### community\.general * aix\_filesystem \- fix issue with empty list items in crfs logic and option order \([https\://github\.com/ansible\-collections/community\.general/pull/8052](https\://github\.com/ansible\-collections/community\.general/pull/8052)\)\. @@ -408,26 +1061,26 @@ If not mentioned explicitly\, the changes are reported in the combined changelog * purefa\_inventory \- Fix issue with iSCSI\-only FlashArrays * purefa\_pgsnap \- Add support for restoring volumes connected to hosts in a host\-based protection group and hosts in a hostgroup\-based protection group\. - + #### purestorage\.flashblade * purefb\_bucket \- Changed logic to allow complex buckets to be created in a single call\, rather than having to split into two tasks\. * purefb\_lag \- Enable LAG port configuration with multi\-chassis * purefb\_timeout \- Fixed arithmetic error that resulted in module incorrectly reporting changed when no change was required\. - + ### New Plugins - + #### Filter * microsoft\.ad\.dn\_escape \- Escape an LDAP DistinguishedName value string\. * microsoft\.ad\.parse\_dn \- Parses an LDAP DistinguishedName string into an object\. - + ### New Modules - + #### community\.general * community\.general\.usb\_facts \- Allows listing information about USB devices @@ -451,12 +1104,12 @@ If not mentioned explicitly\, the changes are reported in the combined changelog * community\.hashi\_vault\.vault\_database\_static\_role\_rotate\_credentials \- Trigger the credential rotation for a static role * community\.hashi\_vault\.vault\_database\_static\_roles\_list \- Returns a list of available static roles - + #### dellemc\.powerflex * dellemc\.powerflex\.fault\_set \- Manage Fault Sets on Dell PowerFlex - + ### Unchanged Collections * ansible\.netcommon \(still version 5\.3\.0\) @@ -545,71 +1198,71 @@ If not mentioned explicitly\, the changes are reported in the combined changelog ## v9\.3\.0 -- Release Summary -- Ansible\-core -- Changed Collections -- Major Changes +- Release Summary +- Ansible\-core +- Changed Collections +- Major Changes - community\.mysql - - fortinet\.fortios -- Minor Changes - - amazon\.aws - - community\.crypto - - community\.docker - - community\.general + - fortinet\.fortios +- Minor Changes + - amazon\.aws + - community\.crypto + - community\.docker + - community\.general - community\.grafana - community\.mysql - community\.postgresql - - community\.routeros - - community\.vmware - - containers\.podman + - community\.routeros + - community\.vmware + - containers\.podman - fortinet\.fortimanager - grafana\.grafana - hetzner\.hcloud - lowlydba\.sqlserver - - netapp\.ontap + - netapp\.ontap - netapp\.storagegrid - netbox\.netbox - purestorage\.fusion -- Deprecated Features - - community\.crypto -- Bugfixes - - Ansible\-core - - amazon\.aws - - community\.crypto - - community\.dns - - community\.docker - - community\.general +- Deprecated Features + - community\.crypto +- Bugfixes + - Ansible\-core + - amazon\.aws + - community\.crypto + - community\.dns + - community\.docker + - community\.general - community\.grafana - community\.mysql - community\.postgresql - - community\.routeros - - containers\.podman + - community\.routeros + - containers\.podman - f5networks\.f5\_modules - fortinet\.fortimanager - - fortinet\.fortios + - fortinet\.fortios - lowlydba\.sqlserver - - netapp\.ontap + - netapp\.ontap - netapp\.storagegrid - netbox\.netbox -- New Plugins +- New Plugins - Callback - - Filter -- New Modules - - community\.general - - containers\.podman + - Filter +- New Modules + - community\.general + - containers\.podman - fortinet\.fortimanager - hetzner\.hcloud - netbox\.netbox -- Unchanged Collections +- Unchanged Collections - + ### Release Summary Release Date\: 2024\-02\-27 [Porting Guide](https\://docs\.ansible\.com/ansible/devel/porting\_guides\.html) - + ### Ansible\-core Ansible 9\.3\.0 contains ansible\-core version 2\.16\.4\. @@ -617,7 +1270,7 @@ This is a newer version than version 2\.16\.3 contained in the previous Ansible The changes are reported in the combined changelog below\. - + ### Changed Collections If not mentioned explicitly\, the changes are reported in the combined changelog below\. @@ -651,7 +1304,7 @@ If not mentioned explicitly\, the changes are reported in the combined changelog | netbox.netbox | 3.16.0 | 3.17.0 | | | purestorage.fusion | 1.6.0 | 1.6.1 | | - + ### Major Changes @@ -659,7 +1312,7 @@ If not mentioned explicitly\, the changes are reported in the combined changelog * Collection version 2\.\*\.\* is EOL\, no more bugfixes will be backported\. Please consider upgrading to the latest version\. - + #### fortinet\.fortios * Update all the boolean values to true/false in the documents and examples\. @@ -668,10 +1321,10 @@ If not mentioned explicitly\, the changes are reported in the combined changelog * Update the required ansible version to 2\.14\. * Update the supported version ranges instead of concrete version numbers to reduce the collection size\. - + ### Minor Changes - + #### amazon\.aws * backup\_plan \- Let user to set schedule\_expression\_timezone for backup plan rules when when using botocore \>\= 1\.31\.36 \([https\://github\.com/ansible\-collections/amazon\.aws/issues/1952](https\://github\.com/ansible\-collections/amazon\.aws/issues/1952)\)\. @@ -682,19 +1335,19 @@ If not mentioned explicitly\, the changes are reported in the combined changelog * s3\_bucket\_info \- add parameter bucket\_versioning to return the versioning state of a bucket \([https\://github\.com/ansible\-collections/amazon\.aws/pull/1919](https\://github\.com/ansible\-collections/amazon\.aws/pull/1919)\)\. * s3\_object\_info \- fix exception raised when listing objects from empty bucket \([https\://github\.com/ansible\-collections/amazon\.aws/pull/1919](https\://github\.com/ansible\-collections/amazon\.aws/pull/1919)\)\. - + #### community\.crypto * x509\_crl \- the new option serial\_numbers allow to configure in which format serial numbers can be provided to revoked\_certificates\[\]\.serial\_number\. The default is as integers \(serial\_numbers\=integer\) for backwards compatibility\; setting serial\_numbers\=hex\-octets allows to specify colon\-separated hex octet strings like 00\:11\:22\:FF \([https\://github\.com/ansible\-collections/community\.crypto/issues/687](https\://github\.com/ansible\-collections/community\.crypto/issues/687)\, [https\://github\.com/ansible\-collections/community\.crypto/pull/715](https\://github\.com/ansible\-collections/community\.crypto/pull/715)\)\. - + #### community\.docker * docker\_compose\_v2 \- allow to wait until containers are running/health when running docker compose up with the new wait option \([https\://github\.com/ansible\-collections/community\.docker/issues/794](https\://github\.com/ansible\-collections/community\.docker/issues/794)\, [https\://github\.com/ansible\-collections/community\.docker/pull/796](https\://github\.com/ansible\-collections/community\.docker/pull/796)\)\. * docker\_container \- the pull\_check\_mode\_behavior option now allows to control the module\'s behavior in check mode when pull\=always \([https\://github\.com/ansible\-collections/community\.docker/issues/792](https\://github\.com/ansible\-collections/community\.docker/issues/792)\, [https\://github\.com/ansible\-collections/community\.docker/pull/797](https\://github\.com/ansible\-collections/community\.docker/pull/797)\)\. * docker\_container \- the pull option now accepts the three values never\, missing\_image \(default\)\, and never\, next to the previously valid values true \(equivalent to always\) and false \(equivalent to missing\_image\)\. This allows the equivalent to \-\-pull\=never from the Docker command line \([https\://github\.com/ansible\-collections/community\.docker/issues/783](https\://github\.com/ansible\-collections/community\.docker/issues/783)\, [https\://github\.com/ansible\-collections/community\.docker/pull/797](https\://github\.com/ansible\-collections/community\.docker/pull/797)\)\. - + #### community\.general * bitwarden lookup plugin \- add bw\_session option\, to pass session key instead of reading from env \([https\://github\.com/ansible\-collections/community\.general/pull/7994](https\://github\.com/ansible\-collections/community\.general/pull/7994)\)\. @@ -727,13 +1380,13 @@ If not mentioned explicitly\, the changes are reported in the combined changelog * postgresql\_db \- add the icu\_locale argument \([https\://github\.com/ansible\-collections/community\.postgresql/issues/666](https\://github\.com/ansible\-collections/community\.postgresql/issues/666)\)\. * postgresql\_db \- add the locale\_provider argument \([https\://github\.com/ansible\-collections/community\.postgresql/issues/666](https\://github\.com/ansible\-collections/community\.postgresql/issues/666)\)\. - + #### community\.routeros * api\_info\, api\_modify \- make path user group modifiable and add comment attribute \([https\://github\.com/ansible\-collections/community\.routeros/issues/256](https\://github\.com/ansible\-collections/community\.routeros/issues/256)\, [https\://github\.com/ansible\-collections/community\.routeros/pull/257](https\://github\.com/ansible\-collections/community\.routeros/pull/257)\)\. * api\_modify\, api\_info \- add support for the ip vrf path in RouterOS 7 \([https\://github\.com/ansible\-collections/community\.routeros/pull/259](https\://github\.com/ansible\-collections/community\.routeros/pull/259)\) - + #### community\.vmware * Add standard function vmware\_argument\_spec\(\) from module\_utils for using default env fallback function\. [https\://github\.com/ansible\-collections/community\.vmware/issues/1977](https\://github\.com/ansible\-collections/community\.vmware/issues/1977) @@ -743,7 +1396,7 @@ If not mentioned explicitly\, the changes are reported in the combined changelog * vmware\_vmkernel \- Add the function to set the enable\_backup\_nfc setting \([https\://github\.com/ansible\-collections/community\.vmware/pull/1978](https\://github\.com/ansible\-collections/community\.vmware/pull/1978)\) * vsphere\_copy \- Add parameter to tell vsphere\_copy which diskformat is being uploaded \([https\://github\.com/ansible\-collections/community\.vmware/pull/1995](https\://github\.com/ansible\-collections/community\.vmware/pull/1995)\)\. - + #### containers\.podman * Add log\_opt and annotaion options to podman\_play module @@ -798,7 +1451,7 @@ If not mentioned explicitly\, the changes are reported in the combined changelog * Add ability to prevent changing login\'s password\, even if password supplied\. * Add new input strings to be compatible with dbops v0\.9\.x \([https\://github\.com/lowlydba/lowlydba\.sqlserver/pull/231](https\://github\.com/lowlydba/lowlydba\.sqlserver/pull/231)\) - + #### netapp\.ontap * na\_ontap\_cifs\_server \- new option is\_multichannel\_enabled added in REST\, requires ONTAP 9\.10 or later\. @@ -833,22 +1486,22 @@ If not mentioned explicitly\, the changes are reported in the combined changelog * fusion\_volume \- Allow creating a new volume from already existing volume or volume snapshot - + ### Deprecated Features * The inspur\.sm collection is considered unmaintained and will be removed from Ansible 11 if no one starts maintaining it again before Ansible 11\. See [the removal process for details on how this works](https\://github\.com/ansible\-collections/overview/blob/main/removal\_from\_ansible\.rst\#cancelling\-removal\-of\-an\-unmaintained\-collection) \([https\://forum\.ansible\.com/t/2854](https\://forum\.ansible\.com/t/2854)\)\. * The netapp\.storagegrid collection is considered unmaintained and will be removed from Ansible 11 if no one starts maintaining it again before Ansible 11\. See [the removal process for details on how this works](https\://github\.com/ansible\-collections/overview/blob/main/removal\_from\_ansible\.rst\#cancelling\-removal\-of\-an\-unmaintained\-collection) \([https\://forum\.ansible\.com/t/2811](https\://forum\.ansible\.com/t/2811)\)\. * The purestorage\.fusion collection is officially unmaintained and has been archived\. Therefore\, it will be removed from Ansible 10 \([https\://forum\.ansible\.com/t/3712](https\://forum\.ansible\.com/t/3712)\)\. - + #### community\.crypto * openssl\_csr\_pipe\, openssl\_privatekey\_pipe\, x509\_certificate\_pipe \- the current behavior of check mode is deprecated and will change in community\.crypto 3\.0\.0\. The current behavior is similar to the modules without \_pipe\: if the object needs to be \(re\-\)generated\, only the changed status is set\, but the object is not updated\. From community\.crypto 3\.0\.0 on\, the modules will ignore check mode and always act as if check mode is not active\. This behavior can already achieved now by adding check\_mode\: false to the task\. If you think this breaks your use\-case of this module\, please [create an issue in the community\.crypto repository](https\://github\.com/ansible\-collections/community\.crypto/issues/new/choose) \([https\://github\.com/ansible\-collections/community\.crypto/issues/712](https\://github\.com/ansible\-collections/community\.crypto/issues/712)\, [https\://github\.com/ansible\-collections/community\.crypto/pull/714](https\://github\.com/ansible\-collections/community\.crypto/pull/714)\)\. - + ### Bugfixes - + #### Ansible\-core * Fix loading vars\_plugins in roles \([https\://github\.com/ansible/ansible/issues/82239](https\://github\.com/ansible/ansible/issues/82239)\)\. @@ -856,32 +1509,32 @@ If not mentioned explicitly\, the changes are reported in the combined changelog * include\_vars \- fix calculating depth relative to the root and ensure all files are included \([https\://github\.com/ansible/ansible/issues/80987](https\://github\.com/ansible/ansible/issues/80987)\)\. * templating \- ensure syntax errors originating from a template being compiled into Python code object result in a failure \([https\://github\.com/ansible/ansible/issues/82606](https\://github\.com/ansible/ansible/issues/82606)\) - + #### amazon\.aws * backup\_plan \- Fix idempotency issue when using botocore \>\= 1\.31\.36 \([https\://github\.com/ansible\-collections/amazon\.aws/issues/1952](https\://github\.com/ansible\-collections/amazon\.aws/issues/1952)\)\. * plugins/inventory/aws\_ec2 \- Fix failure when retrieving information for more than 40 instances with use\_ssm\_inventory \([https\://github\.com/ansible\-collections/amazon\.aws/issues/1713](https\://github\.com/ansible\-collections/amazon\.aws/issues/1713)\)\. - + #### community\.crypto * luks\_device \- fixed module a bug that prevented using remove\_keyslot with the value 0 \([https\://github\.com/ansible\-collections/community\.crypto/pull/710](https\://github\.com/ansible\-collections/community\.crypto/pull/710)\)\. * luks\_device \- fixed module falsely outputting changed\=false when trying to add a new slot with a key that is already present in another slot\. The module now rejects adding keys that are already present in another slot \([https\://github\.com/ansible\-collections/community\.crypto/pull/710](https\://github\.com/ansible\-collections/community\.crypto/pull/710)\)\. * luks\_device \- fixed testing of LUKS passphrases in when specifying a keyslot for cryptsetup version 2\.0\.3\. The output of this cryptsetup version slightly differs from later versions \([https\://github\.com/ansible\-collections/community\.crypto/pull/710](https\://github\.com/ansible\-collections/community\.crypto/pull/710)\)\. - + #### community\.dns * Update Public Suffix List\. - + #### community\.docker * docker\_compose\_v2 \- do not consider a Waiting event as an action/change \([https\://github\.com/ansible\-collections/community\.docker/pull/804](https\://github\.com/ansible\-collections/community\.docker/pull/804)\)\. * docker\_compose\_v2 \- do not treat service\-level pull events as changes to avoid incorrect changed\=true return value of pull\=always \([https\://github\.com/ansible\-collections/community\.docker/issues/802](https\://github\.com/ansible\-collections/community\.docker/issues/802)\, [https\://github\.com/ansible\-collections/community\.docker/pull/803](https\://github\.com/ansible\-collections/community\.docker/pull/803)\)\. * docker\_compose\_v2\, docker\_compose\_v2\_pull \- fix parsing of pull messages for Docker Compose 2\.20\.0 \([https\://github\.com/ansible\-collections/community\.docker/issues/785](https\://github\.com/ansible\-collections/community\.docker/issues/785)\, [https\://github\.com/ansible\-collections/community\.docker/pull/786](https\://github\.com/ansible\-collections/community\.docker/pull/786)\)\. - + #### community\.general * cargo \- fix idempotency issues when using a custom installation path for packages \(using the \-\-path parameter\)\. The initial installation runs fine\, but subsequent runs use the get\_installed\(\) function which did not check the given installation location\, before running cargo install\. This resulted in a false changed state\. Also the removal of packeges using state\: absent failed\, as the installation check did not use the given parameter \([https\://github\.com/ansible\-collections/community\.general/pull/7970](https\://github\.com/ansible\-collections/community\.general/pull/7970)\)\. @@ -909,12 +1562,12 @@ If not mentioned explicitly\, the changes are reported in the combined changelog * postgresql\_privs \- fix a failure when altering privileges with grant\_option\: true \([https\://github\.com/ansible\-collections/community\.postgresql/issues/668](https\://github\.com/ansible\-collections/community\.postgresql/issues/668)\)\. - + #### community\.routeros * facts \- fix date not getting removed for idempotent config export \([https\://github\.com/ansible\-collections/community\.routeros/pull/262](https\://github\.com/ansible\-collections/community\.routeros/pull/262)\)\. - + #### containers\.podman * Add idempotency for podman\_secret module @@ -951,7 +1604,7 @@ If not mentioned explicitly\, the changes are reported in the combined changelog * Reduced the size of module\_arg\_spec in each module\. * Removed most of the sanity test ignores\. - + #### fortinet\.fortios * Github issue @@ -962,7 +1615,7 @@ If not mentioned explicitly\, the changes are reported in the combined changelog * Add ActiveStartDate to the compare properties so this item is marked accurately as changed\. * Fixed the formatting of the SPN by updating the backslash to a forward\-slash for the \$spn var \(lowlydba\.sqlserver\.spn\) - + #### netapp\.ontap * na\_ontap\_igroup\_initiator \- fixed issue with idempotency\. @@ -977,7 +1630,7 @@ If not mentioned explicitly\, the changes are reported in the combined changelog * netbox\_vlan \- Fix documentation of vlan\_group \[\#1138\]\([https\://github\.com/netbox\-community/ansible\_modules/pull/1138](https\://github\.com/netbox\-community/ansible\_modules/pull/1138)\) - + ### New Plugins @@ -985,7 +1638,7 @@ If not mentioned explicitly\, the changes are reported in the combined changelog * community\.general\.default\_without\_diff \- The default ansible callback without diff output - + #### Filter * community\.crypto\.parse\_serial \- Convert a serial number as a colon\-separated list of hex numbers to an integer @@ -995,16 +1648,16 @@ If not mentioned explicitly\, the changes are reported in the combined changelog * community\.general\.lists\_symmetric\_difference \- Symmetric Difference of lists with a predictive order * community\.general\.lists\_union \- Union of lists with a predictive order - + ### New Modules - + #### community\.general * community\.general\.gitlab\_group\_access\_token \- Manages GitLab group access tokens * community\.general\.gitlab\_project\_access\_token \- Manages GitLab project access tokens - + #### containers\.podman * containers\.podman\.podman\_secret\_info \- Secrets info module @@ -1044,7 +1697,7 @@ If not mentioned explicitly\, the changes are reported in the combined changelog * netbox\.netbox\.netbox\_virtual\_disk \- Create\, updates\, or removes a disk from a Virtual Machine - + ### Unchanged Collections * ansible\.netcommon \(still version 5\.3\.0\) @@ -1128,93 +1781,93 @@ If not mentioned explicitly\, the changes are reported in the combined changelog ## v9\.2\.0 -- Release Summary +- Release Summary - Added Collections -- Ansible\-core -- Changed Collections -- Major Changes - - community\.docker +- Ansible\-core +- Changed Collections +- Major Changes + - community\.docker - community\.hashi\_vault - dellemc\.openmanage - infoblox\.nios\_modules -- Minor Changes - - amazon\.aws +- Minor Changes + - amazon\.aws - check\_point\.mgmt - - cisco\.ise - - cisco\.meraki - - community\.aws - - community\.crypto + - cisco\.ise + - cisco\.meraki + - community\.aws + - community\.crypto - community\.digitalocean - - community\.dns - - community\.docker - - community\.general + - community\.dns + - community\.docker + - community\.general - community\.grafana - - community\.hrobot + - community\.hrobot - community\.postgresql - - community\.routeros - - community\.vmware + - community\.routeros + - community\.vmware - community\.zabbix - dellemc\.enterprise\_sonic - dellemc\.openmanage - grafana\.grafana - ibm\.storage\_virtualize - - netapp\.ontap + - netapp\.ontap - netbox\.netbox - purestorage\.flasharray - - purestorage\.flashblade + - purestorage\.flashblade - vultr\.cloud -- Deprecated Features - - community\.dns - - community\.docker - - community\.general - - community\.hrobot +- Deprecated Features + - community\.dns + - community\.docker + - community\.general + - community\.hrobot - Security Fixes - - Ansible\-core -- Bugfixes - - Ansible\-core - - amazon\.aws + - Ansible\-core +- Bugfixes + - Ansible\-core + - amazon\.aws - check\_point\.mgmt - - cisco\.meraki - - community\.aws - - community\.crypto + - cisco\.meraki + - community\.aws + - community\.crypto - community\.digitalocean - - community\.dns - - community\.docker - - community\.general + - community\.dns + - community\.docker + - community\.general - community\.grafana - community\.postgresql - community\.sap\_libs - - community\.vmware + - community\.vmware - community\.zabbix - dellemc\.enterprise\_sonic - dellemc\.openmanage - fortinet\.fortimanager - infoblox\.nios\_modules - - netapp\.ontap + - netapp\.ontap - netbox\.netbox - purestorage\.flasharray - - purestorage\.flashblade + - purestorage\.flashblade - vultr\.cloud - Known Issues - dellemc\.openmanage -- New Plugins +- New Plugins - Connection - - Filter + - Filter - Lookup -- New Modules +- New Modules - check\_point\.mgmt - community\.digitalocean - - community\.docker - - community\.general + - community\.docker + - community\.general - dellemc\.enterprise\_sonic - dellemc\.openmanage - infoblox\.nios\_modules - - netapp\.ontap - - purestorage\.flashblade + - netapp\.ontap + - purestorage\.flashblade - vultr\.cloud -- Unchanged Collections +- Unchanged Collections - + ### Release Summary Release Date\: 2024\-01\-30 @@ -1226,7 +1879,7 @@ Release Date\: 2024\-01\-30 * community\.library\_inventory\_filtering\_v1 \(version 1\.0\.0\) - + ### Ansible\-core Ansible 9\.2\.0 contains ansible\-core version 2\.16\.3\. @@ -1234,7 +1887,7 @@ This is a newer version than version 2\.16\.1 contained in the previous Ansible The changes are reported in the combined changelog below\. - + ### Changed Collections If not mentioned explicitly\, the changes are reported in the combined changelog below\. @@ -1276,10 +1929,10 @@ If not mentioned explicitly\, the changes are reported in the combined changelog | purestorage.flashblade | 1.14.0 | 1.15.0 | | | vultr.cloud | 1.10.1 | 1.12.1 | | - + ### Major Changes - + #### community\.docker * The community\.docker collection now depends on the community\.library\_inventory\_filtering\_v1 collection\. This utility collection provides host filtering functionality for inventory plugins\. If you use the Ansible community package\, both collections are included and you do not have to do anything special\. If you install the collection with ansible\-galaxy collection install\, it will be installed automatically\. If you install the collection by copying the files of the collection to a place where ansible\-core can find it\, for example by cloning the git repository\, you need to make sure that you also have to install the dependency if you are using the inventory plugins \([https\://github\.com/ansible\-collections/community\.docker/pull/698](https\://github\.com/ansible\-collections/community\.docker/pull/698)\)\. @@ -1304,10 +1957,10 @@ If not mentioned explicitly\, the changes are reported in the combined changelog * Upgrade Ansible version support from 2\.13 to 2\.16\. * Upgrade Python version support from 3\.8 to 3\.10\. - + ### Minor Changes - + #### amazon\.aws * autoscaling\_group \- minor PEP8 whitespace sanity fixes \([https\://github\.com/ansible\-collections/amazon\.aws/pull/1846](https\://github\.com/ansible\-collections/amazon\.aws/pull/1846)\)\. @@ -1360,24 +2013,24 @@ If not mentioned explicitly\, the changes are reported in the combined changelog * New resource modules for R81\.20 JHF Take 43 * meta/runtime\.yml \- update minimum Ansible version required to 2\.14\.0\. - + #### cisco\.ise * cisco\.ise collection now supports ansible\.utils v3 - + #### cisco\.meraki * Adding support to ansible\.utils \"\>\=2\.0\.0\, \<4\.00\"\. - + #### community\.aws * aws\_ssm \- Updated the documentation to explicitly state that an S3 bucket is required\, the behavior of the files in that bucket\, and requirements around that\. \([https\://github\.com/ansible\-collections/community\.aws/issues/1775](https\://github\.com/ansible\-collections/community\.aws/issues/1775)\)\. * cloudfront\_distribution \- added support for cache\_policy\_id and origin\_request\_policy\_id for behaviors \([https\://github\.com/ansible\-collections/community\.aws/pull/1589](https\://github\.com/ansible\-collections/community\.aws/pull/1589)\) * mq\_broker \- add support to wait for broker state via wait and wait\_timeout parameter values \([https\://github\.com/ansible\-collections/community\.aws/pull/1879](https\://github\.com/ansible\-collections/community\.aws/pull/1879)\)\. - + #### community\.crypto * luks\_device \- add allow discards option \([https\://github\.com/ansible\-collections/community\.crypto/pull/693](https\://github\.com/ansible\-collections/community\.crypto/pull/693)\)\. @@ -1388,14 +2041,14 @@ If not mentioned explicitly\, the changes are reported in the combined changelog * digital\_ocean\_kubernetes \- add project\_name parameter \([https\://github\.com/ansible\-collections/community\.digitalocean/issues/264](https\://github\.com/ansible\-collections/community\.digitalocean/issues/264)\)\. * fix sanity tests \([https\://github\.com/ansible\-collections/community\.digitalocean/issues/323](https\://github\.com/ansible\-collections/community\.digitalocean/issues/323)\)\. - + #### community\.dns * hetzner\_dns\_records and hosttech\_dns\_records inventory plugins \- the filters option has been renamed to simple\_filters\. The old name still works until community\.hrobot 2\.0\.0\. Then it will change to allow more complex filtering with the community\.library\_inventory\_filtering\_v1 collection\'s functionality \([https\://github\.com/ansible\-collections/community\.dns/pull/181](https\://github\.com/ansible\-collections/community\.dns/pull/181)\)\. * nameserver\_info and nameserver\_record\_info \- add server parameter to specify custom DNS servers \([https\://github\.com/ansible\-collections/community\.dns/pull/168](https\://github\.com/ansible\-collections/community\.dns/pull/168)\, [https\://github\.com/ansible\-collections/community\.dns/pull/178](https\://github\.com/ansible\-collections/community\.dns/pull/178)\)\. * wait\_for\_txt \- add server parameter to specify custom DNS servers \([https\://github\.com/ansible\-collections/community\.dns/pull/178](https\://github\.com/ansible\-collections/community\.dns/pull/178)\)\. - + #### community\.docker * The ca\_cert option available to almost all modules and plugins has been renamed to ca\_path\. The name ca\_path is also used for similar options in ansible\-core and other collections\. The old name has been added as an alias and can still be used \([https\://github\.com/ansible\-collections/community\.docker/pull/744](https\://github\.com/ansible\-collections/community\.docker/pull/744)\)\. @@ -1409,7 +2062,7 @@ If not mentioned explicitly\, the changes are reported in the combined changelog * docker\_image \- allow to specify memory size and swap memory size in other units than bytes \([https\://github\.com/ansible\-collections/community\.docker/pull/727](https\://github\.com/ansible\-collections/community\.docker/pull/727)\)\. * inventory plugins \- add filter option which allows to include and exclude hosts based on Jinja2 conditions \([https\://github\.com/ansible\-collections/community\.docker/pull/698](https\://github\.com/ansible\-collections/community\.docker/pull/698)\, [https\://github\.com/ansible\-collections/community\.docker/issues/610](https\://github\.com/ansible\-collections/community\.docker/issues/610)\)\. - + #### community\.general * consul\_auth\_method\, consul\_binding\_rule\, consul\_policy\, consul\_role\, consul\_session\, consul\_token \- added action group community\.general\.consul \([https\://github\.com/ansible\-collections/community\.general/pull/7897](https\://github\.com/ansible\-collections/community\.general/pull/7897)\)\. @@ -1444,7 +2097,7 @@ If not mentioned explicitly\, the changes are reported in the combined changelog * Add support for Grafana Tempo datasource type \([https\://grafana\.com/docs/grafana/latest/datasources/tempo/](https\://grafana\.com/docs/grafana/latest/datasources/tempo/)\) * default to true/false in docs and code - + #### community\.hrobot * robot inventory plugin \- the filters option has been renamed to simple\_filters\. The old name still works until community\.hrobot 2\.0\.0\. Then it will change to allow more complex filtering with the community\.library\_inventory\_filtering\_v1 collection\'s functionality \([https\://github\.com/ansible\-collections/community\.hrobot/pull/94](https\://github\.com/ansible\-collections/community\.hrobot/pull/94)\)\. @@ -1459,7 +2112,7 @@ If not mentioned explicitly\, the changes are reported in the combined changelog * postgresql\_subscription \- add the comment argument \([https\://github\.com/ansible\-collections/community\.postgresql/issues/354](https\://github\.com/ansible\-collections/community\.postgresql/issues/354)\)\. * postgresql\_tablespace \- add the comment argument \([https\://github\.com/ansible\-collections/community\.postgresql/issues/354](https\://github\.com/ansible\-collections/community\.postgresql/issues/354)\)\. - + #### community\.routeros * api\_info\, api\_modify \- add interface ovpn\-client path \([https\://github\.com/ansible\-collections/community\.routeros/issues/242](https\://github\.com/ansible\-collections/community\.routeros/issues/242)\, [https\://github\.com/ansible\-collections/community\.routeros/pull/244](https\://github\.com/ansible\-collections/community\.routeros/pull/244)\)\. @@ -1470,7 +2123,7 @@ If not mentioned explicitly\, the changes are reported in the combined changelog * api\_info\, api\_modify \- removed host primary key in tool netwatch path \([https\://github\.com/ansible\-collections/community\.routeros/pull/248](https\://github\.com/ansible\-collections/community\.routeros/pull/248)\)\. * api\_modify\, api\_info \- added support for interface wifiwave2 \([https\://github\.com/ansible\-collections/community\.routeros/pull/226](https\://github\.com/ansible\-collections/community\.routeros/pull/226)\)\. - + #### community\.vmware * vmware\_guest \- Add IPv6 support for VM network interfaces \([https\://github\.com/ansible\-collections/community\.vmware/pull/1937](https\://github\.com/ansible\-collections/community\.vmware/pull/1937)\)\. @@ -1569,7 +2222,7 @@ If not mentioned explicitly\, the changes are reported in the combined changelog * ibm\_svc\_info \- Added support to display information about thinclone/clone volumes and volumegroups\. * ibm\_svc\_manage\_volumgroup \- Added support to delete volumegroups keeping volumes via \'evictvolumes\'\. - + #### netapp\.ontap * na\_ontap\_cifs\_server \- new option lm\_compatibility\_level added in REST\, requires ONTAP 9\.8 or later\. @@ -1599,7 +2252,7 @@ If not mentioned explicitly\, the changes are reported in the combined changelog * purefa\_policy \- Added NFS security flavors for accessing files in the mount point\. * purefa\_policy \- Remove default setting for nfs\_version to allow for change of version at policy level - + #### purestorage\.flashblade * purefb\_bucket \- Add support for public buckets @@ -1616,25 +2269,25 @@ If not mentioned explicitly\, the changes are reported in the combined changelog * Implemented a feature to distinguish resources by region if available\. This allows to have identical name per region e\.g\. a VPC named default in each region\. \([https\://github\.com/vultr/ansible\-collection\-vultr/pull/98](https\://github\.com/vultr/ansible\-collection\-vultr/pull/98)\)\. * instance \- Added a new param user\_scheme to change user scheme to non\-root on Linux while creating the instance \([https\://github\.com/vultr/ansible\-collection\-vultr/issues/96](https\://github\.com/vultr/ansible\-collection\-vultr/issues/96)\)\. - + ### Deprecated Features - + #### community\.dns * hetzner\_dns\_records and hosttech\_dns\_records inventory plugins \- the filters option has been renamed to simple\_filters\. The old name will stop working in community\.hrobot 2\.0\.0 \([https\://github\.com/ansible\-collections/community\.dns/pull/181](https\://github\.com/ansible\-collections/community\.dns/pull/181)\)\. - + #### community\.docker * docker\_container \- the default ignore for the image\_name\_mismatch parameter has been deprecated and will switch to recreate in community\.docker 4\.0\.0\. A deprecation warning will be printed in situations where the default value is used and where a behavior would change once the default changes \([https\://github\.com/ansible\-collections/community\.docker/pull/703](https\://github\.com/ansible\-collections/community\.docker/pull/703)\)\. - + #### community\.general * consul\_acl \- the module has been deprecated and will be removed in community\.general 10\.0\.0\. consul\_token and consul\_policy can be used instead \([https\://github\.com/ansible\-collections/community\.general/pull/7901](https\://github\.com/ansible\-collections/community\.general/pull/7901)\)\. - + #### community\.hrobot * robot inventory plugin \- the filters option has been renamed to simple\_filters\. The old name will stop working in community\.hrobot 2\.0\.0 \([https\://github\.com/ansible\-collections/community\.hrobot/pull/94](https\://github\.com/ansible\-collections/community\.hrobot/pull/94)\)\. @@ -1642,15 +2295,15 @@ If not mentioned explicitly\, the changes are reported in the combined changelog ### Security Fixes - + #### Ansible\-core * ANSIBLE\_NO\_LOG \- Address issue where ANSIBLE\_NO\_LOG was ignored \(CVE\-2024\-0690\) - + ### Bugfixes - + #### Ansible\-core * Run all handlers with the same listen topic\, even when notified from another handler \([https\://github\.com/ansible/ansible/issues/82363](https\://github\.com/ansible/ansible/issues/82363)\)\. @@ -1667,7 +2320,7 @@ If not mentioned explicitly\, the changes are reported in the combined changelog * unsafe data \- Address an incompatibility with AnsibleUnsafeText and AnsibleUnsafeBytes when pickling with protocol\=0 * unsafe data \- Enable directly using AnsibleUnsafeText with Python pathlib \([https\://github\.com/ansible/ansible/issues/82414](https\://github\.com/ansible/ansible/issues/82414)\) - + #### amazon\.aws * ec2\_vpc\_subnet \- cleanly handle failure when subnet isn\'t created in time \([https\://github\.com/ansible\-collections/amazon\.aws/pull/1848](https\://github\.com/ansible\-collections/amazon\.aws/pull/1848)\)\. @@ -1680,19 +2333,19 @@ If not mentioned explicitly\, the changes are reported in the combined changelog * httpapi/checkpoint\.py \- Raise a fatal error if login wasn\'t successful\. - + #### cisco\.meraki * Adding smartquotes \= False to conf\.py and romoving \' from rst files\. * Adding build\_ignore property to galaxy file\. * Adding support to ansible\.utils \>\=3\.0 - + #### community\.aws -* aws\_ssm \- disable enable\-bracketed\-paste to fix issue with amazon linux 2023 and other OSes \([https\://github\.com/ansible\-collections/community\.aws/issues/1756](https\://github\.com/ansible\-collections/community\.aws/issues/1756)\) +* aws\_ssm \- disable enable\-bracketed\-paste to fix issue with amazon linux 2023 and other OSes \([https\://github\.com/ansible\-collections/community\.aws/issues/1756](https\://github\.com/ansible\-collections/community\.aws/issues/1756)\) - + #### community\.crypto * acme\_\* modules \- directly react on bad return data for account creation/retrieval/updating requests \([https\://github\.com/ansible\-collections/community\.crypto/pull/682](https\://github\.com/ansible\-collections/community\.crypto/pull/682)\)\. @@ -1710,13 +2363,13 @@ If not mentioned explicitly\, the changes are reported in the combined changelog * digital\_ocean\_kubernetes \- module didn\'t return kubeconfig properly\, return documentation was invalid\. Fixed version returns data with the same structure all the time\, also it is aligned with M\(community\.digitalocean\.digital\_ocean\_kubernetes\_info\) documentation return data now\. \([https\://github\.com/ansible\-collections/community\.digitalocean/issues/322](https\://github\.com/ansible\-collections/community\.digitalocean/issues/322)\)\. * inventory plugin \- restore reading auth token from env variables \([https\://github\.com/ansible\-collections/community\.digitalocean/pull/315](https\://github\.com/ansible\-collections/community\.digitalocean/pull/315)\)\. - + #### community\.dns * Update Public Suffix List\. * wait\_for\_txt\, nameserver\_info\, nameserver\_record\_info \- when looking up nameservers for a domain\, do not treat NXDOMAIN as a fatal error \([https\://github\.com/ansible\-collections/community\.dns/pull/177](https\://github\.com/ansible\-collections/community\.dns/pull/177)\)\. - + #### community\.docker * Use unix\:///var/run/docker\.sock instead of the legacy unix\://var/run/docker\.sock as default for docker\_host \([https\://github\.com/ansible\-collections/community\.docker/pull/736](https\://github\.com/ansible\-collections/community\.docker/pull/736)\)\. @@ -1727,7 +2380,7 @@ If not mentioned explicitly\, the changes are reported in the combined changelog * modules and plugins using the Docker SDK for Python \- remove tls\_hostname from the parameters passed to Docker SDK for Python 7\.0\.0\+\. Explicitly fail with a nicer error message if it was explicitly set in this case \([https\://github\.com/ansible\-collections/community\.docker/pull/721](https\://github\.com/ansible\-collections/community\.docker/pull/721)\)\. * vendored Docker SDK for Python \- avoid passing on ssl\_version and tls\_hostname if they were not provided by the user\. Remove dead code\. \([https\://github\.com/ansible\-collections/community\.docker/pull/722](https\://github\.com/ansible\-collections/community\.docker/pull/722)\)\. - + #### community\.general * homebrew \- detect already installed formulae and casks using JSON output from brew info \([https\://github\.com/ansible\-collections/community\.general/issues/864](https\://github\.com/ansible\-collections/community\.general/issues/864)\)\. @@ -1760,7 +2413,7 @@ If not mentioned explicitly\, the changes are reported in the combined changelog * fixes failures in sanity test for all modules - + #### community\.vmware * Fix InsecureRequestWarning for modules based on the VmwareRestClient module util when setting validate\_certs to False \([https\://github\.com/ansible\-collections/community\.vmware/pull/1969](https\://github\.com/ansible\-collections/community\.vmware/pull/1969)\)\. @@ -1810,7 +2463,7 @@ If not mentioned explicitly\, the changes are reported in the combined changelog * Fixes index error for transform fields in DTC LBDN \(auth\_zone and Pool\) and DTC POOL \(servers and monitors\) [\#209](https\://github\.com/infobloxopen/infoblox\-ansible/pull/209) * Fixes typo for environment variable INFOBLOX\_WAPI\_VERSION [\#209](https\://github\.com/infobloxopen/infoblox\-ansible/pull/209) - + #### netapp\.ontap * na\_ontap\_nfs \- fix error with windows in REST for ONTAP 9\.10 or earlier\. @@ -1831,7 +2484,7 @@ If not mentioned explicitly\, the changes are reported in the combined changelog * purefa\_ds \- Fix issue with SDK returning empty data for data directory services even when it does exist * purefa\_policy \- Fix incorrect call of psot instead of patch for NFS policies - + #### purestorage\.flashblade * purefb\_info \- Added missing object lock retention details if enabledd @@ -1858,7 +2511,7 @@ If not mentioned explicitly\, the changes are reported in the combined changelog * ome\_diagnostics \- Issue\(279193\) \- Export of SupportAssist collection logs to the share location fails on OME version 4\.0\.0\. * ome\_smart\_fabric\_uplink \- Issue\(186024\) \- The module supported by OpenManage Enterprise Modular\, however it does not allow the creation of multiple uplinks of the same name\. If an uplink is created using the same name as an existing uplink\, then the existing uplink is modified\. - + ### New Plugins @@ -1866,7 +2519,7 @@ If not mentioned explicitly\, the changes are reported in the combined changelog * community\.general\.incus \- Run tasks in Incus instances via the Incus CLI\. - + #### Filter * community\.general\.from\_ini \- Converts INI text input into a dictionary @@ -1877,7 +2530,7 @@ If not mentioned explicitly\, the changes are reported in the combined changelog * community\.general\.github\_app\_access\_token \- Obtain short\-lived Github App Access tokens - + ### New Modules @@ -1895,7 +2548,7 @@ If not mentioned explicitly\, the changes are reported in the combined changelog * community\.digitalocean\.digital\_ocean\_project\_resource\_info \- Gather information about DigitalOcean Project Resources - + #### community\.docker * community\.docker\.docker\_compose\_v2 \- Manage multi\-container Docker applications with Docker Compose CLI plugin @@ -1907,7 +2560,7 @@ If not mentioned explicitly\, the changes are reported in the combined changelog * community\.docker\.docker\_image\_remove \- Remove Docker images * community\.docker\.docker\_image\_tag \- Tag Docker images with new names and/or tags - + #### community\.general * community\.general\.consul\_acl\_bootstrap \- Bootstrap ACLs in Consul @@ -1945,14 +2598,14 @@ If not mentioned explicitly\, the changes are reported in the combined changelog * infoblox\.nios\_modules\.nios\_dtc\_monitor\_tcp \- Configures the Infoblox NIOS DTC TCP monitor * infoblox\.nios\_modules\.nios\_dtc\_topology \- Configures the Infoblox NIOS DTC Topology - + #### netapp\.ontap * netapp\.ontap\.na\_ontap\_cifs\_unix\_symlink\_mapping \- NetApp ONTAP module to manage UNIX symbolic link mapping for CIFS clients\. * netapp\.ontap\.na\_ontap\_cli\_timeout \- NetApp ONTAP module to set the CLI inactivity timeout value\. * netapp\.ontap\.na\_ontap\_snmp\_config \- NetApp ONTAP module to modify SNMP configuration\. - + #### purestorage\.flashblade * purestorage\.flashblade\.purefb\_hardware \- Manage FlashBlade Hardware @@ -1962,7 +2615,7 @@ If not mentioned explicitly\, the changes are reported in the combined changelog * vultr\.cloud\.object\_storage \- Manages object storages on Vultr - + ### Unchanged Collections * ansible\.netcommon \(still version 5\.3\.0\) @@ -2038,21 +2691,21 @@ If not mentioned explicitly\, the changes are reported in the combined changelog ## v9\.1\.0 -- Release Summary -- Ansible\-core -- Changed Collections -- Minor Changes +- Release Summary +- Ansible\-core +- Changed Collections +- Minor Changes - ansible\.utils - ansible\.windows - cisco\.ios - - cisco\.ise + - cisco\.ise - cisco\.nxos - - community\.general - - community\.routeros + - community\.general + - community\.routeros - community\.windows - community\.zabbix - dellemc\.openmanage - - dellemc\.powerflex + - dellemc\.powerflex - f5networks\.f5\_modules - google\.cloud - hetzner\.hcloud @@ -2062,52 +2715,52 @@ If not mentioned explicitly\, the changes are reported in the combined changelog - telekom\_mms\.icinga\_director - theforeman\.foreman - Breaking Changes / Porting Guide - - Ansible\-core -- Security Fixes - - Ansible\-core -- Bugfixes - Ansible\-core +- Security Fixes + - Ansible\-core +- Bugfixes + - Ansible\-core - ansible\.windows - arista\.eos - cisco\.ios - cisco\.iosxr - - cisco\.ise - - cisco\.meraki - - community\.crypto - - community\.dns - - community\.general - - community\.vmware + - cisco\.ise + - cisco\.meraki + - community\.crypto + - community\.dns + - community\.general + - community\.vmware - community\.windows - community\.zabbix - dellemc\.openmanage - hetzner\.hcloud - junipernetworks\.junos - microsoft\.ad - - netapp\.ontap + - netapp\.ontap - purestorage\.flasharray - splunk\.es - theforeman\.foreman - vultr\.cloud - Known Issues - dellemc\.openmanage -- New Plugins - - Filter +- New Plugins + - Filter - Lookup - Test -- New Modules +- New Modules - cisco\.ios - - community\.general + - community\.general - purestorage\.flasharray -- Unchanged Collections +- Unchanged Collections - + ### Release Summary Release Date\: 2023\-12\-05 [Porting Guide](https\://docs\.ansible\.com/ansible/devel/porting\_guides\.html) - + ### Ansible\-core Ansible 9\.1\.0 contains ansible\-core version 2\.16\.1\. @@ -2115,7 +2768,7 @@ This is a newer version than version 2\.16\.0 contained in the previous Ansible The changes are reported in the combined changelog below\. - + ### Changed Collections If not mentioned explicitly\, the changes are reported in the combined changelog below\. @@ -2155,7 +2808,7 @@ If not mentioned explicitly\, the changes are reported in the combined changelog | theforeman.foreman | 3.14.0 | 3.15.0 | | | vultr.cloud | 1.10.0 | 1.10.1 | | - + ### Minor Changes @@ -2181,7 +2834,7 @@ If not mentioned explicitly\, the changes are reported in the combined changelog * ios\_vlans \- added vlan config CLI feature\. * ios\_vrf \- added MDT related keys - + #### cisco\.ise * Services included configuration\, edda\, dataconnect\_services\, subscriber\. @@ -2191,7 +2844,7 @@ If not mentioned explicitly\, the changes are reported in the combined changelog * nxos\_config \- Relax restrictions on I\(src\) parameter so it can be used more like I\(lines\)\. \([https\://github\.com/ansible\-collections/cisco\.nxos/issues/89](https\://github\.com/ansible\-collections/cisco\.nxos/issues/89)\)\. - + #### community\.general * bitwarden lookup plugin \- when looking for items using an item ID\, the item is now accessed directly with bw get item instead of searching through all items\. This doubles the lookup speed \([https\://github\.com/ansible\-collections/community\.general/pull/7468](https\://github\.com/ansible\-collections/community\.general/pull/7468)\)\. @@ -2228,7 +2881,7 @@ If not mentioned explicitly\, the changes are reported in the combined changelog * redfish\_info \- adding the BootProgress property when getting Systems info \([https\://github\.com/ansible\-collections/community\.general/pull/7626](https\://github\.com/ansible\-collections/community\.general/pull/7626)\)\. * ssh\_config \- adds controlmaster\, controlpath and controlpersist parameters \([https\://github\.com/ansible\-collections/community\.general/pull/7456](https\://github\.com/ansible\-collections/community\.general/pull/7456)\)\. - + #### community\.routeros * api\_info\, api\_modify \- add missing DoH parameters doh\-max\-concurrent\-queries\, doh\-max\-server\-connections\, and doh\-timeout to the ip dns path \([https\://github\.com/ansible\-collections/community\.routeros/issues/230](https\://github\.com/ansible\-collections/community\.routeros/issues/230)\, [https\://github\.com/ansible\-collections/community\.routeros/pull/235](https\://github\.com/ansible\-collections/community\.routeros/pull/235)\) @@ -2267,7 +2920,7 @@ If not mentioned explicitly\, the changes are reported in the combined changelog * Ansible lint issues are fixed for the collections\. * Module redfish\_storage\_volume is enhanced to support reboot options and job tracking operation\. - + #### dellemc\.powerflex * Added support for PowerFlex Denver version\(4\.5\.x\) to TB and Config role\. @@ -2337,7 +2990,7 @@ If not mentioned explicitly\, the changes are reported in the combined changelog ### Breaking Changes / Porting Guide - + #### Ansible\-core * assert \- Nested templating may result in an inability for the conditional to be evaluated\. See the porting guide for more information\. @@ -2345,15 +2998,15 @@ If not mentioned explicitly\, the changes are reported in the combined changelog ### Security Fixes - + #### Ansible\-core * templating \- Address issues where internal templating can cause unsafe variables to lose their unsafe designation \(CVE\-2023\-5764\) - + ### Bugfixes - + #### Ansible\-core * Fix issue where an include\_tasks handler in a role was not able to locate a file in tasks/ when tasks\_from was used as a role entry point and main\.yml was not present \([https\://github\.com/ansible/ansible/issues/82241](https\://github\.com/ansible/ansible/issues/82241)\) @@ -2394,13 +3047,13 @@ If not mentioned explicitly\, the changes are reported in the combined changelog * Fix issue in gathered state of interfaces and l3\_interfaces RMs\([https\://github\.com/ansible\-collections/cisco\.iosxr/issues/452](https\://github\.com/ansible\-collections/cisco\.iosxr/issues/452)\, [https\://github\.com/ansible\-collections/cisco\.iosxr/issues/451](https\://github\.com/ansible\-collections/cisco\.iosxr/issues/451)\) - + #### cisco\.ise * Added missing import re in endpoint module * Updated to use ciscoisesdk v2\.1\.1 or newer fixing ciscoisesdk problem\. - + #### cisco\.meraki * Adding network\_clients\_info and network\_client\_info\. @@ -2424,18 +3077,18 @@ If not mentioned explicitly\, the changes are reported in the combined changelog * Removing logs in meraki\.py\. * networks\_syslog\_servers is now just an Update action to API\. - + #### community\.crypto * acme\_\* modules \- also retry requests in case of socket errors\, bad status lines\, and unknown connection errors\; improve error messages in these cases \([https\://github\.com/ansible\-collections/community\.crypto/issues/680](https\://github\.com/ansible\-collections/community\.crypto/issues/680)\)\. - + #### community\.dns * Update Public Suffix List\. * nameserver\_record\_info \- fix crash when more than one record is retrieved \([https\://github\.com/ansible\-collections/community\.dns/pull/172](https\://github\.com/ansible\-collections/community\.dns/pull/172)\)\. - + #### community\.general * apt\-rpm \- the module did not upgrade packages if a newer version exists\. Now the package will be reinstalled if the candidate is newer than the installed version \([https\://github\.com/ansible\-collections/community\.general/issues/7414](https\://github\.com/ansible\-collections/community\.general/issues/7414)\)\. @@ -2453,7 +3106,7 @@ If not mentioned explicitly\, the changes are reported in the combined changelog [https\://github\.com/ansible\-collections/community\.general/pull/7624](https\://github\.com/ansible\-collections/community\.general/pull/7624)\)\. * terraform \- fix multiline string handling in complex variables \([https\://github\.com/ansible\-collections/community\.general/pull/7535](https\://github\.com/ansible\-collections/community\.general/pull/7535)\)\. - + #### community\.vmware * vmware\_vm\_info \- Fix an AttributeError when gathering network information \([https\://github\.com/ansible\-collections/community\.vmware/pull/1919](https\://github\.com/ansible\-collections/community\.vmware/pull/1919)\)\. @@ -2493,7 +3146,7 @@ If not mentioned explicitly\, the changes are reported in the combined changelog * debug\_ldap\_client \- handle failures when attempting to get the krb5 context and default CCache rather than fail with a traceback - + #### netapp\.ontap * na\_ontap\_ems\_destination \- fix field error with certificate\.name for ONTAP 9\.11\.1 or later in REST\. @@ -2537,10 +3190,10 @@ If not mentioned explicitly\, the changes are reported in the combined changelog * ome\_diagnostics \- Issue\(279193\) \- Export of SupportAssist collection logs to the share location fails on OME version 4\.0\.0\. * ome\_smart\_fabric\_uplink \- Issue\(186024\) \- The module supported by OpenManage Enterprise Modular\, however it does not allow the creation of multiple uplinks of the same name\. If an uplink is created using the same name as an existing uplink\, then the existing uplink is modified\. - + ### New Plugins - + #### Filter * ansible\.utils\.fact\_diff \- Find the difference between currently set facts @@ -2555,7 +3208,7 @@ If not mentioned explicitly\, the changes are reported in the combined changelog * community\.general\.fqdn\_valid \- Validates fully\-qualified domain names against RFC 1123 - + ### New Modules @@ -2565,7 +3218,7 @@ If not mentioned explicitly\, the changes are reported in the combined changelog * cisco\.ios\.ios\_evpn\_global \- Resource module to configure L2VPN EVPN\. * cisco\.ios\.ios\_vxlan\_vtep \- Resource module to configure VXLAN VTEP interface\. - + #### community\.general * community\.general\.git\_config\_info \- Read git configuration @@ -2577,7 +3230,7 @@ If not mentioned explicitly\, the changes are reported in the combined changelog * purestorage\.flasharray\.purefa\_hardware \- Manage FlashArray Hardware Identification - + ### Unchanged Collections * amazon\.aws \(still version 7\.0\.0\) @@ -2654,30 +3307,30 @@ If not mentioned explicitly\, the changes are reported in the combined changelog ## v9\.0\.1 -- Release Summary -- Ansible\-core -- Bugfixes -- Unchanged Collections +- Release Summary +- Ansible\-core +- Bugfixes +- Unchanged Collections - + ### Release Summary Release Date\: 2023\-11\-21 [Porting Guide](https\://docs\.ansible\.com/ansible/devel/porting\_guides\.html) - + ### Ansible\-core Ansible 9\.0\.1 contains ansible\-core version 2\.16\.0\. This is the same version of ansible\-core as in the previous Ansible release\. - + ### Bugfixes * Fix the Python package metadata in setup\.cfg to require Python \>\=3\.10 to ensure that pip can properly install ansible on older Python versions\. - + ### Unchanged Collections * amazon\.aws \(still version 7\.0\.0\) @@ -2786,13 +3439,13 @@ This is the same version of ansible\-core as in the previous Ansible release\. ## v9\.0\.0 -- Release Summary +- Release Summary - Removed Collections - Added Collections -- Ansible\-core +- Ansible\-core - Included Collections -- Major Changes - - amazon\.aws +- Major Changes + - amazon\.aws - chocolatey\.chocolatey - cisco\.ios - cisco\.nxos @@ -2800,43 +3453,43 @@ This is the same version of ansible\-core as in the previous Ansible release\. - community\.mysql - community\.postgresql - community\.sap - - community\.vmware + - community\.vmware - fortinet\.fortimanager - - fortinet\.fortios + - fortinet\.fortios - grafana\.grafana -- Minor Changes - - Ansible\-core - - amazon\.aws +- Minor Changes + - Ansible\-core + - amazon\.aws - ansible\.netcommon - ansible\.utils - ansible\.windows - arista\.eos - check\_point\.mgmt - chocolatey\.chocolatey - - cisco\.aci + - cisco\.aci - cisco\.ios - cisco\.iosxr - - cisco\.meraki - - cisco\.mso + - cisco\.meraki + - cisco\.mso - cisco\.nxos - - community\.aws + - community\.aws - community\.ciscosmb - - community\.crypto + - community\.crypto - community\.digitalocean - - community\.dns - - community\.general + - community\.dns + - community\.general - community\.grafana - community\.libvirt - community\.mysql - community\.postgresql - - community\.routeros - - community\.vmware + - community\.routeros + - community\.vmware - community\.windows - community\.zabbix - - containers\.podman + - containers\.podman - dellemc\.enterprise\_sonic - dellemc\.openmanage - - dellemc\.powerflex + - dellemc\.powerflex - dellemc\.unity - f5networks\.f5\_modules - fortinet\.fortimanager @@ -2847,11 +3500,11 @@ This is the same version of ansible\-core as in the previous Ansible release\. - junipernetworks\.junos - lowlydba\.sqlserver - microsoft\.ad - - netapp\.ontap + - netapp\.ontap - netbox\.netbox - ovirt\.ovirt - purestorage\.flasharray - - purestorage\.flashblade + - purestorage\.flashblade - purestorage\.fusion - sensu\.sensu\_go - t\_systems\_mms\.icinga\_director @@ -2859,24 +3512,24 @@ This is the same version of ansible\-core as in the previous Ansible release\. - vultr\.cloud - vyos\.vyos - Breaking Changes / Porting Guide - - Ansible\-core - - amazon\.aws - - community\.aws - - community\.general + - Ansible\-core + - amazon\.aws + - community\.aws + - community\.general - community\.hashi\_vault - - community\.vmware + - community\.vmware - dellemc\.enterprise\_sonic - hetzner\.hcloud -- Deprecated Features - - Ansible\-core - - amazon\.aws +- Deprecated Features + - Ansible\-core + - amazon\.aws - ansible\.netcommon - ansible\.windows - cisco\.ios - cisco\.iosxr - community\.ciscosmb - - community\.crypto - - community\.general + - community\.crypto + - community\.general - community\.postgresql - community\.sap - community\.windows @@ -2885,112 +3538,112 @@ This is the same version of ansible\-core as in the previous Ansible release\. - purestorage\.fusion - t\_systems\_mms\.icinga\_director - Removed Features \(previously deprecated\) - - Ansible\-core + - Ansible\-core - ansible\.windows - cisco\.ios - cisco\.nxos - community\.ciscosmb - - community\.general + - community\.general - community\.hashi\_vault - - community\.vmware + - community\.vmware - community\.windows - dellemc\.openmanage - hetzner\.hcloud - Security Fixes - - Ansible\-core -- Bugfixes - - Ansible\-core - - amazon\.aws + - Ansible\-core +- Bugfixes + - Ansible\-core + - amazon\.aws - ansible\.netcommon - ansible\.utils - ansible\.windows - arista\.eos - check\_point\.mgmt - chocolatey\.chocolatey - - cisco\.aci + - cisco\.aci - cisco\.ios - cisco\.iosxr - - cisco\.ise - - cisco\.meraki - - cisco\.mso + - cisco\.ise + - cisco\.meraki + - cisco\.mso - cisco\.nxos - cloud\.common - cloudscale\_ch\.cloud - - community\.aws + - community\.aws - community\.ciscosmb - - community\.crypto + - community\.crypto - community\.digitalocean - - community\.dns - - community\.docker - - community\.general + - community\.dns + - community\.docker + - community\.general - community\.grafana - community\.hashi\_vault - - community\.hrobot + - community\.hrobot - community\.libvirt - community\.mysql - community\.network - community\.postgresql - - community\.routeros + - community\.routeros - community\.sops - - community\.vmware + - community\.vmware - community\.windows - community\.zabbix - - containers\.podman + - containers\.podman - dellemc\.enterprise\_sonic - dellemc\.openmanage - f5networks\.f5\_modules - fortinet\.fortimanager - - fortinet\.fortios + - fortinet\.fortios - google\.cloud - hetzner\.hcloud - junipernetworks\.junos - microsoft\.ad - - netapp\.ontap + - netapp\.ontap - netbox\.netbox - ovirt\.ovirt - purestorage\.flasharray - - purestorage\.flashblade + - purestorage\.flashblade - purestorage\.fusion - t\_systems\_mms\.icinga\_director - theforeman\.foreman - vultr\.cloud - vyos\.vyos - Known Issues - - Ansible\-core - - community\.crypto - - community\.dns - - community\.docker - - community\.general - - community\.hrobot - - community\.routeros + - Ansible\-core + - community\.crypto + - community\.dns + - community\.docker + - community\.general + - community\.hrobot + - community\.routeros - community\.sops - dellemc\.openmanage -- New Plugins +- New Plugins - Cliconf - - Filter + - Filter - Inventory - Lookup -- New Modules - - amazon\.aws +- New Modules + - amazon\.aws - cisco\.ios - cisco\.iosxr - cisco\.nxos - cloudscale\_ch\.cloud - - community\.aws - - community\.dns - - community\.general + - community\.aws + - community\.dns + - community\.general - community\.grafana - - community\.vmware + - community\.vmware - community\.zabbix - - containers\.podman + - containers\.podman - dellemc\.enterprise\_sonic - dellemc\.openmanage - - dellemc\.powerflex + - dellemc\.powerflex - dellemc\.unity - f5networks\.f5\_modules - fortinet\.fortimanager - inspur\.ispim - - netapp\.ontap + - netapp\.ontap - netbox\.netbox - ngine\_io\.exoscale - purestorage\.flasharray @@ -2999,9 +3652,9 @@ This is the same version of ansible\-core as in the previous Ansible release\. - theforeman\.foreman - vultr\.cloud - New Roles -- Unchanged Collections +- Unchanged Collections - + ### Release Summary \[YANKED\] Release Date\: 2023\-11\-21 [Porting Guide](https\://docs\.ansible\.com/ansible/devel/porting\_guides\.html) @@ -3022,7 +3675,7 @@ This is the same version of ansible\-core as in the previous Ansible release\. * ibm\.storage\_virtualize \(version 2\.1\.0\) * telekom\_mms\.icinga\_director \(version 1\.34\.1\) - + ### Ansible\-core Ansible 9\.0\.0 contains ansible\-core version 2\.16\.0\. @@ -3118,10 +3771,10 @@ If not mentioned explicitly\, the changes are reported in the combined changelog | vyos.vyos | 4.0.2 | 4.1.0 | | | wti.remote | 1.0.4 | 1.0.5 | Unfortunately, this collection does not provide changelog data in a format that can be processed by the changelog generator. | - + ### Major Changes - + #### amazon\.aws * aws\_region\_info \- The module has been migrated from the community\.aws collection\. Playbooks using the Fully Qualified Collection Name for this module should be updated to use amazon\.aws\.aws\_region\_info\. @@ -3181,7 +3834,7 @@ If not mentioned explicitly\, the changes are reported in the combined changelog * all modules \- everything is now a redirect to the new collection community\.sap\_libs - + #### community\.vmware * vmware\_vasa \- added a new module to register/unregister a VASA provider @@ -3193,7 +3846,7 @@ If not mentioned explicitly\, the changes are reported in the combined changelog * Support all FortiManager versions in 6\.2\, 6\.4\, 7\.0\, 7\.2 and 7\.4\. 139 new modules\. * Support token based authentication\. - + #### fortinet\.fortios * Add new fortios version 7\.4\.1\. @@ -3218,12 +3871,12 @@ If not mentioned explicitly\, the changes are reported in the combined changelog * Grafana Plugins support on\-prem Grafana installation by \@ishanjainn * Updated Service for flow mode by \@bentonam - + ### Minor Changes * Move setuptools configuration into the declarative setup\.cfg format\. ansible sdists still contain a stub setup\.py file\, but we recommend that users move to tools like pip and build and the PEP 517 interface instead of setuptools\' deprecated setup\.py interface \([https\://github\.com/ansible\-community/antsibull/pull/530](https\://github\.com/ansible\-community/antsibull/pull/530)\)\. - + #### Ansible\-core * Add Python type hints to the Display class \([https\://github\.com/ansible/ansible/issues/80841](https\://github\.com/ansible/ansible/issues/80841)\) @@ -3320,7 +3973,7 @@ If not mentioned explicitly\, the changes are reported in the combined changelog * user \- add new option password\_expire\_warn \(supported on Linux only\) to set the number of days of warning before a password change is required \([https\://github\.com/ansible/ansible/issues/79882](https\://github\.com/ansible/ansible/issues/79882)\)\. * yum\_repository \- Align module documentation with parameters - + #### amazon\.aws * amazon\.aws collection \- apply isort code formatting to ensure consistent formatting of code \([https\://github\.com/ansible\-collections/amazon\.aws/pull/1771](https\://github\.com/ansible\-collections/amazon\.aws/pull/1771)\)\. @@ -3393,7 +4046,7 @@ If not mentioned explicitly\, the changes are reported in the combined changelog * All modules \- Ensure modules are compatible with both Chocolatey CLI v2\.x and v1\.x * win\_chocolatey \- Improve error messages when installation of Chocolatey CLI v2\.x fails due to unmet \.NET Framework 4\.8 dependency on client - + #### cisco\.aci * Add 8\.0 option for dvs\_version attribute in aci\_vmm\_controller @@ -3467,7 +4120,7 @@ If not mentioned explicitly\, the changes are reported in the combined changelog * iosxr\_facts \- Add CPU utilization\. * iosxr\_l2\_interfaces \- fix issue in supporting multiple iosxr version\. \([https\://github\.com/ansible\-collections/cisco\.iosxr/issues/379](https\://github\.com/ansible\-collections/cisco\.iosxr/issues/379)\)\. - + #### cisco\.meraki * administered\_identities\_me\_info \- new plugin\. @@ -3900,7 +4553,7 @@ If not mentioned explicitly\, the changes are reported in the combined changelog * organizations\_webhooks\_logs\_info \- new plugin\. * organizations\_wireless\_devices\_ethernet\_statuses\_info \- new plugin\. - + #### cisco\.mso * Add login domain attribute to mso httpapi connection plugin with restructure of connection parameter handling @@ -3920,7 +4573,7 @@ If not mentioned explicitly\, the changes are reported in the combined changelog * nxos\_user \- Added dev\-ops role to BUILTINS \([https\://github\.com/ansible\-collections/cisco\.nxos/issues/690](https\://github\.com/ansible\-collections/cisco\.nxos/issues/690)\) * route\_maps \- support extcommunity rt option \([https\://github\.com/ansible\-collections/cisco\.nxos/issues/743](https\://github\.com/ansible\-collections/cisco\.nxos/issues/743)\)\. - + #### community\.aws * api\_gateway \- add support for parameters name\, lookup\, tags and purge\_tags \([https\://github\.com/ansible\-collections/community\.aws/pull/1845](https\://github\.com/ansible\-collections/community\.aws/pull/1845)\)\. @@ -3944,7 +4597,7 @@ If not mentioned explicitly\, the changes are reported in the combined changelog * removed unused portion of code in cliconf/ciscosmb\.yml * test Ansible 2\.14 - + #### community\.crypto * acme\_certificate \- allow to use no challenge by providing no challenge for the challenge option\. This is needed for ACME servers where validation is done without challenges \([https\://github\.com/ansible\-collections/community\.crypto/issues/613](https\://github\.com/ansible\-collections/community\.crypto/issues/613)\, [https\://github\.com/ansible\-collections/community\.crypto/pull/615](https\://github\.com/ansible\-collections/community\.crypto/pull/615)\)\. @@ -3964,13 +4617,13 @@ If not mentioned explicitly\, the changes are reported in the combined changelog * tests \- run C\(psf/black\) across all files \([https\://github\.com/ansible\-collections/community\.digitalocean/pull/310](https\://github\.com/ansible\-collections/community\.digitalocean/pull/310)\)\. * tests \- test against Ansible Core 2\.12\, 2\.13\, and 2\.14 \([https\://github\.com/ansible\-collections/community\.digitalocean/pull/310](https\://github\.com/ansible\-collections/community\.digitalocean/pull/310)\)\. - + #### community\.dns * wait\_for\_txt \- add servfail\_retries parameter that allows retrying after SERVFAIL errors \([https\://github\.com/ansible\-collections/community\.dns/pull/159](https\://github\.com/ansible\-collections/community\.dns/pull/159)\)\. * wait\_for\_txt\, resolver module utils \- use [EDNS](https\://en\.wikipedia\.org/wiki/Extension\_Mechanisms\_for\_DNS) \([https\://github\.com/ansible\-collections/community\.dns/pull/158](https\://github\.com/ansible\-collections/community\.dns/pull/158)\)\. - + #### community\.general * The collection will start using semantic markup \([https\://github\.com/ansible\-collections/community\.general/pull/6539](https\://github\.com/ansible\-collections/community\.general/pull/6539)\)\. @@ -4139,7 +4792,7 @@ If not mentioned explicitly\, the changes are reported in the combined changelog * postgresql\_privs \- added support for implicit roles CURRENT\_ROLE\, CURRENT\_USER\, and SESSION\_USER \([https\://github\.com/ansible\-collections/community\.postgresql/pull/502](https\://github\.com/ansible\-collections/community\.postgresql/pull/502)\)\. * postgresql\_tablespace \- added idempotence when dropping a non\-existing tablespace \([https\://github\.com/ansible\-collections/community\.postgresql/pull/554](https\://github\.com/ansible\-collections/community\.postgresql/pull/554)\)\. - + #### community\.routeros * api\_info \- add new include\_read\_only option to select behavior for read\-only values\. By default these are not returned \([https\://github\.com/ansible\-collections/community\.routeros/pull/213](https\://github\.com/ansible\-collections/community\.routeros/pull/213)\)\. @@ -4165,7 +4818,7 @@ If not mentioned explicitly\, the changes are reported in the combined changelog * api\_modify \- add new handle\_read\_only and handle\_write\_only options to handle the module\'s behavior for read\-only and write\-only fields \([https\://github\.com/ansible\-collections/community\.routeros/pull/213](https\://github\.com/ansible\-collections/community\.routeros/pull/213)\)\. * api\_modify\, api\_info \- support API paths routing id\, routing bgp connection \([https\://github\.com/ansible\-collections/community\.routeros/pull/220](https\://github\.com/ansible\-collections/community\.routeros/pull/220)\)\. - + #### community\.vmware * Removed module / plugin documentation RST files from the repository \([https\://github\.com/ansible\-collections/community\.vmware/pull/1897](https\://github\.com/ansible\-collections/community\.vmware/pull/1897)\)\. @@ -4206,7 +4859,7 @@ If not mentioned explicitly\, the changes are reported in the combined changelog * zabbix\_settings module added * zabbix\_token module added - + #### containers\.podman * Update docs @@ -4305,7 +4958,7 @@ If not mentioned explicitly\, the changes are reported in the combined changelog * Role idrac\_os\_deployment is enhanced to remove the auto installation of required libraries and to support custom ISO and kickstart file as input\. * Updated the idrac\_gather\_facts role to use jinja template filters\. - + #### dellemc\.powerflex * Added Ansible role to support creation and deletion of protection domain\, storage pool and fault set\. @@ -4460,7 +5113,7 @@ If not mentioned explicitly\, the changes are reported in the combined changelog * microsoft\.ad\.ldap \- Added the option filter\_without\_computer to not add the AND clause objectClass\=computer to the final filter used \- [https\://github\.com/ansible\-collections/microsoft\.ad/issues/55](https\://github\.com/ansible\-collections/microsoft\.ad/issues/55) * microsoft\.ad\.ldap \- Allow setting LDAP connection and authentication options through environment variables \- [https\://github\.com/ansible\-collections/microsoft\.ad/issues/34](https\://github\.com/ansible\-collections/microsoft\.ad/issues/34) - + #### netapp\.ontap * na\_ontap\_broadcast\_domain \- changed documentation for ipspace as it is required while using REST\. @@ -4526,7 +5179,7 @@ If not mentioned explicitly\, the changes are reported in the combined changelog * purefa\_snap \- Added new parameter to support snapshot throttling * purefa\_vg \- Add rename parameter - + #### purestorage\.flashblade * purefb\_bucket\_replica \- Added support for cascading replica links @@ -4619,14 +5272,14 @@ If not mentioned explicitly\, the changes are reported in the combined changelog ### Breaking Changes / Porting Guide - + #### Ansible\-core * Any plugin using the config system and the cli entry to use the timeout from the command line\, will see the value change if the use had configured it in any of the lower precedence methods\. If relying on this behaviour to consume the global/generic timeout from the DEFAULT\_TIMEOUT constant\, please consult the documentation on plugin configuration to add the overlaping entries\. * ansible\-test \- Test plugins that rely on containers no longer support reusing running containers\. The previous behavior was an undocumented\, untested feature\. * service module will not permanently configure variables/flags for openbsd when doing enable/disable operation anymore\, this module was never meant to do this type of work\, just to manage the service state itself\. A rcctl\_config or similar module should be created and used instead\. - + #### amazon\.aws * The amazon\.aws collection has dropped support for botocore\<1\.29\.0 and boto3\<1\.26\.0\. Most modules will continue to work with older versions of the AWS SDK\, however compatability with older versions of the SDK is not guaranteed and will not be tested\. When using older versions of the SDK a warning will be emitted by Ansible \([https\://github\.com/ansible\-collections/amazon\.aws/pull/1763](https\://github\.com/ansible\-collections/amazon\.aws/pull/1763)\)\. @@ -4634,7 +5287,7 @@ If not mentioned explicitly\, the changes are reported in the combined changelog * module\_utils \- module\_utils\.urls was previously deprecated and has been removed \([https\://github\.com/ansible\-collections/amazon\.aws/pull/1540](https\://github\.com/ansible\-collections/amazon\.aws/pull/1540)\)\. * module\_utils\.\_version \- vendored copy of distutils\.version has been dropped \([https\://github\.com/ansible\-collections/amazon\.aws/pull/1587](https\://github\.com/ansible\-collections/amazon\.aws/pull/1587)\)\. - + #### community\.aws * The community\.aws collection has dropped support for botocore\<1\.29\.0 and boto3\<1\.26\.0\. Most modules will continue to work with older versions of the AWS SDK\, however compatability with older versions of the SDK is not guaranteed and will not be tested\. When using older versions of the SDK a warning will be emitted by Ansible \([https\://github\.com/ansible\-collections/amazon\.aws/pull/1763](https\://github\.com/ansible\-collections/amazon\.aws/pull/1763)\)\. @@ -4652,7 +5305,7 @@ If not mentioned explicitly\, the changes are reported in the combined changelog * s3\_bucket\_info \- The module has been migrated from the community\.aws collection\. Playbooks using the Fully Qualified Collection Name for this module should be updated to use amazon\.aws\.s3\_bucket\_info\. * sts\_assume\_role \- The module has been migrated from the community\.aws collection\. Playbooks using the Fully Qualified Collection Name for this module should be updated to use amazon\.aws\.sts\_assume\_role\. - + #### community\.general * collection\_version lookup plugin \- remove compatibility code for ansible\-base 2\.10 and ansible\-core 2\.11 \([https\://github\.com/ansible\-collections/community\.general/pull/7269](https\://github\.com/ansible\-collections/community\.general/pull/7269)\)\. @@ -4666,7 +5319,7 @@ If not mentioned explicitly\, the changes are reported in the combined changelog * The minimum required version of hvac is now 1\.2\.1 \([https\://docs\.ansible\.com/ansible/devel/collections/community/hashi\_vault/docsite/user\_guide\.html\#hvac\-version\-specifics](https\://docs\.ansible\.com/ansible/devel/collections/community/hashi\_vault/docsite/user\_guide\.html\#hvac\-version\-specifics)\)\. - + #### community\.vmware * Removed support for ansible\-core version \< 2\.15\.0\. @@ -4687,7 +5340,7 @@ If not mentioned explicitly\, the changes are reported in the combined changelog * hcloud\-python 1\.20\.0 is now required for full compatibility * inventory plugin \- Don\'t set the server image variables \(image\_id\, image\_os\_flavor and image\_name\) when the server image is not defined\. - + ### Deprecated Features * The community\.azure collection is officially unmaintained and has been archived\. Therefore\, it will be removed from Ansible 10\. There is already a successor collection azure\.azcollection in the community package which should cover the same functionality \([https\://github\.com/ansible\-community/community\-topics/issues/263](https\://github\.com/ansible\-community/community\-topics/issues/263)\)\. @@ -4699,7 +5352,7 @@ If not mentioned explicitly\, the changes are reported in the combined changelog * The netapp\.elementsw collection is considered unmaintained and will be removed from Ansible 10 if no one starts maintaining it again before Ansible 10\. See [the removal process for details on how this works](https\://github\.com/ansible\-collections/overview/blob/main/removal\_from\_ansible\.rst\#cancelling\-removal\-of\-an\-unmaintained\-collection) \([https\://github\.com/ansible\-community/community\-topics/issues/235](https\://github\.com/ansible\-community/community\-topics/issues/235)\)\. * The netapp\.um\_info collection is considered unmaintained and will be removed from Ansible 10 if no one starts maintaining it again before Ansible 10\. See [the removal process for details on how this works](https\://github\.com/ansible\-collections/overview/blob/main/removal\_from\_ansible\.rst\#cancelling\-removal\-of\-an\-unmaintained\-collection) \([https\://github\.com/ansible\-community/community\-topics/issues/244](https\://github\.com/ansible\-community/community\-topics/issues/244)\)\. - + #### Ansible\-core * Deprecated ini config option collections\_paths\, use the singular form collections\_path instead @@ -4711,7 +5364,7 @@ If not mentioned explicitly\, the changes are reported in the combined changelog * vault and unfault filters \- the undocumented vaultid parameter is deprecated and will be removed in ansible\-core 2\.20\. Use vault\_id instead\. * yum\_repository \- deprecated parameter \'keepcache\' \([https\://github\.com/ansible/ansible/issues/78693](https\://github\.com/ansible/ansible/issues/78693)\)\. - + #### amazon\.aws * ec2\_instance \- deprecation of tenancy and placement\_group in favor of placement attribute \([https\://github\.com/ansible\-collections/amazon\.aws/pull/1825](https\://github\.com/ansible\-collections/amazon\.aws/pull/1825)\)\. @@ -4749,12 +5402,12 @@ If not mentioned explicitly\, the changes are reported in the combined changelog * support for Python 2\.6 nad 2\.7 * support for ansible 2\.9 - + #### community\.crypto * get\_certificate \- the default false of the asn1\_base64 option is deprecated and will change to true in community\.crypto 3\.0\.0 \([https\://github\.com/ansible\-collections/community\.crypto/pull/600](https\://github\.com/ansible\-collections/community\.crypto/pull/600)\)\. - + #### community\.general * CmdRunner module utils \- deprecate cmd\_runner\_fmt\.as\_default\_type\(\) formatter \([https\://github\.com/ansible\-collections/community\.general/pull/6601](https\://github\.com/ansible\-collections/community\.general/pull/6601)\)\. @@ -4876,7 +5529,7 @@ If not mentioned explicitly\, the changes are reported in the combined changelog * community\.google was considered unmaintained and removed from Ansible 9 as per the [removal from Ansible process](https\://github\.com/ansible\-collections/overview/blob/main/removal\_from\_ansible\.rst\#unmaintained\-collections)\. Users can still install this collection with ansible\-galaxy collection install community\.google\. * community\.skydive was considered unmaintained and removed from Ansible 9 as per the [removal from Ansible process](https\://github\.com/ansible\-collections/overview/blob/main/removal\_from\_ansible\.rst\#unmaintained\-collections)\. Users can still install this collection with ansible\-galaxy collection install community\.skydive\. - + #### Ansible\-core * ActionBase \- remove deprecated \_remote\_checksum method @@ -4928,7 +5581,7 @@ If not mentioned explicitly\, the changes are reported in the combined changelog * remove testing for Python 2\.6 nad 2\.7 * remove testing for ansible 2\.9 - + #### community\.general * The collection no longer supports ansible\-core 2\.11 and ansible\-core 2\.12\. Parts of the collection might still work on these ansible\-core versions\, but others might not \([https\://github\.com/ansible\-collections/community\.general/pull/7269](https\://github\.com/ansible\-collections/community\.general/pull/7269)\)\. @@ -4951,7 +5604,7 @@ If not mentioned explicitly\, the changes are reported in the combined changelog * The minimum supported version of ansible\-core is now 2\.14\, support for 2\.13 has been dropped \([https\://github\.com/ansible\-collections/community\.hashi\_vault/pull/403](https\://github\.com/ansible\-collections/community\.hashi\_vault/pull/403)\)\. - + #### community\.vmware * Removed module util version \([https\://github\.com/ansible\-collections/community\.vmware/issues/1639](https\://github\.com/ansible\-collections/community\.vmware/issues/1639)\)\. @@ -4989,15 +5642,15 @@ If not mentioned explicitly\, the changes are reported in the combined changelog ### Security Fixes - + #### Ansible\-core * ansible\-galaxy \- Prevent roles from using symlinks to overwrite files outside of the installation directory \(CVE\-2023\-5115\) - + ### Bugfixes - + #### Ansible\-core * Allow for searching handler subdir for included task via include\_role \([https\://github\.com/ansible/ansible/issues/81722](https\://github\.com/ansible/ansible/issues/81722)\) @@ -5147,7 +5800,7 @@ If not mentioned explicitly\, the changes are reported in the combined changelog * win\_fetch \- Add support for using file with wildcards in file name\. \([https\://github\.com/ansible/ansible/issues/73128](https\://github\.com/ansible/ansible/issues/73128)\) * winrm \- Better handle send input failures when communicating with hosts under load - + #### amazon\.aws * autoscaling\_group \- fix ValidationError when describing an autoscaling group that has more than 20 target groups attached to it by breaking the request into chunks \([https\://github\.com/ansible\-collections/amazon\.aws/pull/1593](https\://github\.com/ansible\-collections/amazon\.aws/pull/1593)\)\. @@ -5218,7 +5871,7 @@ If not mentioned explicitly\, the changes are reported in the combined changelog * win\-chocolatey \- unable to install packages if a license is already installed and chocolatey\.extension is not installed - + #### cisco\.aci * Change input of prefix\_suppression to type string to allow enable\, disable and inherit options for aci\_interface\_policy\_ospf @@ -5264,7 +5917,7 @@ If not mentioned explicitly\, the changes are reported in the combined changelog * l2\_interfaces Fix issue in qvlan parsing\.\([https\://github\.com/ansible\-collections/cisco\.iosxr/issues/403](https\://github\.com/ansible\-collections/cisco\.iosxr/issues/403)\) * l3\_interfaces \- Fix issue in gather state of not gathering management interface\. \([https\://github\.com/ansible\-collections/cisco\.iosxr/issues/381](https\://github\.com/ansible\-collections/cisco\.iosxr/issues/381)\) - + #### cisco\.ise * Cannot get cisco\.ise\.active\_directory\_groups\_by\_domain\_info to work\. @@ -5275,7 +5928,7 @@ If not mentioned explicitly\, the changes are reported in the combined changelog * system\_certificate \- added support for none value in the used\_by param\. * system\_certificate \- fixed get\_object\_by\_id response\. - + #### cisco\.meraki * Adding condition to avoid error on exists on devices\. @@ -5316,7 +5969,7 @@ If not mentioned explicitly\, the changes are reported in the combined changelog * meraki\_devices \- Fix endpoints due to breaking change in Meraki API v1\.33 * runtime updated requires\_ansible from 2\.9\.10 to \'\>\=2\.14\.0\'\. - + #### cisco\.mso * Fix mso\_tenant\_site \"site not found\" issue on absent \(\#368\) @@ -5350,7 +6003,7 @@ If not mentioned explicitly\, the changes are reported in the combined changelog * Add missing modules to the \"cloudscale\_ch\.cloud\.cloudscale\" action group\. * Remove outdated Ansible version requirement from the README\. - + #### community\.aws * Remove apigateway and apigateway\_deployment from meta/runtime\.yml \([https\://github\.com/ansible\-collections/community\.aws/pull/1905](https\://github\.com/ansible\-collections/community\.aws/pull/1905)\)\. @@ -5373,7 +6026,7 @@ If not mentioned explicitly\, the changes are reported in the combined changelog * added Cisco device config guide to address issue * added extra \"n\" to sending commands to address issue - + #### community\.crypto * Fix PEM detection/identification to also accept random other lines before the line starting with \-\-\-\-\-BEGIN \([https\://github\.com/ansible\-collections/community\.crypto/issues/627](https\://github\.com/ansible\-collections/community\.crypto/issues/627)\, [https\://github\.com/ansible\-collections/community\.crypto/pull/628](https\://github\.com/ansible\-collections/community\.crypto/pull/628)\)\. @@ -5387,14 +6040,14 @@ If not mentioned explicitly\, the changes are reported in the combined changelog * digital\_ocean\_domain \- fix all\_domains by using get\_paginated\_data to retrieve all of the domains in the account from the paginated domains api endpoint \([https\://github\.com/ansible\-collections/community\.digitalocean/pull/307](https\://github\.com/ansible\-collections/community\.digitalocean/pull/307)\)\. - + #### community\.dns * HTTP module utils \- make compatible with ansible\-core 2\.17 \([https\://github\.com/ansible\-collections/community\.dns/pull/165](https\://github\.com/ansible\-collections/community\.dns/pull/165)\)\. * Update Public Suffix List\. * wait\_for\_txt\, resolver module utils \- improve error handling \([https\://github\.com/ansible\-collections/community\.dns/pull/158](https\://github\.com/ansible\-collections/community\.dns/pull/158)\)\. - + #### community\.docker * docker\_swarm \- make init and join operations work again with Docker SDK for Python before 4\.0\.0 \([https\://github\.com/ansible\-collections/community\.docker/issues/695](https\://github\.com/ansible\-collections/community\.docker/issues/695)\, [https\://github\.com/ansible\-collections/community\.docker/pull/696](https\://github\.com/ansible\-collections/community\.docker/pull/696)\)\. @@ -5402,7 +6055,7 @@ If not mentioned explicitly\, the changes are reported in the combined changelog * docker\_volume \- fix crash caused by accessing an empty dictionary\. The has\_different\_config\(\) was raising an AttributeError because the self\.existing\_volume\[\"Labels\"\] dictionary was None \([https\://github\.com/ansible\-collections/community\.docker/pull/702](https\://github\.com/ansible\-collections/community\.docker/pull/702)\)\. * vendored Docker SDK for Python code \- cherry\-pick changes from the Docker SDK for Python code to align code\. These changes should not affect the parts used by the collection\'s code \([https\://github\.com/ansible\-collections/community\.docker/pull/694](https\://github\.com/ansible\-collections/community\.docker/pull/694)\)\. - + #### community\.general * CmdRunner module utils \- does not attempt to resolve path if executable is a relative or absolute path \([https\://github\.com/ansible\-collections/community\.general/pull/7200](https\://github\.com/ansible\-collections/community\.general/pull/7200)\)\. @@ -5503,7 +6156,7 @@ If not mentioned explicitly\, the changes are reported in the combined changelog * vault\_write \- the vault\_write lookup and module were not able to write data containing keys named path or wrap\_ttl due to a bug in the hvac library\. These plugins have now been updated to take advantage of fixes in hvac\>\=1\.2 to address this \([https\://github\.com/ansible\-collections/community\.hashi\_vault/issues/389](https\://github\.com/ansible\-collections/community\.hashi\_vault/issues/389)\)\. - + #### community\.hrobot * Show more information \(if available\) from error messages \([https\://github\.com/ansible\-collections/community\.hrobot/pull/89](https\://github\.com/ansible\-collections/community\.hrobot/pull/89)\)\. @@ -5544,7 +6197,7 @@ If not mentioned explicitly\, the changes are reported in the combined changelog * postgresql\_set \- fixed GUC\_LIST\_QUOTE parameters \([https\://github\.com/ansible\-collections/community\.postgresql/pull/521](https\://github\.com/ansible\-collections/community\.postgresql/pull/521)\)\. * postgresql\_set \- fixed error message in param\_set function \([https\://github\.com/ansible\-collections/community\.postgresql/pull/505](https\://github\.com/ansible\-collections/community\.postgresql/pull/505)\)\. - + #### community\.routeros * api\_info\, api\_modify \- in the snmp path\, ensure that engine\-id\-suffix is only available on RouterOS 7\.10\+\, and that engine\-id is read\-only on RouterOS 7\.10\+ \([https\://github\.com/ansible\-collections/community\.routeros/issues/208](https\://github\.com/ansible\-collections/community\.routeros/issues/208)\, [https\://github\.com/ansible\-collections/community\.routeros/pull/218](https\://github\.com/ansible\-collections/community\.routeros/pull/218)\)\. @@ -5562,7 +6215,7 @@ If not mentioned explicitly\, the changes are reported in the combined changelog * install role \- make sure that the pkg\_mgr fact is definitely available when installing on localhost\. This can improve error messages in some cases \([https\://github\.com/ansible\-collections/community\.sops/issues/145](https\://github\.com/ansible\-collections/community\.sops/issues/145)\, [https\://github\.com/ansible\-collections/community\.sops/pull/146](https\://github\.com/ansible\-collections/community\.sops/pull/146)\)\. * sops\_encrypt \- ensure that output\-type is set to yaml when the file extension \.yml is used\. Now both \.yaml and \.yml files use the SOPS \-\-output\-type\=yaml formatting \([https\://github\.com/ansible\-collections/community\.sops/issues/164](https\://github\.com/ansible\-collections/community\.sops/issues/164)\)\. - + #### community\.vmware * Add missing modules to runtime\.yml \([https\://github\.com/ansible\-collections/community\.vmware/pull/1764](https\://github\.com/ansible\-collections/community\.vmware/pull/1764)\)\. @@ -5592,7 +6245,7 @@ If not mentioned explicitly\, the changes are reported in the combined changelog * zabbix\_proxy role \- undefined vars at updating proxy definition\. Fix adds null defaults for zabbix\_proxy\_tlsaccept and zabbix\_proxy\_tlsconnect\. * zabbix\_web role \- removed \'ssl on\;\' nginx configuration\, which is no longer supported since nginx version 1\.25\.1\. - + #### containers\.podman * Add hooks\-dir parameter for containers @@ -5703,7 +6356,7 @@ If not mentioned explicitly\, the changes are reported in the combined changelog * Improve sanity tests\. * When the JSON data sent by FortiManager is not in the right format\, the collection can still execute correctly\. - + #### fortinet\.fortios * Fix the error of pure number password\. @@ -5757,7 +6410,7 @@ If not mentioned explicitly\, the changes are reported in the combined changelog * microsoft\.ad\.user \- Ensure the spn diff after key is spn and not kerberos\_encryption\_types * microsoft\.ad\.user \- treat an expired account as a password that needs to be changed - + #### netapp\.ontap * na\_ontap\_dns \- fix DNS not working with Cluster mode\. @@ -5828,7 +6481,7 @@ If not mentioned explicitly\, the changes are reported in the combined changelog * purefa\_subnet \- Fixed IPv6 support issues\. * purefa\_volume \- Fixed bug with NULL suffix for multiple volume creation\. - + #### purestorage\.flashblade * purefb\_bucket \- Fixed bucket type mode name typo @@ -5876,38 +6529,38 @@ If not mentioned explicitly\, the changes are reported in the combined changelog ### Known Issues - + #### Ansible\-core * ansible\-galaxy \- dies in the middle of installing a role when that role contains Java inner classes \(files with \$ in the file name\)\. This is by design\, to exclude temporary or backup files\. \([https\://github\.com/ansible/ansible/pull/81553](https\://github\.com/ansible/ansible/pull/81553)\)\. * ansible\-test \- The pep8 sanity test is unable to detect f\-string spacing issues \(E201\, E202\) on Python 3\.10 and 3\.11\. They are correctly detected under Python 3\.12\. See \([https\://github\.com/PyCQA/pycodestyle/issues/1190](https\://github\.com/PyCQA/pycodestyle/issues/1190)\)\. - + #### community\.crypto * Ansible markup will show up in raw form on ansible\-doc text output for ansible\-core before 2\.15\. If you have trouble deciphering the documentation markup\, please upgrade to ansible\-core 2\.15 \(or newer\)\, or read the HTML documentation on [https\://docs\.ansible\.com/ansible/devel/collections/community/crypto/](https\://docs\.ansible\.com/ansible/devel/collections/community/crypto/)\. - + #### community\.dns * Ansible markup will show up in raw form on ansible\-doc text output for ansible\-core before 2\.15\. If you have trouble deciphering the documentation markup\, please upgrade to ansible\-core 2\.15 \(or newer\)\, or read the HTML documentation on [https\://docs\.ansible\.com/ansible/devel/collections/community/dns/](https\://docs\.ansible\.com/ansible/devel/collections/community/dns/)\. - + #### community\.docker * Ansible markup will show up in raw form on ansible\-doc text output for ansible\-core before 2\.15\. If you have trouble deciphering the documentation markup\, please upgrade to ansible\-core 2\.15 \(or newer\)\, or read the HTML documentation on [https\://docs\.ansible\.com/ansible/devel/collections/community/docker/](https\://docs\.ansible\.com/ansible/devel/collections/community/docker/)\. - + #### community\.general * Ansible markup will show up in raw form on ansible\-doc text output for ansible\-core before 2\.15\. If you have trouble deciphering the documentation markup\, please upgrade to ansible\-core 2\.15 \(or newer\)\, or read the HTML documentation on [https\://docs\.ansible\.com/ansible/devel/collections/community/general/](https\://docs\.ansible\.com/ansible/devel/collections/community/general/) \([https\://github\.com/ansible\-collections/community\.general/pull/6539](https\://github\.com/ansible\-collections/community\.general/pull/6539)\)\. - + #### community\.hrobot * Ansible markup will show up in raw form on ansible\-doc text output for ansible\-core before 2\.15\. If you have trouble deciphering the documentation markup\, please upgrade to ansible\-core 2\.15 \(or newer\)\, or read the HTML documentation on [https\://docs\.ansible\.com/ansible/devel/collections/community/hrobot/](https\://docs\.ansible\.com/ansible/devel/collections/community/hrobot/)\. - + #### community\.routeros * Ansible markup will show up in raw form on ansible\-doc text output for ansible\-core before 2\.15\. If you have trouble deciphering the documentation markup\, please upgrade to ansible\-core 2\.15 \(or newer\)\, or read the HTML documentation on [https\://docs\.ansible\.com/ansible/devel/collections/community/routeros/](https\://docs\.ansible\.com/ansible/devel/collections/community/routeros/)\. @@ -5930,7 +6583,7 @@ If not mentioned explicitly\, the changes are reported in the combined changelog * ome\_device\_quick\_deploy \- Issue\(275231\) \- This module does not deploy a new configuration to a slot that has disabled IPv6\. * ome\_smart\_fabric\_uplink \- Issue\(186024\) \- Despite the module supported by OpenManage Enterprise Modular\, it does not allow the creation of multiple uplinks of the same name\. If an uplink is created using the same name as an existing uplink\, the existing uplink is modified\. - + ### New Plugins @@ -5938,7 +6591,7 @@ If not mentioned explicitly\, the changes are reported in the combined changelog * ansible\.netcommon\.default \- General purpose cliconf plugin for new platforms - + #### Filter * ansible\.utils\.ipcut \- This filter is designed to get 1st or last few bits of IP address\. @@ -5958,10 +6611,10 @@ If not mentioned explicitly\, the changes are reported in the combined changelog * community\.dns\.lookup\_as\_dict \- Look up DNS records as dictionaries * community\.general\.bitwarden\_secrets\_manager \- Retrieve secrets from Bitwarden Secrets Manager - + ### New Modules - + #### amazon\.aws * amazon\.aws\.ec2\_import\_image \- Manage AWS EC2 import image tasks @@ -5995,18 +6648,18 @@ If not mentioned explicitly\, the changes are reported in the combined changelog * cloudscale\_ch\.cloud\.load\_balancer\_pool \- Manages load balancer pools on the cloudscale\.ch IaaS service * cloudscale\_ch\.cloud\.load\_balancer\_pool\_member \- Manages load balancer pool members on the cloudscale\.ch IaaS service - + #### community\.aws * community\.aws\.route53\_wait \- wait for changes in Amazons Route 53 DNS service to propagate - + #### community\.dns * community\.dns\.nameserver\_info \- Look up nameservers for a DNS name * community\.dns\.nameserver\_record\_info \- Look up all records of a type from all nameservers for a DNS name - + #### community\.general * community\.general\.consul\_policy \- Manipulate Consul policies @@ -6034,7 +6687,7 @@ If not mentioned explicitly\, the changes are reported in the combined changelog * community\.grafana\.grafana\_organization\_user \- Manage Grafana Organization Users\. - + #### community\.vmware * community\.vmware\.vcenter\_root\_password\_expiration \- root password expiration of vCSA @@ -6051,7 +6704,7 @@ If not mentioned explicitly\, the changes are reported in the combined changelog * community\.zabbix\.zabbix\_settings \- Update Zabbix global settings\. * community\.zabbix\.zabbix\_token \- Create/Update/Generate/Delete Zabbix token\. - + #### containers\.podman * containers\.podman\.podman\_container\_exec \- Executes a command in a running container @@ -6085,7 +6738,7 @@ If not mentioned explicitly\, the changes are reported in the combined changelog * dellemc\.openmanage\.ome\_alert\_policies\_message\_id\_info \- Get message ID information of alert policies\. * dellemc\.openmanage\.redfish\_firmware\_rollback \- To perform a component firmware rollback using component name\. - + #### dellemc\.powerflex * dellemc\.powerflex\.snapshot\_policy \- Manage snapshot policies on Dell PowerFlex @@ -6282,7 +6935,7 @@ If not mentioned explicitly\, the changes are reported in the combined changelog * inspur\.ispim\.hba\_info \- Get CPU information * inspur\.ispim\.update\_psu \- Update PSU - + #### netapp\.ontap * netapp\.ontap\.na\_ontap\_active\_directory\_domain\_controllers \- NetApp ONTAP configure active directory preferred domain controllers @@ -6339,7 +6992,7 @@ If not mentioned explicitly\, the changes are reported in the combined changelog * dellemc\.openmanage\.idrac\_reset \- Role to reset and restart iDRAC \(iDRAC8 and iDRAC9 only\) for Dell PowerEdge servers\. * dellemc\.openmanage\.idrac\_storage\_controller \- Role to configure the physical disk\, virtual disk\, and storage controller settings on iDRAC9 based PowerEdge servers\. - + ### Unchanged Collections * ansible\.posix \(still version 1\.5\.4\) diff --git a/CHANGELOG-v9.rst b/CHANGELOG-v9.rst index d3abd5c05..156f5870c 100644 --- a/CHANGELOG-v9.rst +++ b/CHANGELOG-v9.rst @@ -7,6 +7,625 @@ This changelog describes changes since Ansible 8.0.0. .. contents:: :depth: 2 +v9.5.1 +====== + +.. contents:: + :local: + :depth: 2 + +Release Summary +--------------- + +Release Date: 2024-04-24 + +`Porting Guide `_ + +Please note that this release replaces a mistakenly released 9.5.0 that included a breaking change. The 9.5.0 release has been yanked from PyPI and is not part of the official release history. + +Ansible-core +------------ + +Ansible 9.5.1 contains ansible-core version 2.16.6. +This is a newer version than version 2.16.5 contained in the previous Ansible release. + +The changes are reported in the combined changelog below. + +Changed Collections +------------------- + +If not mentioned explicitly, the changes are reported in the combined changelog below. + ++------------------------------------------+---------------+---------------+------------------------------------------------------------------------------------------------------------------------------+ +| Collection | Ansible 9.4.0 | Ansible 9.5.1 | Notes | ++==========================================+===============+===============+==============================================================================================================================+ +| amazon.aws | 7.4.0 | 7.5.0 | | ++------------------------------------------+---------------+---------------+------------------------------------------------------------------------------------------------------------------------------+ +| cisco.aci | 2.8.0 | 2.9.0 | | ++------------------------------------------+---------------+---------------+------------------------------------------------------------------------------------------------------------------------------+ +| cisco.dnac | 6.13.1 | 6.13.3 | | ++------------------------------------------+---------------+---------------+------------------------------------------------------------------------------------------------------------------------------+ +| cisco.intersight | 2.0.7 | 2.0.8 | Unfortunately, this collection does not provide changelog data in a format that can be processed by the changelog generator. | ++------------------------------------------+---------------+---------------+------------------------------------------------------------------------------------------------------------------------------+ +| cisco.ise | 2.8.0 | 2.8.1 | | ++------------------------------------------+---------------+---------------+------------------------------------------------------------------------------------------------------------------------------+ +| cisco.meraki | 2.17.2 | 2.18.0 | | ++------------------------------------------+---------------+---------------+------------------------------------------------------------------------------------------------------------------------------+ +| cisco.mso | 2.5.0 | 2.6.0 | | ++------------------------------------------+---------------+---------------+------------------------------------------------------------------------------------------------------------------------------+ +| community.aws | 7.1.0 | 7.2.0 | | ++------------------------------------------+---------------+---------------+------------------------------------------------------------------------------------------------------------------------------+ +| community.crypto | 2.18.0 | 2.19.0 | | ++------------------------------------------+---------------+---------------+------------------------------------------------------------------------------------------------------------------------------+ +| community.dns | 2.8.3 | 2.9.0 | | ++------------------------------------------+---------------+---------------+------------------------------------------------------------------------------------------------------------------------------+ +| community.docker | 3.8.1 | 3.9.0 | | ++------------------------------------------+---------------+---------------+------------------------------------------------------------------------------------------------------------------------------+ +| community.general | 8.5.0 | 8.6.0 | | ++------------------------------------------+---------------+---------------+------------------------------------------------------------------------------------------------------------------------------+ +| community.hrobot | 1.9.1 | 1.9.2 | | ++------------------------------------------+---------------+---------------+------------------------------------------------------------------------------------------------------------------------------+ +| community.library_inventory_filtering_v1 | 1.0.0 | 1.0.1 | | ++------------------------------------------+---------------+---------------+------------------------------------------------------------------------------------------------------------------------------+ +| community.mongodb | 1.7.2 | 1.7.3 | There are no changes recorded in the changelog. | ++------------------------------------------+---------------+---------------+------------------------------------------------------------------------------------------------------------------------------+ +| community.rabbitmq | 1.2.3 | 1.3.0 | | ++------------------------------------------+---------------+---------------+------------------------------------------------------------------------------------------------------------------------------+ +| community.routeros | 2.14.0 | 2.15.0 | | ++------------------------------------------+---------------+---------------+------------------------------------------------------------------------------------------------------------------------------+ +| community.vmware | 4.2.0 | 4.3.0 | | ++------------------------------------------+---------------+---------------+------------------------------------------------------------------------------------------------------------------------------+ +| containers.podman | 1.12.0 | 1.13.0 | | ++------------------------------------------+---------------+---------------+------------------------------------------------------------------------------------------------------------------------------+ +| dellemc.powerflex | 2.2.0 | 2.3.0 | | ++------------------------------------------+---------------+---------------+------------------------------------------------------------------------------------------------------------------------------+ +| fortinet.fortios | 2.3.5 | 2.3.6 | | ++------------------------------------------+---------------+---------------+------------------------------------------------------------------------------------------------------------------------------+ +| infinidat.infinibox | 1.4.3 | 1.4.5 | Unfortunately, this collection does not provide changelog data in a format that can be processed by the changelog generator. | ++------------------------------------------+---------------+---------------+------------------------------------------------------------------------------------------------------------------------------+ +| netapp.ontap | 22.10.0 | 22.11.0 | | ++------------------------------------------+---------------+---------------+------------------------------------------------------------------------------------------------------------------------------+ +| purestorage.flashblade | 1.16.0 | 1.17.0 | | ++------------------------------------------+---------------+---------------+------------------------------------------------------------------------------------------------------------------------------+ + +Major Changes +------------- + +containers.podman +~~~~~~~~~~~~~~~~~ + +- Add quadlet support for Podman modules + +fortinet.fortios +~~~~~~~~~~~~~~~~ + +- Add notes for backup modules in the documentation in both monitor and monitor_fact modules. +- Supported new FOS versions 7.4.2 and 7.4.3, and support data type mac_address in the collection. +- Update the documentation for the supported versions from latest to a fix version number. +- Update the required ansible version to 2.15. + +Minor Changes +------------- + +amazon.aws +~~~~~~~~~~ + +- iam_user_info - Add ``login_profile`` to return info that is get from a user, to know if they can login from AWS console (https://github.com/ansible-collections/amazon.aws/pull/2012). +- module_utils.iam - refactored normalization functions to use ``boto3_resource_to_ansible_dict()`` and ``boto3_resource_list_to_ansible_dict()`` (https://github.com/ansible-collections/amazon.aws/pull/2006). +- module_utils.transformations - add ``boto3_resource_to_ansible_dict()`` and ``boto3_resource_list_to_ansible_dict()`` helpers (https://github.com/ansible-collections/amazon.aws/pull/2006). + +cisco.aci +~~~~~~~~~ + +- Add Authentification option for EIGRP interface profile. +- Add L3out Floating SVI modules (aci_l3out_floating_svi, aci_l3out_floating_svi_path, aci_l3out_floating_svi_path_secondary_ip and aci_l3out_floating_svi_secondary_ip) (#478) +- Add No-verification flag option to reduce the number of API calls. If true, a verifying GET will not be sent after a POST update to APIC +- Add access spine interface selector and port block binding in aci_access_port_block_to_access_port +- Add aci_access_spine_interface_selector module +- Add aci_action_rule_additional_communities module +- Add aci_action_rule_set_as_path and aci_action_rule_set_as_path_asn modules +- Add aci_bgp_peer_prefix_policy, aci_bgp_route_summarization_policy and aci_bgp_address_family_context_policy modules +- Add aci_fabric_pod, aci_fabric_pod_external_tep, aci_fabric_pod_profile, aci_fabric_pod_remote_pool modules (#558) +- Add aci_hsrp_interface_policy, aci_l3out_hsrp_group, aci_l3out_hsrp_interface_profile and aci_l3out_hsrp_secondary_vip modules (#505) +- Add aci_interface_policy_eigrp (class:eigrpIfPol) module +- Add aci_interface_policy_pim module +- Add aci_interface_policy_storm_control module +- Add aci_keychain_policy and aci_key_policy modules +- Add aci_l3out_bfd_multihop_interface_profile, aci_l3out_bfd_interface_profile, aci_interface_policy_bfd_multihop, aci_interface_policy_bfd and aci_bfd_multihop_node_policy modules (#492) +- Add aci_l3out_dhcp_relay_label, aci_dhcp_option_policy and aci_dhcp_option modules +- Add aci_l3out_eigrp_interface_profile module +- Add aci_listify filter plugin to flattens nested dictionaries +- Add aci_netflow_exporter_policy module +- Add aci_netflow_monitor_policy and aci_netflow_record_policy modules +- Add aci_netflow_monitor_to_exporter module +- Add aci_node_block module +- Add aci_pim_route_map_policy and aci_pim_route_map_entry modules +- Add aci_qos_custom_policy and aci_qos_dscp_class modules +- Add aci_qos_dot1p_class module +- Add action rules attributes to aci_tenant_action_rule_profile. +- Add auto to speed attribute options in aci_interface_policy_link_level module (#577) +- Add missing options to aci_bd module +- Add modules aci_bd_to_netflow_monitor_policy and aci_bd_rogue_exception_mac (#600) +- Add modules for Fabric External Connection Policies and its childs +- Add option to set delimiter to _ in aci_epg_to_domain module +- Add qos_custom_policy, pim_interface_policy and igmp_interface_policy as new child_classes for aci_l3out_logical_interface_profile. +- Add support for annotation in aci_rest module (#437) +- Add support for block statements in useg attributes with the aci_epg_useg_attribute_block_statement module +- Add support for configuration of access switch policy groups with aci_access_switch_policy_group module +- Add support for configuration of certificate authorities in aci_aaa_certificate_authority +- Add support for configuration of fabric management access policies in aci_fabric_management_access +- Add support for configuration of vrf multicast with aci_vrf_multicast module +- Add support for configuring Azure cloud subnets using the aci_cloud_subnet module +- Add support for encap scope in aci_l3out_interface +- Add support for https ssl cipher configuration in aci_fabric_management_access_https_cipher +- Add support for infra l3out nodes bgp-evpn loopback, mpls transport loopback and segment id in aci_l3out_logical_node +- Add support for infra sr mpls micro bfd in aci_l3out_interface +- Add support for intra epg, taboo, and contract interface in aci_epg_to_contract +- Add support for key ring configuration in aci_aaa_key_ring +- Add support for mac and description in aci_l3out_interface +- Add support for mpls custom qos policy for infra sr mpls l3outs node profiles in aci_l3out_logical_node_profile +- Add support for security default settings configuration in aci_aaa_security_default_settings +- Add support for simple statements in useg attributes with the aci_epg_useg_attribute_simple_statement module +- Add support for sr-mpls bgpInfraPeerP and bgp_password in aci_l3out_bgp_peer module (#543) +- Add support for sr-mpls in aci_l3out module +- Add support for sr-mpls l3out to infra l3out in aci_l3out_to_sr_mpls_infra_l3out +- Add support for subject labels for EPG, EPG Contract, ESG, Contract Subject, L2Out External EPG, L3out External EPG, and L3out External EPG Contract with the aci_subject_label module +- Add support for taboo contract, contract interface and intra_epg contract in aci_l3out_extepg_to_contract +- Add support for useg default block statement configuration for useg epg in aci_epg +- Modify child class node block conditions to be optional in aci_switch_leaf_selector + +cisco.dnac +~~~~~~~~~~ + +- Added a method to validate IP addresses. +- Added the op_modifies=True when calling SDK APIs in the workflow manager modules. +- Adding support to importing a template using JSON file +- Changes in discovery workflow manager modules relating to different states of the discovery job +- Changes in inventory and swim workflow manager modules. +- Fixed a minor issue in the site workflow manager module. +- Updating galaxy.yml ansible.utils dependencies. + +cisco.meraki +~~~~~~~~~~~~ + +- Ansible collection now support v1.44.1 of Dashboard Api. +- administered_licensing_subscription_entitlements_info - new plugin. +- administered_licensing_subscription_subscriptions_bind - new plugin. +- administered_licensing_subscription_subscriptions_claim - new plugin. +- administered_licensing_subscription_subscriptions_claim_key_validate - new plugin. +- administered_licensing_subscription_subscriptions_compliance_statuses_info - new plugin. +- administered_licensing_subscription_subscriptions_info - new plugin. +- devices_appliance_radio_settings - new plugin. +- devices_appliance_radio_settings_info - new plugin. +- devices_live_tools_arp_table - new plugin. +- devices_live_tools_arp_table_info - new plugin. +- devices_live_tools_cable_test - new plugin. +- devices_live_tools_cable_test_info - new plugin. +- devices_live_tools_throughput_test - new plugin. +- devices_live_tools_throughput_test_info - new plugin. +- devices_live_tools_wake_on_lan - new plugin. +- devices_live_tools_wake_on_lan_info - new plugin. +- devices_wireless_alternate_management_interface_ipv6 - new plugin. +- networks_appliance_rf_profiles - new plugin. +- networks_appliance_rf_profiles_info - new plugin. +- networks_appliance_traffic_shaping_vpn_exclusions - new plugin. +- networks_sm_devices_install_apps - new plugin. +- networks_sm_devices_reboot - new plugin. +- networks_sm_devices_shutdown - new plugin. +- networks_sm_devices_uninstall_apps - new plugin. +- networks_vlan_profiles - new plugin. +- networks_vlan_profiles_assignments_by_device_info - new plugin. +- networks_vlan_profiles_assignments_reassign - new plugin. +- networks_vlan_profiles_info - new plugin. +- networks_wireless_ethernet_ports_profiles - new plugin. +- networks_wireless_ethernet_ports_profiles_assign - new plugin. +- networks_wireless_ethernet_ports_profiles_info - new plugin. +- networks_wireless_ethernet_ports_profiles_set_default - new plugin. +- organizations_appliance_traffic_shaping_vpn_exclusions_by_network_info - new plugin. +- organizations_appliance_uplinks_statuses_overview_info - new plugin. +- organizations_appliance_uplinks_usage_by_network_info - new plugin. +- organizations_camera_boundaries_areas_by_device_info - new plugin. +- organizations_camera_boundaries_lines_by_device_info - new plugin. +- organizations_camera_detections_history_by_boundary_by_interval_info - new plugin. +- organizations_camera_permissions_info - new plugin. +- organizations_camera_roles - new plugin. +- organizations_camera_roles_info - new plugin. +- organizations_devices_availabilities_change_history_info - new plugin. +- organizations_devices_boots_history_info - new plugin. +- organizations_sm_admins_roles - new plugin. +- organizations_sm_admins_roles_info - new plugin. +- organizations_sm_sentry_policies_assignments - new plugin. +- organizations_sm_sentry_policies_assignments_by_network_info - new plugin. +- organizations_summary_top_networks_by_status_info - new plugin. +- organizations_webhooks_callbacks_statuses_info - new plugin. +- organizations_wireless_devices_channel_utilization_by_device_info - new plugin. +- organizations_wireless_devices_channel_utilization_by_network_info - new plugin. +- organizations_wireless_devices_channel_utilization_history_by_device_by_interval_info - new plugin. +- organizations_wireless_devices_channel_utilization_history_by_network_by_interval_info - new plugin. +- organizations_wireless_devices_packet_loss_by_client_info - new plugin. +- organizations_wireless_devices_packet_loss_by_device_info - new plugin. +- organizations_wireless_devices_packet_loss_by_network_info - new plugin. + +cisco.mso +~~~~~~~~~ + +- Add Azure Cloud site support to mso_schema_site_contract_service_graph +- Add Azure Cloud site support to mso_schema_site_service_graph +- Add functionality to resolve same name in remote and local user. +- Add l3out_template and l3out_schema arguments to mso_schema_site_external_epg (#394) +- Add mso_schema_site_contract_service_graph module to manage site contract service graph +- Add mso_schema_site_contract_service_graph_listener module to manage Azure site contract service graph listeners and update other modules +- Add new parameter remote_user to add multiple remote users associated with multiple login domains +- Add support for replacing all existing contracts with new provided contracts in a single operation with one request and adding/removing multiple contracts in multiple operations with a single request in mso_schema_template_anp_epg_contract module +- Add support for replacing all existing static ports with new provided static ports in a single operation with one request and adding/removing multiple static ports in multiple operations with a single request in mso_schema_template_anp_epg_staticport module +- Add support for required attributes introduced in NDO 4.2 for mso_schema_site_anp_epg_domain +- Support for creation of schemas without templates with the mso_schema module + +community.aws +~~~~~~~~~~~~~ + +- glue_job - add support for 2 new instance types which are G.4X and G.8X (https://github.com/ansible-collections/community.aws/pull/2048). +- msk_cluster - Support for additional ``m5`` and ``m7g`` types of MSK clusters (https://github.com/ansible-collections/community.aws/pull/1947). + +community.crypto +~~~~~~~~~~~~~~~~ + +- When using cryptography >= 42.0.0, use offset-aware ``datetime.datetime`` objects (with timezone UTC) instead of offset-naive UTC timestamps (https://github.com/ansible-collections/community.crypto/issues/726, https://github.com/ansible-collections/community.crypto/pull/727). +- openssh_cert - avoid UTC functions deprecated in Python 3.12 when using Python 3 (https://github.com/ansible-collections/community.crypto/pull/727). + +community.docker +~~~~~~~~~~~~~~~~ + +- The EE requirements now include PyYAML, since the ``docker_compose_v2*`` modules depend on it when the ``definition`` option is used. This should not have a noticable effect on generated EEs since ansible-core itself depends on PyYAML as well, and ansible-builder explicitly ignores this dependency (https://github.com/ansible-collections/community.docker/pull/832). +- docker_compose_v2* - the new option ``check_files_existing`` allows to disable the check for one of the files ``compose.yaml``, ``compose.yml``, ``docker-compose.yaml``, and ``docker-compose.yml`` in ``project_src`` if ``files`` is not specified. This is necessary if a non-standard compose filename is specified through other means, like the ``COMPOSE_FILE`` environment variable (https://github.com/ansible-collections/community.docker/issues/838, https://github.com/ansible-collections/community.docker/pull/839). +- docker_compose_v2* modules - allow to provide an inline definition of the compose content instead of having to provide a ``project_src`` directory with the compose file written into it (https://github.com/ansible-collections/community.docker/issues/829, https://github.com/ansible-collections/community.docker/pull/832). +- vendored Docker SDK for Python - remove unused code that relies on functionality deprecated in Python 3.12 (https://github.com/ansible-collections/community.docker/pull/834). + +community.general +~~~~~~~~~~~~~~~~~ + +- Use offset-aware ``datetime.datetime`` objects (with timezone UTC) instead of offset-naive UTC timestamps, which are deprecated in Python 3.12 (https://github.com/ansible-collections/community.general/pull/8222). +- apt_rpm - add new states ``latest`` and ``present_not_latest``. The value ``latest`` is equivalent to the current behavior of ``present``, which will upgrade a package if a newer version exists. ``present_not_latest`` does what most users would expect ``present`` to do: it does not upgrade if the package is already installed. The current behavior of ``present`` will be deprecated in a later version, and eventually changed to that of ``present_not_latest`` (https://github.com/ansible-collections/community.general/issues/8217, https://github.com/ansible-collections/community.general/pull/8247). +- bitwarden lookup plugin - add support to filter by organization ID (https://github.com/ansible-collections/community.general/pull/8188). +- filesystem - add bcachefs support (https://github.com/ansible-collections/community.general/pull/8126). +- ini_file - add an optional parameter ``section_has_values``. If the target ini file contains more than one ``section``, use ``section_has_values`` to specify which one should be updated (https://github.com/ansible-collections/community.general/pull/7505). +- java_cert - add ``cert_content`` argument (https://github.com/ansible-collections/community.general/pull/8153). +- keycloak_client, keycloak_clientscope, keycloak_clienttemplate - added ``docker-v2`` protocol support, enhancing alignment with Keycloak's protocol options (https://github.com/ansible-collections/community.general/issues/8215, https://github.com/ansible-collections/community.general/pull/8216). +- nmcli - adds OpenvSwitch support with new ``type`` values ``ovs-port``, ``ovs-interface``, and ``ovs-bridge``, and new ``slave_type`` value ``ovs-port`` (https://github.com/ansible-collections/community.general/pull/8154). +- osx_defaults - add option ``check_types`` to enable changing the type of existing defaults on the fly (https://github.com/ansible-collections/community.general/pull/8173). +- passwordstore lookup - add ``missing_subkey`` parameter defining the behavior of the lookup when a passwordstore subkey is missing (https://github.com/ansible-collections/community.general/pull/8166). +- portage - adds the possibility to explicitely tell portage to write packages to world file (https://github.com/ansible-collections/community.general/issues/6226, https://github.com/ansible-collections/community.general/pull/8236). +- redfish_command - add command ``ResetToDefaults`` to reset manager to default state (https://github.com/ansible-collections/community.general/issues/8163). +- redfish_info - add boolean return value ``MultipartHttpPush`` to ``GetFirmwareUpdateCapabilities`` (https://github.com/ansible-collections/community.general/issues/8194, https://github.com/ansible-collections/community.general/pull/8195). +- ssh_config - allow ``accept-new`` as valid value for ``strict_host_key_checking`` (https://github.com/ansible-collections/community.general/pull/8257). + +community.rabbitmq +~~~~~~~~~~~~~~~~~~ + +- rabbitmq_user - add support to user manipulation through RabbitMQ API (https://github.com/ansible-collections/community.rabbitmq/issues/76) + +community.routeros +~~~~~~~~~~~~~~~~~~ + +- api_info, api_modify - Add RouterOS 7.x support to ``/mpls ldp`` path (https://github.com/ansible-collections/community.routeros/pull/271). +- api_info, api_modify - add ``/ip route rule`` path for RouterOS 6.x (https://github.com/ansible-collections/community.routeros/pull/278). +- api_info, api_modify - add ``/routing filter`` path for RouterOS 6.x (https://github.com/ansible-collections/community.routeros/pull/279). +- api_info, api_modify - add default value for ``from-pool`` field in ``/ipv6 address`` (https://github.com/ansible-collections/community.routeros/pull/270). +- api_info, api_modify - add missing path ``/interface pppoe-server server`` (https://github.com/ansible-collections/community.routeros/pull/273). +- api_info, api_modify - add missing path ``/ip dhcp-relay`` (https://github.com/ansible-collections/community.routeros/pull/276). +- api_info, api_modify - add missing path ``/queue simple`` (https://github.com/ansible-collections/community.routeros/pull/269). +- api_info, api_modify - add missing path ``/queue type`` (https://github.com/ansible-collections/community.routeros/pull/274). +- api_info, api_modify - add missing paths ``/routing bgp aggregate``, ``/routing bgp network`` and ``/routing bgp peer`` (https://github.com/ansible-collections/community.routeros/pull/277). +- api_info, api_modify - add support for paths ``/mpls interface``, ``/mpls ldp accept-filter``, ``/mpls ldp advertise-filter`` and ``mpls ldp interface`` (https://github.com/ansible-collections/community.routeros/pull/272). + +community.vmware +~~~~~~~~~~~~~~~~ + +- Document that all parameters and VMware object names are case sensitive (https://github.com/ansible-collections/community.vmware/issues/2019). +- Drop the outdated (and actually unmaintained) scenario guides (https://github.com/ansible-collections/community.vmware/pull/2022). +- vmware_dvswitch - Add switchIpAddress/switch_ip parameter for netflow config +- vmware_guest_tools_info - Use `toolsVersionStatus2` instead of `toolsVersionStatus` (https://github.com/ansible-collections/community.vmware/issues/2033). + +containers.podman +~~~~~~~~~~~~~~~~~ + +- CI - Fix rootfs test in CI +- CI - add custom podman path to tasks +- CI - add parametrized executables to tests +- podman_container - Add pasta as default network mode after v5 +- podman_container_exec - Return data for podman exec module +- podman_generate_systemd - Fix broken example for podman_generate_systemd (#708) +- podman_login - Update podman_login.py +- podman_play - Add support for kube yaml files with multi-documents (#724) +- podman_play - Update the logic for deleting pods/containers in podman_play +- podman_pod_info - handle return being list in Podman 5 (#713) + +dellemc.powerflex +~~~~~~~~~~~~~~~~~ + +- Added support for PowerFlex ansible modules and roles on Azure. +- Added support for resource group provisioning to validate, deploy, edit, add nodes and delete a resource group. +- The Info module is enhanced to list the firmware repositories. + +netapp.ontap +~~~~~~~~~~~~ + +- na_ontap_cifs - new option `offline_files` added in REST, requires ONTAP 9.10 or later. +- na_ontap_net_ifgrp - updated documentation for parameter `name`. +- na_ontap_vserver_audit - new options `schedule.*` added under `log.rotation`, requires ONTAP 9.6 or later. + +purestorage.flashblade +~~~~~~~~~~~~~~~~~~~~~~ + +- purefb_bucket - Add support for strict 17a-4 WORM compliance. +- purefb_connect - Increase Fan-In and Fan-Out maximums +- purefb_fs - Add ``group_ownership`` parameter from Purity//FB 4.4.0. +- purefb_info - Show array network access policy from Purity//FB 4.4.0 +- purefb_policy - Add support for network access policies from Purity//FB 4.4.0 + +Deprecated Features +------------------- + +community.crypto +~~~~~~~~~~~~~~~~ + +- acme.backends module utils - from community.crypto on, all implementations of ``CryptoBackend`` must override ``get_ordered_csr_identifiers()``. The current default implementation, which simply sorts the result of ``get_csr_identifiers()``, will then be removed (https://github.com/ansible-collections/community.crypto/pull/725). + +community.general +~~~~~~~~~~~~~~~~~ + +- hipchat callback plugin - the hipchat service has been discontinued and the self-hosted variant has been End of Life since 2020. The callback plugin is therefore deprecated and will be removed from community.general 10.0.0 if nobody provides compelling reasons to still keep it (https://github.com/ansible-collections/community.general/issues/8184, https://github.com/ansible-collections/community.general/pull/8189). + +community.vmware +~~~~~~~~~~~~~~~~ + +- vmware_guest_tools_info - `vm_tools_install_status` will be removed from next major version (5.0.0) of the collection since the API call that provides this information has been deprecated by VMware. Use `vm_tools_running_status` / `vm_tools_version_status` instead (https://github.com/ansible-collections/community.vmware/issues/2033). + +Bugfixes +-------- + +Ansible-core +~~~~~~~~~~~~ + +- Consolidated the list of internal static vars, centralized them as constant and completed from some missing entries. +- Fix check for missing _sub_plugin attribute in older connection plugins (https://github.com/ansible/ansible/pull/82954) +- Fixes permission for cache json file from 600 to 644 (https://github.com/ansible/ansible/issues/82683). +- Slight optimization to hostvars (instantiate template only once per host, vs per call to var). +- allow_duplicates - fix evaluating if the current role allows duplicates instead of using the initial value from the duplicate's cached role. +- ansible-config will now properly template defaults before dumping them. +- ansible-test ansible-doc sanity test - do not remove underscores from plugin names in collections before calling ``ansible-doc`` (https://github.com/ansible/ansible/pull/82574). +- async - Fix bug that stopped running async task in ``--check`` when ``check_mode: False`` was set as a task attribute - https://github.com/ansible/ansible/issues/82811 +- blockinfile - when ``create=true`` is used with a filename without path, the module crashed (https://github.com/ansible/ansible/pull/81638). +- dnf - fix an issue when cached RPMs were left in the cache directory even when the keepcache setting was unset (https://github.com/ansible/ansible/issues/81954) +- dnf5 - replace removed API calls +- facts - add a generic detection for VMware in product name. +- fetch - add error message when using ``dest`` with a trailing slash that becomes a local directory - https://github.com/ansible/ansible/issues/82878 +- find - do not fail on Permission errors (https://github.com/ansible/ansible/issues/82027). +- unarchive modules now uses zipinfo options without relying on implementation defaults, making it more compatible with all OS/distributions. +- winrm - Do not raise another exception during cleanup when a task is timed out - https://github.com/ansible/ansible/issues/81095 + +amazon.aws +~~~~~~~~~~ + +- cloudwatchlogs_log_group_info - Implement exponential backoff when making API calls to prevent throttling exceptions (https://github.com/ansible-collections/amazon.aws/issues/2011). +- plugin_utils.inventory - Ensure templated options in lookup plugins are converted (https://github.com/ansible-collections/amazon.aws/issues/1955). +- s3_object - Fix the issue when copying an object with overriding metadata. (https://github.com/ansible-collections/amazon.aws/issues/1991). + +cisco.aci +~~~~~~~~~ + +- Fix auto logout issue in aci connection plugin to keep connection active between tasks +- Fix idempotency for l3out configuration when l3protocol is used in aci_l3out +- Fix issues with new attributes in aci_interface_policy_leaf_policy_group module by adding conditions to include attributes in the payload only when they are specified by the user (#578) +- Fix query in aci_vmm_controller + +cisco.ise +~~~~~~~~~ + +- ansible.utils changes to `">=2.0.0,<5.0"` in galaxy.yml dependencies. + +cisco.mso +~~~~~~~~~ + +- Fix TypeError for iteration on NoneType in mso_schema_template +- Fixed the useg_subnet logic in mso_schema_template_anp_epg_useg_attribute + +community.aws +~~~~~~~~~~~~~ + +- ssm(connection) - fix bucket region logic when region is ``us-east-1`` (https://github.com/ansible-collections/community.aws/pull/1908). + +community.crypto +~~~~~~~~~~~~~~~~ + +- acme_certificate - respect the order of the CNAME and SAN identifiers that are passed on when creating an ACME order (https://github.com/ansible-collections/community.crypto/issues/723, https://github.com/ansible-collections/community.crypto/pull/725). + +community.dns +~~~~~~~~~~~~~ + +- Update Public Suffix List. +- inventory plugins - add unsafe wrapper to avoid marking strings that do not contain ``{`` or ``}`` as unsafe, to work around a bug in AWX (https://github.com/ansible-collections/community.dns/pull/197). + +community.docker +~~~~~~~~~~~~~~~~ + +- docker_compose_v2* - allow ``project_src`` to be a relative path, by converting it to an absolute path before using it (https://github.com/ansible-collections/community.docker/issues/827, https://github.com/ansible-collections/community.docker/pull/828). +- docker_compose_v2* modules - abort with a nice error message instead of crash when the Docker Compose CLI plugin version is ``dev`` (https://github.com/ansible-collections/community.docker/issues/825, https://github.com/ansible-collections/community.docker/pull/826). +- inventory plugins - add unsafe wrapper to avoid marking strings that do not contain ``{`` or ``}`` as unsafe, to work around a bug in AWX (https://github.com/ansible-collections/community.docker/pull/835). + +community.general +~~~~~~~~~~~~~~~~~ + +- aix_filesystem - fix ``_validate_vg`` not passing VG name to ``lsvg_cmd`` (https://github.com/ansible-collections/community.general/issues/8151). +- apt_rpm - when checking whether packages were installed after running ``apt-get -y install ``, only the last package name was checked (https://github.com/ansible-collections/community.general/pull/8263). +- bitwarden_secrets_manager lookup plugin - implements retry with exponential backoff to avoid lookup errors when Bitwardn's API rate limiting is encountered (https://github.com/ansible-collections/community.general/issues/8230, https://github.com/ansible-collections/community.general/pull/8238). +- from_ini filter plugin - disabling interpolation of ``ConfigParser`` to allow converting values with a ``%`` sign (https://github.com/ansible-collections/community.general/issues/8183, https://github.com/ansible-collections/community.general/pull/8185). +- gitlab_issue, gitlab_label, gitlab_milestone - avoid crash during version comparison when the python-gitlab Python module is not installed (https://github.com/ansible-collections/community.general/pull/8158). +- haproxy - fix an issue where HAProxy could get stuck in DRAIN mode when the backend was unreachable (https://github.com/ansible-collections/community.general/issues/8092). +- inventory plugins - add unsafe wrapper to avoid marking strings that do not contain ``{`` or ``}`` as unsafe, to work around a bug in AWX ((https://github.com/ansible-collections/community.general/issues/8212, https://github.com/ansible-collections/community.general/pull/8225). +- ipa - fix get version regex in IPA module_utils (https://github.com/ansible-collections/community.general/pull/8175). +- keycloak_client - add sorted ``defaultClientScopes`` and ``optionalClientScopes`` to normalizations (https://github.com/ansible-collections/community.general/pull/8223). +- keycloak_realm - add normalizations for ``enabledEventTypes`` and ``supportedLocales`` (https://github.com/ansible-collections/community.general/pull/8224). +- puppet - add option ``environment_lang`` to set the environment language encoding. Defaults to lang ``C``. It is recommended to set it to ``C.UTF-8`` or ``en_US.UTF-8`` depending on what is available on your system. (https://github.com/ansible-collections/community.general/issues/8000) +- riak - support ``riak admin`` sub-command in newer Riak KV versions beside the legacy ``riak-admin`` main command (https://github.com/ansible-collections/community.general/pull/8211). +- to_ini filter plugin - disabling interpolation of ``ConfigParser`` to allow converting values with a ``%`` sign (https://github.com/ansible-collections/community.general/issues/8183, https://github.com/ansible-collections/community.general/pull/8185). +- xml - make module work with lxml 5.1.1, which removed some internals that the module was relying on (https://github.com/ansible-collections/community.general/pull/8169). + +community.hrobot +~~~~~~~~~~~~~~~~ + +- inventory plugins - add unsafe wrapper to avoid marking strings that do not contain ``{`` or ``}`` as unsafe, to work around a bug in AWX (https://github.com/ansible-collections/community.hrobot/pull/102). + +community.vmware +~~~~~~~~~~~~~~~~ + +- Use `isinstance()` instead of `type()` for a typecheck (https://github.com/ansible-collections/community.vmware/pull/2011). +- vmware_guest - Fix a error while updating the VM by adding a new disk. While adding a disk to an existing VM, it leaves it in invalid state. (https://github.com/ansible-collections/community.vmware/pull/2044). +- vmware_guest - Fix a missing error message while setting a template parameter with inconsistency guest_os ID (https://github.com/ansible-collections/community.vmware/pull/2036). + +containers.podman +~~~~~~~~~~~~~~~~~ + +- Fix pod info for non-existant pods +- podman_container - Add check and fixed for v5 network diff +- podman_container - Fix pasta networking idempotency for v5 (#728) +- podman_container_exec - Remove unnecessary quotes in podman_container_exec module +- podman_image_info - Fix wrong return data type in podman_image_info +- podman_play - Fix kube play annotations +- podman_pod - Fix broken info of pods in Podman v5 +- podman_pod - Fix pod for Podman v5 +- podman_pod - Fix podman pod v5 broken info issue + +fortinet.fortios +~~~~~~~~~~~~~~~~ + +- Fix the issue that ssl-certificate cannot be set in `fortios_firewall_vip` and `fortios_firewall_vip6`. +- Github issue +- mantis issue + +netapp.ontap +~~~~~~~~~~~~ + +- na_ontap_dns - fix issue with modifying DNS servers in REST. +- na_ontap_fpolicy_policy - fixed issue with idempotency in REST. +- na_ontap_quotas - fixed issue with idempotency in REST. +- na_ontap_security_config - added warning for missing `supported_cipher_suites` to maintain idempotency in REST. + +New Plugins +----------- + +Filter +~~~~~~ + +- community.dns.quote_txt - Quotes a string to use as a TXT record entry +- community.dns.unquote_txt - Unquotes a TXT record entry to a string + +New Modules +----------- + +community.aws +~~~~~~~~~~~~~ + +- community.aws.dynamodb_table_info - Returns information about a Dynamo DB table + +community.crypto +~~~~~~~~~~~~~~~~ + +- community.crypto.x509_certificate_convert - Convert X.509 certificates + +community.general +~~~~~~~~~~~~~~~~~ + +- community.general.keycloak_client_rolescope - Allows administration of Keycloak client roles scope to restrict the usage of certain roles to a other specific client applications. + +dellemc.powerflex +~~~~~~~~~~~~~~~~~ + +- dellemc.powerflex.resource_group - Manage resource group deployments on Dell PowerFlex + +Unchanged Collections +--------------------- + +- ansible.netcommon (still version 5.3.0) +- ansible.posix (still version 1.5.4) +- ansible.utils (still version 2.12.0) +- ansible.windows (still version 2.3.0) +- arista.eos (still version 6.2.2) +- awx.awx (still version 23.9.0) +- azure.azcollection (still version 1.19.0) +- check_point.mgmt (still version 5.2.3) +- chocolatey.chocolatey (still version 1.5.1) +- cisco.asa (still version 4.0.3) +- cisco.ios (still version 5.3.0) +- cisco.iosxr (still version 6.1.1) +- cisco.nxos (still version 5.3.0) +- cisco.ucs (still version 1.10.0) +- cloud.common (still version 2.1.4) +- cloudscale_ch.cloud (still version 2.3.1) +- community.azure (still version 2.0.0) +- community.ciscosmb (still version 1.0.7) +- community.digitalocean (still version 1.26.0) +- community.grafana (still version 1.8.0) +- community.hashi_vault (still version 6.2.0) +- community.libvirt (still version 1.3.0) +- community.mysql (still version 3.9.0) +- community.network (still version 5.0.2) +- community.okd (still version 2.3.0) +- community.postgresql (still version 3.4.0) +- community.proxysql (still version 1.5.1) +- community.sap (still version 2.0.0) +- community.sap_libs (still version 1.4.2) +- community.sops (still version 1.6.7) +- community.windows (still version 2.2.0) +- community.zabbix (still version 2.3.1) +- cyberark.conjur (still version 1.2.2) +- cyberark.pas (still version 1.0.25) +- dellemc.enterprise_sonic (still version 2.4.0) +- dellemc.openmanage (still version 8.7.0) +- dellemc.unity (still version 1.7.1) +- f5networks.f5_modules (still version 1.28.0) +- fortinet.fortimanager (still version 2.4.0) +- frr.frr (still version 2.0.2) +- gluster.gluster (still version 1.0.2) +- google.cloud (still version 1.3.0) +- grafana.grafana (still version 2.2.5) +- hetzner.hcloud (still version 2.5.0) +- hpe.nimble (still version 1.1.4) +- ibm.qradar (still version 2.1.0) +- ibm.spectrum_virtualize (still version 2.0.0) +- ibm.storage_virtualize (still version 2.3.1) +- infoblox.nios_modules (still version 1.6.1) +- inspur.ispim (still version 2.2.0) +- inspur.sm (still version 2.3.0) +- junipernetworks.junos (still version 5.3.1) +- kubernetes.core (still version 2.4.2) +- lowlydba.sqlserver (still version 2.3.2) +- microsoft.ad (still version 1.5.0) +- netapp.aws (still version 21.7.1) +- netapp.azure (still version 21.10.1) +- netapp.cloudmanager (still version 21.22.1) +- netapp.elementsw (still version 21.7.0) +- netapp.storagegrid (still version 21.12.0) +- netapp.um_info (still version 21.8.1) +- netapp_eseries.santricity (still version 1.4.0) +- netbox.netbox (still version 3.17.0) +- ngine_io.cloudstack (still version 2.3.0) +- ngine_io.exoscale (still version 1.1.0) +- openstack.cloud (still version 2.2.0) +- openvswitch.openvswitch (still version 2.1.1) +- ovirt.ovirt (still version 3.2.0) +- purestorage.flasharray (still version 1.27.0) +- purestorage.fusion (still version 1.6.1) +- sensu.sensu_go (still version 1.14.0) +- splunk.es (still version 2.1.2) +- t_systems_mms.icinga_director (still version 2.0.1) +- telekom_mms.icinga_director (still version 1.35.0) +- theforeman.foreman (still version 3.15.0) +- vmware.vmware_rest (still version 2.3.1) +- vultr.cloud (still version 1.12.1) +- vyos.vyos (still version 4.1.0) +- wti.remote (still version 1.0.5) + v9.4.0 ====== @@ -1529,7 +2148,7 @@ cisco.meraki community.aws ~~~~~~~~~~~~~ -- aws_ssm - disable `enable-bracketed-paste` to fix issue with amazon linux 2023 and other OSes (https://github.com/ansible-collections/community.aws/issues/1756) +- aws_ssm - disable ``enable-bracketed-paste`` to fix issue with amazon linux 2023 and other OSes (https://github.com/ansible-collections/community.aws/issues/1756) community.crypto ~~~~~~~~~~~~~~~~ diff --git a/PKG-INFO b/PKG-INFO index 20e6e9c14..7397f21b8 100644 --- a/PKG-INFO +++ b/PKG-INFO @@ -1,6 +1,6 @@ Metadata-Version: 2.1 Name: ansible -Version: 9.4.0 +Version: 9.5.1 Summary: Radically simple IT automation Home-page: https://ansible.com/ Author: Ansible, Inc. @@ -28,7 +28,7 @@ Classifier: Programming Language :: Python :: 3 :: Only Requires-Python: >=3.10 Description-Content-Type: text/x-rst License-File: COPYING -Requires-Dist: ansible-core~=2.16.5 +Requires-Dist: ansible-core~=2.16.6 .. GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) diff --git a/ansible.egg-info/PKG-INFO b/ansible.egg-info/PKG-INFO index 20e6e9c14..7397f21b8 100644 --- a/ansible.egg-info/PKG-INFO +++ b/ansible.egg-info/PKG-INFO @@ -1,6 +1,6 @@ Metadata-Version: 2.1 Name: ansible -Version: 9.4.0 +Version: 9.5.1 Summary: Radically simple IT automation Home-page: https://ansible.com/ Author: Ansible, Inc. @@ -28,7 +28,7 @@ Classifier: Programming Language :: Python :: 3 :: Only Requires-Python: >=3.10 Description-Content-Type: text/x-rst License-File: COPYING -Requires-Dist: ansible-core~=2.16.5 +Requires-Dist: ansible-core~=2.16.6 .. GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) diff --git a/ansible.egg-info/SOURCES.txt b/ansible.egg-info/SOURCES.txt index 27d50939c..526c6786b 100644 --- a/ansible.egg-info/SOURCES.txt +++ b/ansible.egg-info/SOURCES.txt @@ -1562,16 +1562,21 @@ tags.yaml ./ansible_collections/cisco/aci/plugins/doc_fragments/aci.py ./ansible_collections/cisco/aci/plugins/doc_fragments/annotation.py ./ansible_collections/cisco/aci/plugins/doc_fragments/owner.py +./ansible_collections/cisco/aci/plugins/filter/listify.py ./ansible_collections/cisco/aci/plugins/httpapi/aci.py ./ansible_collections/cisco/aci/plugins/lookup/__init__.py ./ansible_collections/cisco/aci/plugins/lookup/interface_range.py ./ansible_collections/cisco/aci/plugins/module_utils/__init__.py ./ansible_collections/cisco/aci/plugins/module_utils/aci.py +./ansible_collections/cisco/aci/plugins/module_utils/annotation_unsupported.py ./ansible_collections/cisco/aci/plugins/module_utils/constants.py ./ansible_collections/cisco/aci/plugins/modules/__init__.py +./ansible_collections/cisco/aci/plugins/modules/aci_aaa_certificate_authority.py ./ansible_collections/cisco/aci/plugins/modules/aci_aaa_custom_privilege.py ./ansible_collections/cisco/aci/plugins/modules/aci_aaa_domain.py +./ansible_collections/cisco/aci/plugins/modules/aci_aaa_key_ring.py ./ansible_collections/cisco/aci/plugins/modules/aci_aaa_role.py +./ansible_collections/cisco/aci/plugins/modules/aci_aaa_security_default_settings.py ./ansible_collections/cisco/aci/plugins/modules/aci_aaa_ssh_auth.py ./ansible_collections/cisco/aci/plugins/modules/aci_aaa_user.py ./ansible_collections/cisco/aci/plugins/modules/aci_aaa_user_certificate.py @@ -1585,16 +1590,31 @@ tags.yaml ./ansible_collections/cisco/aci/plugins/modules/aci_access_span_src_group.py ./ansible_collections/cisco/aci/plugins/modules/aci_access_span_src_group_src.py ./ansible_collections/cisco/aci/plugins/modules/aci_access_span_src_group_src_path.py +./ansible_collections/cisco/aci/plugins/modules/aci_access_spine_interface_profile.py +./ansible_collections/cisco/aci/plugins/modules/aci_access_spine_interface_profile_to_spine_switch_profile.py +./ansible_collections/cisco/aci/plugins/modules/aci_access_spine_interface_selector.py +./ansible_collections/cisco/aci/plugins/modules/aci_access_spine_switch_profile.py +./ansible_collections/cisco/aci/plugins/modules/aci_access_spine_switch_selector.py ./ansible_collections/cisco/aci/plugins/modules/aci_access_sub_port_block_to_access_port.py +./ansible_collections/cisco/aci/plugins/modules/aci_access_switch_policy_group.py +./ansible_collections/cisco/aci/plugins/modules/aci_action_rule_additional_communities.py +./ansible_collections/cisco/aci/plugins/modules/aci_action_rule_set_as_path.py +./ansible_collections/cisco/aci/plugins/modules/aci_action_rule_set_as_path_asn.py ./ansible_collections/cisco/aci/plugins/modules/aci_aep.py ./ansible_collections/cisco/aci/plugins/modules/aci_aep_to_domain.py ./ansible_collections/cisco/aci/plugins/modules/aci_aep_to_epg.py ./ansible_collections/cisco/aci/plugins/modules/aci_ap.py ./ansible_collections/cisco/aci/plugins/modules/aci_bd.py ./ansible_collections/cisco/aci/plugins/modules/aci_bd_dhcp_label.py +./ansible_collections/cisco/aci/plugins/modules/aci_bd_rogue_exception_mac.py ./ansible_collections/cisco/aci/plugins/modules/aci_bd_subnet.py ./ansible_collections/cisco/aci/plugins/modules/aci_bd_to_l3out.py +./ansible_collections/cisco/aci/plugins/modules/aci_bd_to_netflow_monitor_policy.py +./ansible_collections/cisco/aci/plugins/modules/aci_bfd_multihop_node_policy.py +./ansible_collections/cisco/aci/plugins/modules/aci_bgp_address_family_context_policy.py ./ansible_collections/cisco/aci/plugins/modules/aci_bgp_best_path_policy.py +./ansible_collections/cisco/aci/plugins/modules/aci_bgp_peer_prefix_policy.py +./ansible_collections/cisco/aci/plugins/modules/aci_bgp_route_summarization_policy.py ./ansible_collections/cisco/aci/plugins/modules/aci_bgp_rr_asn.py ./ansible_collections/cisco/aci/plugins/modules/aci_bgp_rr_node.py ./ansible_collections/cisco/aci/plugins/modules/aci_bgp_timers_policy.py @@ -1621,6 +1641,8 @@ tags.yaml ./ansible_collections/cisco/aci/plugins/modules/aci_contract_subject.py ./ansible_collections/cisco/aci/plugins/modules/aci_contract_subject_to_filter.py ./ansible_collections/cisco/aci/plugins/modules/aci_contract_subject_to_service_graph.py +./ansible_collections/cisco/aci/plugins/modules/aci_dhcp_option.py +./ansible_collections/cisco/aci/plugins/modules/aci_dhcp_option_policy.py ./ansible_collections/cisco/aci/plugins/modules/aci_dhcp_relay.py ./ansible_collections/cisco/aci/plugins/modules/aci_dhcp_relay_provider.py ./ansible_collections/cisco/aci/plugins/modules/aci_dns_domain.py @@ -1638,17 +1660,28 @@ tags.yaml ./ansible_collections/cisco/aci/plugins/modules/aci_epg_to_contract_interface.py ./ansible_collections/cisco/aci/plugins/modules/aci_epg_to_contract_master.py ./ansible_collections/cisco/aci/plugins/modules/aci_epg_to_domain.py +./ansible_collections/cisco/aci/plugins/modules/aci_epg_useg_attribute_block_statement.py +./ansible_collections/cisco/aci/plugins/modules/aci_epg_useg_attribute_simple_statement.py ./ansible_collections/cisco/aci/plugins/modules/aci_esg.py ./ansible_collections/cisco/aci/plugins/modules/aci_esg_contract_master.py ./ansible_collections/cisco/aci/plugins/modules/aci_esg_epg_selector.py ./ansible_collections/cisco/aci/plugins/modules/aci_esg_ip_subnet_selector.py ./ansible_collections/cisco/aci/plugins/modules/aci_esg_tag_selector.py +./ansible_collections/cisco/aci/plugins/modules/aci_fabric_external_connection_profile.py +./ansible_collections/cisco/aci/plugins/modules/aci_fabric_external_routing_profile.py ./ansible_collections/cisco/aci/plugins/modules/aci_fabric_interface_policy_group.py ./ansible_collections/cisco/aci/plugins/modules/aci_fabric_leaf_profile.py ./ansible_collections/cisco/aci/plugins/modules/aci_fabric_leaf_switch_assoc.py +./ansible_collections/cisco/aci/plugins/modules/aci_fabric_management_access.py +./ansible_collections/cisco/aci/plugins/modules/aci_fabric_management_access_https_cipher.py ./ansible_collections/cisco/aci/plugins/modules/aci_fabric_node.py ./ansible_collections/cisco/aci/plugins/modules/aci_fabric_node_control.py +./ansible_collections/cisco/aci/plugins/modules/aci_fabric_pod.py +./ansible_collections/cisco/aci/plugins/modules/aci_fabric_pod_connectivity_profile.py +./ansible_collections/cisco/aci/plugins/modules/aci_fabric_pod_external_tep.py ./ansible_collections/cisco/aci/plugins/modules/aci_fabric_pod_policy_group.py +./ansible_collections/cisco/aci/plugins/modules/aci_fabric_pod_profile.py +./ansible_collections/cisco/aci/plugins/modules/aci_fabric_pod_remote_pool.py ./ansible_collections/cisco/aci/plugins/modules/aci_fabric_pod_selector.py ./ansible_collections/cisco/aci/plugins/modules/aci_fabric_scheduler.py ./ansible_collections/cisco/aci/plugins/modules/aci_fabric_span_dst_group.py @@ -1672,8 +1705,12 @@ tags.yaml ./ansible_collections/cisco/aci/plugins/modules/aci_interface_blacklist.py ./ansible_collections/cisco/aci/plugins/modules/aci_interface_config.py ./ansible_collections/cisco/aci/plugins/modules/aci_interface_description.py +./ansible_collections/cisco/aci/plugins/modules/aci_interface_policy_bfd.py +./ansible_collections/cisco/aci/plugins/modules/aci_interface_policy_bfd_multihop.py ./ansible_collections/cisco/aci/plugins/modules/aci_interface_policy_cdp.py +./ansible_collections/cisco/aci/plugins/modules/aci_interface_policy_eigrp.py ./ansible_collections/cisco/aci/plugins/modules/aci_interface_policy_fc.py +./ansible_collections/cisco/aci/plugins/modules/aci_interface_policy_hsrp.py ./ansible_collections/cisco/aci/plugins/modules/aci_interface_policy_l2.py ./ansible_collections/cisco/aci/plugins/modules/aci_interface_policy_leaf_breakout_port_group.py ./ansible_collections/cisco/aci/plugins/modules/aci_interface_policy_leaf_fc_policy_group.py @@ -1684,11 +1721,15 @@ tags.yaml ./ansible_collections/cisco/aci/plugins/modules/aci_interface_policy_lldp.py ./ansible_collections/cisco/aci/plugins/modules/aci_interface_policy_mcp.py ./ansible_collections/cisco/aci/plugins/modules/aci_interface_policy_ospf.py +./ansible_collections/cisco/aci/plugins/modules/aci_interface_policy_pim.py ./ansible_collections/cisco/aci/plugins/modules/aci_interface_policy_port_channel.py ./ansible_collections/cisco/aci/plugins/modules/aci_interface_policy_port_security.py ./ansible_collections/cisco/aci/plugins/modules/aci_interface_policy_spanning_tree.py ./ansible_collections/cisco/aci/plugins/modules/aci_interface_policy_spine_policy_group.py +./ansible_collections/cisco/aci/plugins/modules/aci_interface_policy_storm_control.py ./ansible_collections/cisco/aci/plugins/modules/aci_interface_selector_to_switch_policy_leaf_profile.py +./ansible_collections/cisco/aci/plugins/modules/aci_key_policy.py +./ansible_collections/cisco/aci/plugins/modules/aci_keychain_policy.py ./ansible_collections/cisco/aci/plugins/modules/aci_l2out.py ./ansible_collections/cisco/aci/plugins/modules/aci_l2out_extepg.py ./ansible_collections/cisco/aci/plugins/modules/aci_l2out_extepg_to_contract.py @@ -1696,11 +1737,22 @@ tags.yaml ./ansible_collections/cisco/aci/plugins/modules/aci_l2out_logical_interface_profile.py ./ansible_collections/cisco/aci/plugins/modules/aci_l2out_logical_node_profile.py ./ansible_collections/cisco/aci/plugins/modules/aci_l3out.py +./ansible_collections/cisco/aci/plugins/modules/aci_l3out_bfd_interface_profile.py +./ansible_collections/cisco/aci/plugins/modules/aci_l3out_bfd_multihop_interface_profile.py ./ansible_collections/cisco/aci/plugins/modules/aci_l3out_bgp_peer.py ./ansible_collections/cisco/aci/plugins/modules/aci_l3out_bgp_protocol_profile.py +./ansible_collections/cisco/aci/plugins/modules/aci_l3out_dhcp_relay_label.py +./ansible_collections/cisco/aci/plugins/modules/aci_l3out_eigrp_interface_profile.py ./ansible_collections/cisco/aci/plugins/modules/aci_l3out_extepg.py ./ansible_collections/cisco/aci/plugins/modules/aci_l3out_extepg_to_contract.py ./ansible_collections/cisco/aci/plugins/modules/aci_l3out_extsubnet.py +./ansible_collections/cisco/aci/plugins/modules/aci_l3out_floating_svi.py +./ansible_collections/cisco/aci/plugins/modules/aci_l3out_floating_svi_path.py +./ansible_collections/cisco/aci/plugins/modules/aci_l3out_floating_svi_path_secondary_ip.py +./ansible_collections/cisco/aci/plugins/modules/aci_l3out_floating_svi_secondary_ip.py +./ansible_collections/cisco/aci/plugins/modules/aci_l3out_hsrp_group.py +./ansible_collections/cisco/aci/plugins/modules/aci_l3out_hsrp_interface_profile.py +./ansible_collections/cisco/aci/plugins/modules/aci_l3out_hsrp_secondary_vip.py ./ansible_collections/cisco/aci/plugins/modules/aci_l3out_interface.py ./ansible_collections/cisco/aci/plugins/modules/aci_l3out_interface_secondary_ip.py ./ansible_collections/cisco/aci/plugins/modules/aci_l3out_logical_interface_profile.py @@ -1711,6 +1763,7 @@ tags.yaml ./ansible_collections/cisco/aci/plugins/modules/aci_l3out_route_tag_policy.py ./ansible_collections/cisco/aci/plugins/modules/aci_l3out_static_routes.py ./ansible_collections/cisco/aci/plugins/modules/aci_l3out_static_routes_nexthop.py +./ansible_collections/cisco/aci/plugins/modules/aci_l3out_to_sr_mpls_infra_l3out.py ./ansible_collections/cisco/aci/plugins/modules/aci_maintenance_group.py ./ansible_collections/cisco/aci/plugins/modules/aci_maintenance_group_node.py ./ansible_collections/cisco/aci/plugins/modules/aci_maintenance_policy.py @@ -1720,9 +1773,19 @@ tags.yaml ./ansible_collections/cisco/aci/plugins/modules/aci_match_community_term.py ./ansible_collections/cisco/aci/plugins/modules/aci_match_route_destination.py ./ansible_collections/cisco/aci/plugins/modules/aci_match_rule.py +./ansible_collections/cisco/aci/plugins/modules/aci_netflow_exporter_policy.py +./ansible_collections/cisco/aci/plugins/modules/aci_netflow_monitor_policy.py +./ansible_collections/cisco/aci/plugins/modules/aci_netflow_monitor_to_exporter.py +./ansible_collections/cisco/aci/plugins/modules/aci_netflow_record_policy.py +./ansible_collections/cisco/aci/plugins/modules/aci_node_block.py ./ansible_collections/cisco/aci/plugins/modules/aci_node_mgmt_epg.py ./ansible_collections/cisco/aci/plugins/modules/aci_ntp_policy.py ./ansible_collections/cisco/aci/plugins/modules/aci_ntp_server.py +./ansible_collections/cisco/aci/plugins/modules/aci_pim_route_map_entry.py +./ansible_collections/cisco/aci/plugins/modules/aci_pim_route_map_policy.py +./ansible_collections/cisco/aci/plugins/modules/aci_qos_custom_policy.py +./ansible_collections/cisco/aci/plugins/modules/aci_qos_dot1p_class.py +./ansible_collections/cisco/aci/plugins/modules/aci_qos_dscp_class.py ./ansible_collections/cisco/aci/plugins/modules/aci_rest.py ./ansible_collections/cisco/aci/plugins/modules/aci_route_control_context.py ./ansible_collections/cisco/aci/plugins/modules/aci_route_control_profile.py @@ -1733,6 +1796,7 @@ tags.yaml ./ansible_collections/cisco/aci/plugins/modules/aci_snmp_user.py ./ansible_collections/cisco/aci/plugins/modules/aci_static_binding_to_epg.py ./ansible_collections/cisco/aci/plugins/modules/aci_static_node_mgmt_address.py +./ansible_collections/cisco/aci/plugins/modules/aci_subject_label.py ./ansible_collections/cisco/aci/plugins/modules/aci_switch_leaf_selector.py ./ansible_collections/cisco/aci/plugins/modules/aci_switch_policy_leaf_profile.py ./ansible_collections/cisco/aci/plugins/modules/aci_switch_policy_vpc_protection_group.py @@ -1761,6 +1825,7 @@ tags.yaml ./ansible_collections/cisco/aci/plugins/modules/aci_vmm_vswitch_policy.py ./ansible_collections/cisco/aci/plugins/modules/aci_vrf.py ./ansible_collections/cisco/aci/plugins/modules/aci_vrf_leak_internal_subnet.py +./ansible_collections/cisco/aci/plugins/modules/aci_vrf_multicast.py ./ansible_collections/cisco/aci/plugins/modules/aci_vzany_to_contract.py ./ansible_collections/cisco/asa/CHANGELOG.rst ./ansible_collections/cisco/asa/FILES.json @@ -3365,6 +3430,7 @@ tags.yaml ./ansible_collections/cisco/ise/LICENSE ./ansible_collections/cisco/ise/MANIFEST.json ./ansible_collections/cisco/ise/Makefile +./ansible_collections/cisco/ise/Pipfile ./ansible_collections/cisco/ise/README.md ./ansible_collections/cisco/ise/requirements.txt ./ansible_collections/cisco/ise/changelogs/changelog.yaml @@ -3429,7 +3495,6 @@ tags.yaml ./ansible_collections/cisco/ise/playbooks/trustsec_vn_vlan_mapping.yml ./ansible_collections/cisco/ise/playbooks/group_vars/ise_servers ./ansible_collections/cisco/ise/playbooks/vars/device_administration_time_date_conditions.yml -./ansible_collections/cisco/ise/plugins/.DS_Store ./ansible_collections/cisco/ise/plugins/action/aci_bindings_info.py ./ansible_collections/cisco/ise/plugins/action/aci_settings.py ./ansible_collections/cisco/ise/plugins/action/aci_settings_info.py @@ -4287,8 +4352,16 @@ tags.yaml ./ansible_collections/cisco/meraki/plugins/README.md ./ansible_collections/cisco/meraki/plugins/__init__.py ./ansible_collections/cisco/meraki/plugins/action/administered_identities_me_info.py +./ansible_collections/cisco/meraki/plugins/action/administered_licensing_subscription_entitlements_info.py +./ansible_collections/cisco/meraki/plugins/action/administered_licensing_subscription_subscriptions_bind.py +./ansible_collections/cisco/meraki/plugins/action/administered_licensing_subscription_subscriptions_claim.py +./ansible_collections/cisco/meraki/plugins/action/administered_licensing_subscription_subscriptions_claim_key_validate.py +./ansible_collections/cisco/meraki/plugins/action/administered_licensing_subscription_subscriptions_compliance_statuses_info.py +./ansible_collections/cisco/meraki/plugins/action/administered_licensing_subscription_subscriptions_info.py ./ansible_collections/cisco/meraki/plugins/action/devices.py ./ansible_collections/cisco/meraki/plugins/action/devices_appliance_performance_info.py +./ansible_collections/cisco/meraki/plugins/action/devices_appliance_radio_settings.py +./ansible_collections/cisco/meraki/plugins/action/devices_appliance_radio_settings_info.py ./ansible_collections/cisco/meraki/plugins/action/devices_appliance_uplinks_settings.py ./ansible_collections/cisco/meraki/plugins/action/devices_appliance_uplinks_settings_info.py ./ansible_collections/cisco/meraki/plugins/action/devices_appliance_vmx_authentication_token.py @@ -4313,10 +4386,18 @@ tags.yaml ./ansible_collections/cisco/meraki/plugins/action/devices_cellular_sims.py ./ansible_collections/cisco/meraki/plugins/action/devices_cellular_sims_info.py ./ansible_collections/cisco/meraki/plugins/action/devices_info.py +./ansible_collections/cisco/meraki/plugins/action/devices_live_tools_arp_table.py +./ansible_collections/cisco/meraki/plugins/action/devices_live_tools_arp_table_info.py +./ansible_collections/cisco/meraki/plugins/action/devices_live_tools_cable_test.py +./ansible_collections/cisco/meraki/plugins/action/devices_live_tools_cable_test_info.py ./ansible_collections/cisco/meraki/plugins/action/devices_live_tools_ping.py ./ansible_collections/cisco/meraki/plugins/action/devices_live_tools_ping_device.py ./ansible_collections/cisco/meraki/plugins/action/devices_live_tools_ping_device_info.py ./ansible_collections/cisco/meraki/plugins/action/devices_live_tools_ping_info.py +./ansible_collections/cisco/meraki/plugins/action/devices_live_tools_throughput_test.py +./ansible_collections/cisco/meraki/plugins/action/devices_live_tools_throughput_test_info.py +./ansible_collections/cisco/meraki/plugins/action/devices_live_tools_wake_on_lan.py +./ansible_collections/cisco/meraki/plugins/action/devices_live_tools_wake_on_lan_info.py ./ansible_collections/cisco/meraki/plugins/action/devices_lldp_cdp_info.py ./ansible_collections/cisco/meraki/plugins/action/devices_management_interface.py ./ansible_collections/cisco/meraki/plugins/action/devices_management_interface_info.py @@ -4334,6 +4415,7 @@ tags.yaml ./ansible_collections/cisco/meraki/plugins/action/devices_switch_routing_static_routes_info.py ./ansible_collections/cisco/meraki/plugins/action/devices_switch_warm_spare.py ./ansible_collections/cisco/meraki/plugins/action/devices_switch_warm_spare_info.py +./ansible_collections/cisco/meraki/plugins/action/devices_wireless_alternate_management_interface_ipv6.py ./ansible_collections/cisco/meraki/plugins/action/devices_wireless_bluetooth_settings.py ./ansible_collections/cisco/meraki/plugins/action/devices_wireless_bluetooth_settings_info.py ./ansible_collections/cisco/meraki/plugins/action/devices_wireless_connection_stats_info.py @@ -4373,6 +4455,8 @@ tags.yaml ./ansible_collections/cisco/meraki/plugins/action/networks_appliance_ports_info.py ./ansible_collections/cisco/meraki/plugins/action/networks_appliance_prefixes_delegated_statics.py ./ansible_collections/cisco/meraki/plugins/action/networks_appliance_prefixes_delegated_statics_info.py +./ansible_collections/cisco/meraki/plugins/action/networks_appliance_rf_profiles.py +./ansible_collections/cisco/meraki/plugins/action/networks_appliance_rf_profiles_info.py ./ansible_collections/cisco/meraki/plugins/action/networks_appliance_security_intrusion.py ./ansible_collections/cisco/meraki/plugins/action/networks_appliance_security_intrusion_info.py ./ansible_collections/cisco/meraki/plugins/action/networks_appliance_security_malware.py @@ -4394,6 +4478,7 @@ tags.yaml ./ansible_collections/cisco/meraki/plugins/action/networks_appliance_traffic_shaping_uplink_bandwidth_info.py ./ansible_collections/cisco/meraki/plugins/action/networks_appliance_traffic_shaping_uplink_selection.py ./ansible_collections/cisco/meraki/plugins/action/networks_appliance_traffic_shaping_uplink_selection_info.py +./ansible_collections/cisco/meraki/plugins/action/networks_appliance_traffic_shaping_vpn_exclusions.py ./ansible_collections/cisco/meraki/plugins/action/networks_appliance_vlans.py ./ansible_collections/cisco/meraki/plugins/action/networks_appliance_vlans_info.py ./ansible_collections/cisco/meraki/plugins/action/networks_appliance_vlans_settings.py @@ -4481,14 +4566,18 @@ tags.yaml ./ansible_collections/cisco/meraki/plugins/action/networks_sm_devices_device_profiles_info.py ./ansible_collections/cisco/meraki/plugins/action/networks_sm_devices_fields.py ./ansible_collections/cisco/meraki/plugins/action/networks_sm_devices_info.py +./ansible_collections/cisco/meraki/plugins/action/networks_sm_devices_install_apps.py ./ansible_collections/cisco/meraki/plugins/action/networks_sm_devices_lock.py ./ansible_collections/cisco/meraki/plugins/action/networks_sm_devices_modify_tags.py ./ansible_collections/cisco/meraki/plugins/action/networks_sm_devices_move.py ./ansible_collections/cisco/meraki/plugins/action/networks_sm_devices_network_adapters_info.py ./ansible_collections/cisco/meraki/plugins/action/networks_sm_devices_performance_history_info.py +./ansible_collections/cisco/meraki/plugins/action/networks_sm_devices_reboot.py ./ansible_collections/cisco/meraki/plugins/action/networks_sm_devices_refresh_details.py ./ansible_collections/cisco/meraki/plugins/action/networks_sm_devices_security_centers_info.py +./ansible_collections/cisco/meraki/plugins/action/networks_sm_devices_shutdown.py ./ansible_collections/cisco/meraki/plugins/action/networks_sm_devices_unenroll.py +./ansible_collections/cisco/meraki/plugins/action/networks_sm_devices_uninstall_apps.py ./ansible_collections/cisco/meraki/plugins/action/networks_sm_devices_wipe.py ./ansible_collections/cisco/meraki/plugins/action/networks_sm_devices_wlan_lists_info.py ./ansible_collections/cisco/meraki/plugins/action/networks_sm_profiles_info.py @@ -4555,6 +4644,10 @@ tags.yaml ./ansible_collections/cisco/meraki/plugins/action/networks_traffic_shaping_application_categories_info.py ./ansible_collections/cisco/meraki/plugins/action/networks_traffic_shaping_dscp_tagging_options_info.py ./ansible_collections/cisco/meraki/plugins/action/networks_unbind.py +./ansible_collections/cisco/meraki/plugins/action/networks_vlan_profiles.py +./ansible_collections/cisco/meraki/plugins/action/networks_vlan_profiles_assignments_by_device_info.py +./ansible_collections/cisco/meraki/plugins/action/networks_vlan_profiles_assignments_reassign.py +./ansible_collections/cisco/meraki/plugins/action/networks_vlan_profiles_info.py ./ansible_collections/cisco/meraki/plugins/action/networks_webhooks_http_servers.py ./ansible_collections/cisco/meraki/plugins/action/networks_webhooks_http_servers_info.py ./ansible_collections/cisco/meraki/plugins/action/networks_webhooks_payload_templates.py @@ -4573,6 +4666,10 @@ tags.yaml ./ansible_collections/cisco/meraki/plugins/action/networks_wireless_connection_stats_info.py ./ansible_collections/cisco/meraki/plugins/action/networks_wireless_data_rate_history_info.py ./ansible_collections/cisco/meraki/plugins/action/networks_wireless_devices_connection_stats_info.py +./ansible_collections/cisco/meraki/plugins/action/networks_wireless_ethernet_ports_profiles.py +./ansible_collections/cisco/meraki/plugins/action/networks_wireless_ethernet_ports_profiles_assign.py +./ansible_collections/cisco/meraki/plugins/action/networks_wireless_ethernet_ports_profiles_info.py +./ansible_collections/cisco/meraki/plugins/action/networks_wireless_ethernet_ports_profiles_set_default.py ./ansible_collections/cisco/meraki/plugins/action/networks_wireless_failed_connections_info.py ./ansible_collections/cisco/meraki/plugins/action/networks_wireless_latency_history_info.py ./ansible_collections/cisco/meraki/plugins/action/networks_wireless_latency_stats_info.py @@ -4627,6 +4724,9 @@ tags.yaml ./ansible_collections/cisco/meraki/plugins/action/organizations_api_requests_overview_response_codes_by_interval_info.py ./ansible_collections/cisco/meraki/plugins/action/organizations_appliance_security_intrusion.py ./ansible_collections/cisco/meraki/plugins/action/organizations_appliance_security_intrusion_info.py +./ansible_collections/cisco/meraki/plugins/action/organizations_appliance_traffic_shaping_vpn_exclusions_by_network_info.py +./ansible_collections/cisco/meraki/plugins/action/organizations_appliance_uplinks_statuses_overview_info.py +./ansible_collections/cisco/meraki/plugins/action/organizations_appliance_uplinks_usage_by_network_info.py ./ansible_collections/cisco/meraki/plugins/action/organizations_appliance_vpn_third_party_vpnpeers.py ./ansible_collections/cisco/meraki/plugins/action/organizations_appliance_vpn_third_party_vpnpeers_info.py ./ansible_collections/cisco/meraki/plugins/action/organizations_appliance_vpn_vpn_firewall_rules.py @@ -4635,8 +4735,14 @@ tags.yaml ./ansible_collections/cisco/meraki/plugins/action/organizations_branding_policies_info.py ./ansible_collections/cisco/meraki/plugins/action/organizations_branding_policies_priorities.py ./ansible_collections/cisco/meraki/plugins/action/organizations_branding_policies_priorities_info.py +./ansible_collections/cisco/meraki/plugins/action/organizations_camera_boundaries_areas_by_device_info.py +./ansible_collections/cisco/meraki/plugins/action/organizations_camera_boundaries_lines_by_device_info.py ./ansible_collections/cisco/meraki/plugins/action/organizations_camera_custom_analytics_artifacts.py ./ansible_collections/cisco/meraki/plugins/action/organizations_camera_custom_analytics_artifacts_info.py +./ansible_collections/cisco/meraki/plugins/action/organizations_camera_detections_history_by_boundary_by_interval_info.py +./ansible_collections/cisco/meraki/plugins/action/organizations_camera_permissions_info.py +./ansible_collections/cisco/meraki/plugins/action/organizations_camera_roles.py +./ansible_collections/cisco/meraki/plugins/action/organizations_camera_roles_info.py ./ansible_collections/cisco/meraki/plugins/action/organizations_cellular_gateway_uplink_statuses_info.py ./ansible_collections/cisco/meraki/plugins/action/organizations_claim.py ./ansible_collections/cisco/meraki/plugins/action/organizations_clients_bandwidth_usage_history_info.py @@ -4648,7 +4754,9 @@ tags.yaml ./ansible_collections/cisco/meraki/plugins/action/organizations_config_templates_switch_profiles_info.py ./ansible_collections/cisco/meraki/plugins/action/organizations_config_templates_switch_profiles_ports.py ./ansible_collections/cisco/meraki/plugins/action/organizations_config_templates_switch_profiles_ports_info.py +./ansible_collections/cisco/meraki/plugins/action/organizations_devices_availabilities_change_history_info.py ./ansible_collections/cisco/meraki/plugins/action/organizations_devices_availabilities_info.py +./ansible_collections/cisco/meraki/plugins/action/organizations_devices_boots_history_info.py ./ansible_collections/cisco/meraki/plugins/action/organizations_devices_info.py ./ansible_collections/cisco/meraki/plugins/action/organizations_devices_power_modules_statuses_by_device_info.py ./ansible_collections/cisco/meraki/plugins/action/organizations_devices_provisioning_statuses_info.py @@ -4698,7 +4806,11 @@ tags.yaml ./ansible_collections/cisco/meraki/plugins/action/organizations_saml_roles_info.py ./ansible_collections/cisco/meraki/plugins/action/organizations_sensor_readings_history_info.py ./ansible_collections/cisco/meraki/plugins/action/organizations_sensor_readings_latest_info.py +./ansible_collections/cisco/meraki/plugins/action/organizations_sm_admins_roles.py +./ansible_collections/cisco/meraki/plugins/action/organizations_sm_admins_roles_info.py ./ansible_collections/cisco/meraki/plugins/action/organizations_sm_apns_cert_info.py +./ansible_collections/cisco/meraki/plugins/action/organizations_sm_sentry_policies_assignments.py +./ansible_collections/cisco/meraki/plugins/action/organizations_sm_sentry_policies_assignments_by_network_info.py ./ansible_collections/cisco/meraki/plugins/action/organizations_sm_vpp_accounts_info.py ./ansible_collections/cisco/meraki/plugins/action/organizations_snmp.py ./ansible_collections/cisco/meraki/plugins/action/organizations_snmp_info.py @@ -4707,14 +4819,23 @@ tags.yaml ./ansible_collections/cisco/meraki/plugins/action/organizations_summary_top_clients_manufacturers_by_usage_info.py ./ansible_collections/cisco/meraki/plugins/action/organizations_summary_top_devices_by_usage_info.py ./ansible_collections/cisco/meraki/plugins/action/organizations_summary_top_devices_models_by_usage_info.py +./ansible_collections/cisco/meraki/plugins/action/organizations_summary_top_networks_by_status_info.py ./ansible_collections/cisco/meraki/plugins/action/organizations_summary_top_ssids_by_usage_info.py ./ansible_collections/cisco/meraki/plugins/action/organizations_summary_top_switches_by_energy_usage_info.py ./ansible_collections/cisco/meraki/plugins/action/organizations_switch_devices_clone.py ./ansible_collections/cisco/meraki/plugins/action/organizations_switch_ports_by_switch_info.py ./ansible_collections/cisco/meraki/plugins/action/organizations_uplinks_statuses_info.py ./ansible_collections/cisco/meraki/plugins/action/organizations_users.py +./ansible_collections/cisco/meraki/plugins/action/organizations_webhooks_callbacks_statuses_info.py ./ansible_collections/cisco/meraki/plugins/action/organizations_webhooks_logs_info.py +./ansible_collections/cisco/meraki/plugins/action/organizations_wireless_devices_channel_utilization_by_device_info.py +./ansible_collections/cisco/meraki/plugins/action/organizations_wireless_devices_channel_utilization_by_network_info.py +./ansible_collections/cisco/meraki/plugins/action/organizations_wireless_devices_channel_utilization_history_by_device_by_interval_info.py +./ansible_collections/cisco/meraki/plugins/action/organizations_wireless_devices_channel_utilization_history_by_network_by_interval_info.py ./ansible_collections/cisco/meraki/plugins/action/organizations_wireless_devices_ethernet_statuses_info.py +./ansible_collections/cisco/meraki/plugins/action/organizations_wireless_devices_packet_loss_by_client_info.py +./ansible_collections/cisco/meraki/plugins/action/organizations_wireless_devices_packet_loss_by_device_info.py +./ansible_collections/cisco/meraki/plugins/action/organizations_wireless_devices_packet_loss_by_network_info.py ./ansible_collections/cisco/meraki/plugins/doc_fragments/__init__.py ./ansible_collections/cisco/meraki/plugins/doc_fragments/meraki.py ./ansible_collections/cisco/meraki/plugins/doc_fragments/module.py @@ -4724,8 +4845,16 @@ tags.yaml ./ansible_collections/cisco/meraki/plugins/module_utils/network/meraki/meraki.py ./ansible_collections/cisco/meraki/plugins/modules/__init__.py ./ansible_collections/cisco/meraki/plugins/modules/administered_identities_me_info.py +./ansible_collections/cisco/meraki/plugins/modules/administered_licensing_subscription_entitlements_info.py +./ansible_collections/cisco/meraki/plugins/modules/administered_licensing_subscription_subscriptions_bind.py +./ansible_collections/cisco/meraki/plugins/modules/administered_licensing_subscription_subscriptions_claim.py +./ansible_collections/cisco/meraki/plugins/modules/administered_licensing_subscription_subscriptions_claim_key_validate.py +./ansible_collections/cisco/meraki/plugins/modules/administered_licensing_subscription_subscriptions_compliance_statuses_info.py +./ansible_collections/cisco/meraki/plugins/modules/administered_licensing_subscription_subscriptions_info.py ./ansible_collections/cisco/meraki/plugins/modules/devices.py ./ansible_collections/cisco/meraki/plugins/modules/devices_appliance_performance_info.py +./ansible_collections/cisco/meraki/plugins/modules/devices_appliance_radio_settings.py +./ansible_collections/cisco/meraki/plugins/modules/devices_appliance_radio_settings_info.py ./ansible_collections/cisco/meraki/plugins/modules/devices_appliance_uplinks_settings.py ./ansible_collections/cisco/meraki/plugins/modules/devices_appliance_uplinks_settings_info.py ./ansible_collections/cisco/meraki/plugins/modules/devices_appliance_vmx_authentication_token.py @@ -4750,10 +4879,18 @@ tags.yaml ./ansible_collections/cisco/meraki/plugins/modules/devices_cellular_sims.py ./ansible_collections/cisco/meraki/plugins/modules/devices_cellular_sims_info.py ./ansible_collections/cisco/meraki/plugins/modules/devices_info.py +./ansible_collections/cisco/meraki/plugins/modules/devices_live_tools_arp_table.py +./ansible_collections/cisco/meraki/plugins/modules/devices_live_tools_arp_table_info.py +./ansible_collections/cisco/meraki/plugins/modules/devices_live_tools_cable_test.py +./ansible_collections/cisco/meraki/plugins/modules/devices_live_tools_cable_test_info.py ./ansible_collections/cisco/meraki/plugins/modules/devices_live_tools_ping.py ./ansible_collections/cisco/meraki/plugins/modules/devices_live_tools_ping_device.py ./ansible_collections/cisco/meraki/plugins/modules/devices_live_tools_ping_device_info.py ./ansible_collections/cisco/meraki/plugins/modules/devices_live_tools_ping_info.py +./ansible_collections/cisco/meraki/plugins/modules/devices_live_tools_throughput_test.py +./ansible_collections/cisco/meraki/plugins/modules/devices_live_tools_throughput_test_info.py +./ansible_collections/cisco/meraki/plugins/modules/devices_live_tools_wake_on_lan.py +./ansible_collections/cisco/meraki/plugins/modules/devices_live_tools_wake_on_lan_info.py ./ansible_collections/cisco/meraki/plugins/modules/devices_lldp_cdp_info.py ./ansible_collections/cisco/meraki/plugins/modules/devices_management_interface.py ./ansible_collections/cisco/meraki/plugins/modules/devices_management_interface_info.py @@ -4771,6 +4908,7 @@ tags.yaml ./ansible_collections/cisco/meraki/plugins/modules/devices_switch_routing_static_routes_info.py ./ansible_collections/cisco/meraki/plugins/modules/devices_switch_warm_spare.py ./ansible_collections/cisco/meraki/plugins/modules/devices_switch_warm_spare_info.py +./ansible_collections/cisco/meraki/plugins/modules/devices_wireless_alternate_management_interface_ipv6.py ./ansible_collections/cisco/meraki/plugins/modules/devices_wireless_bluetooth_settings.py ./ansible_collections/cisco/meraki/plugins/modules/devices_wireless_bluetooth_settings_info.py ./ansible_collections/cisco/meraki/plugins/modules/devices_wireless_connection_stats_info.py @@ -4853,6 +4991,8 @@ tags.yaml ./ansible_collections/cisco/meraki/plugins/modules/networks_appliance_ports_info.py ./ansible_collections/cisco/meraki/plugins/modules/networks_appliance_prefixes_delegated_statics.py ./ansible_collections/cisco/meraki/plugins/modules/networks_appliance_prefixes_delegated_statics_info.py +./ansible_collections/cisco/meraki/plugins/modules/networks_appliance_rf_profiles.py +./ansible_collections/cisco/meraki/plugins/modules/networks_appliance_rf_profiles_info.py ./ansible_collections/cisco/meraki/plugins/modules/networks_appliance_security_intrusion.py ./ansible_collections/cisco/meraki/plugins/modules/networks_appliance_security_intrusion_info.py ./ansible_collections/cisco/meraki/plugins/modules/networks_appliance_security_malware.py @@ -4874,6 +5014,7 @@ tags.yaml ./ansible_collections/cisco/meraki/plugins/modules/networks_appliance_traffic_shaping_uplink_bandwidth_info.py ./ansible_collections/cisco/meraki/plugins/modules/networks_appliance_traffic_shaping_uplink_selection.py ./ansible_collections/cisco/meraki/plugins/modules/networks_appliance_traffic_shaping_uplink_selection_info.py +./ansible_collections/cisco/meraki/plugins/modules/networks_appliance_traffic_shaping_vpn_exclusions.py ./ansible_collections/cisco/meraki/plugins/modules/networks_appliance_vlans.py ./ansible_collections/cisco/meraki/plugins/modules/networks_appliance_vlans_info.py ./ansible_collections/cisco/meraki/plugins/modules/networks_appliance_vlans_settings.py @@ -4961,14 +5102,18 @@ tags.yaml ./ansible_collections/cisco/meraki/plugins/modules/networks_sm_devices_device_profiles_info.py ./ansible_collections/cisco/meraki/plugins/modules/networks_sm_devices_fields.py ./ansible_collections/cisco/meraki/plugins/modules/networks_sm_devices_info.py +./ansible_collections/cisco/meraki/plugins/modules/networks_sm_devices_install_apps.py ./ansible_collections/cisco/meraki/plugins/modules/networks_sm_devices_lock.py ./ansible_collections/cisco/meraki/plugins/modules/networks_sm_devices_modify_tags.py ./ansible_collections/cisco/meraki/plugins/modules/networks_sm_devices_move.py ./ansible_collections/cisco/meraki/plugins/modules/networks_sm_devices_network_adapters_info.py ./ansible_collections/cisco/meraki/plugins/modules/networks_sm_devices_performance_history_info.py +./ansible_collections/cisco/meraki/plugins/modules/networks_sm_devices_reboot.py ./ansible_collections/cisco/meraki/plugins/modules/networks_sm_devices_refresh_details.py ./ansible_collections/cisco/meraki/plugins/modules/networks_sm_devices_security_centers_info.py +./ansible_collections/cisco/meraki/plugins/modules/networks_sm_devices_shutdown.py ./ansible_collections/cisco/meraki/plugins/modules/networks_sm_devices_unenroll.py +./ansible_collections/cisco/meraki/plugins/modules/networks_sm_devices_uninstall_apps.py ./ansible_collections/cisco/meraki/plugins/modules/networks_sm_devices_wipe.py ./ansible_collections/cisco/meraki/plugins/modules/networks_sm_devices_wlan_lists_info.py ./ansible_collections/cisco/meraki/plugins/modules/networks_sm_profiles_info.py @@ -5035,6 +5180,10 @@ tags.yaml ./ansible_collections/cisco/meraki/plugins/modules/networks_traffic_shaping_application_categories_info.py ./ansible_collections/cisco/meraki/plugins/modules/networks_traffic_shaping_dscp_tagging_options_info.py ./ansible_collections/cisco/meraki/plugins/modules/networks_unbind.py +./ansible_collections/cisco/meraki/plugins/modules/networks_vlan_profiles.py +./ansible_collections/cisco/meraki/plugins/modules/networks_vlan_profiles_assignments_by_device_info.py +./ansible_collections/cisco/meraki/plugins/modules/networks_vlan_profiles_assignments_reassign.py +./ansible_collections/cisco/meraki/plugins/modules/networks_vlan_profiles_info.py ./ansible_collections/cisco/meraki/plugins/modules/networks_webhooks_http_servers.py ./ansible_collections/cisco/meraki/plugins/modules/networks_webhooks_http_servers_info.py ./ansible_collections/cisco/meraki/plugins/modules/networks_webhooks_payload_templates.py @@ -5053,6 +5202,10 @@ tags.yaml ./ansible_collections/cisco/meraki/plugins/modules/networks_wireless_connection_stats_info.py ./ansible_collections/cisco/meraki/plugins/modules/networks_wireless_data_rate_history_info.py ./ansible_collections/cisco/meraki/plugins/modules/networks_wireless_devices_connection_stats_info.py +./ansible_collections/cisco/meraki/plugins/modules/networks_wireless_ethernet_ports_profiles.py +./ansible_collections/cisco/meraki/plugins/modules/networks_wireless_ethernet_ports_profiles_assign.py +./ansible_collections/cisco/meraki/plugins/modules/networks_wireless_ethernet_ports_profiles_info.py +./ansible_collections/cisco/meraki/plugins/modules/networks_wireless_ethernet_ports_profiles_set_default.py ./ansible_collections/cisco/meraki/plugins/modules/networks_wireless_failed_connections_info.py ./ansible_collections/cisco/meraki/plugins/modules/networks_wireless_latency_history_info.py ./ansible_collections/cisco/meraki/plugins/modules/networks_wireless_latency_stats_info.py @@ -5107,6 +5260,9 @@ tags.yaml ./ansible_collections/cisco/meraki/plugins/modules/organizations_api_requests_overview_response_codes_by_interval_info.py ./ansible_collections/cisco/meraki/plugins/modules/organizations_appliance_security_intrusion.py ./ansible_collections/cisco/meraki/plugins/modules/organizations_appliance_security_intrusion_info.py +./ansible_collections/cisco/meraki/plugins/modules/organizations_appliance_traffic_shaping_vpn_exclusions_by_network_info.py +./ansible_collections/cisco/meraki/plugins/modules/organizations_appliance_uplinks_statuses_overview_info.py +./ansible_collections/cisco/meraki/plugins/modules/organizations_appliance_uplinks_usage_by_network_info.py ./ansible_collections/cisco/meraki/plugins/modules/organizations_appliance_vpn_third_party_vpnpeers.py ./ansible_collections/cisco/meraki/plugins/modules/organizations_appliance_vpn_third_party_vpnpeers_info.py ./ansible_collections/cisco/meraki/plugins/modules/organizations_appliance_vpn_vpn_firewall_rules.py @@ -5115,8 +5271,14 @@ tags.yaml ./ansible_collections/cisco/meraki/plugins/modules/organizations_branding_policies_info.py ./ansible_collections/cisco/meraki/plugins/modules/organizations_branding_policies_priorities.py ./ansible_collections/cisco/meraki/plugins/modules/organizations_branding_policies_priorities_info.py +./ansible_collections/cisco/meraki/plugins/modules/organizations_camera_boundaries_areas_by_device_info.py +./ansible_collections/cisco/meraki/plugins/modules/organizations_camera_boundaries_lines_by_device_info.py ./ansible_collections/cisco/meraki/plugins/modules/organizations_camera_custom_analytics_artifacts.py ./ansible_collections/cisco/meraki/plugins/modules/organizations_camera_custom_analytics_artifacts_info.py +./ansible_collections/cisco/meraki/plugins/modules/organizations_camera_detections_history_by_boundary_by_interval_info.py +./ansible_collections/cisco/meraki/plugins/modules/organizations_camera_permissions_info.py +./ansible_collections/cisco/meraki/plugins/modules/organizations_camera_roles.py +./ansible_collections/cisco/meraki/plugins/modules/organizations_camera_roles_info.py ./ansible_collections/cisco/meraki/plugins/modules/organizations_cellular_gateway_uplink_statuses_info.py ./ansible_collections/cisco/meraki/plugins/modules/organizations_claim.py ./ansible_collections/cisco/meraki/plugins/modules/organizations_clients_bandwidth_usage_history_info.py @@ -5128,7 +5290,9 @@ tags.yaml ./ansible_collections/cisco/meraki/plugins/modules/organizations_config_templates_switch_profiles_info.py ./ansible_collections/cisco/meraki/plugins/modules/organizations_config_templates_switch_profiles_ports.py ./ansible_collections/cisco/meraki/plugins/modules/organizations_config_templates_switch_profiles_ports_info.py +./ansible_collections/cisco/meraki/plugins/modules/organizations_devices_availabilities_change_history_info.py ./ansible_collections/cisco/meraki/plugins/modules/organizations_devices_availabilities_info.py +./ansible_collections/cisco/meraki/plugins/modules/organizations_devices_boots_history_info.py ./ansible_collections/cisco/meraki/plugins/modules/organizations_devices_info.py ./ansible_collections/cisco/meraki/plugins/modules/organizations_devices_power_modules_statuses_by_device_info.py ./ansible_collections/cisco/meraki/plugins/modules/organizations_devices_provisioning_statuses_info.py @@ -5178,7 +5342,11 @@ tags.yaml ./ansible_collections/cisco/meraki/plugins/modules/organizations_saml_roles_info.py ./ansible_collections/cisco/meraki/plugins/modules/organizations_sensor_readings_history_info.py ./ansible_collections/cisco/meraki/plugins/modules/organizations_sensor_readings_latest_info.py +./ansible_collections/cisco/meraki/plugins/modules/organizations_sm_admins_roles.py +./ansible_collections/cisco/meraki/plugins/modules/organizations_sm_admins_roles_info.py ./ansible_collections/cisco/meraki/plugins/modules/organizations_sm_apns_cert_info.py +./ansible_collections/cisco/meraki/plugins/modules/organizations_sm_sentry_policies_assignments.py +./ansible_collections/cisco/meraki/plugins/modules/organizations_sm_sentry_policies_assignments_by_network_info.py ./ansible_collections/cisco/meraki/plugins/modules/organizations_sm_vpp_accounts_info.py ./ansible_collections/cisco/meraki/plugins/modules/organizations_snmp.py ./ansible_collections/cisco/meraki/plugins/modules/organizations_snmp_info.py @@ -5187,14 +5355,23 @@ tags.yaml ./ansible_collections/cisco/meraki/plugins/modules/organizations_summary_top_clients_manufacturers_by_usage_info.py ./ansible_collections/cisco/meraki/plugins/modules/organizations_summary_top_devices_by_usage_info.py ./ansible_collections/cisco/meraki/plugins/modules/organizations_summary_top_devices_models_by_usage_info.py +./ansible_collections/cisco/meraki/plugins/modules/organizations_summary_top_networks_by_status_info.py ./ansible_collections/cisco/meraki/plugins/modules/organizations_summary_top_ssids_by_usage_info.py ./ansible_collections/cisco/meraki/plugins/modules/organizations_summary_top_switches_by_energy_usage_info.py ./ansible_collections/cisco/meraki/plugins/modules/organizations_switch_devices_clone.py ./ansible_collections/cisco/meraki/plugins/modules/organizations_switch_ports_by_switch_info.py ./ansible_collections/cisco/meraki/plugins/modules/organizations_uplinks_statuses_info.py ./ansible_collections/cisco/meraki/plugins/modules/organizations_users.py +./ansible_collections/cisco/meraki/plugins/modules/organizations_webhooks_callbacks_statuses_info.py ./ansible_collections/cisco/meraki/plugins/modules/organizations_webhooks_logs_info.py +./ansible_collections/cisco/meraki/plugins/modules/organizations_wireless_devices_channel_utilization_by_device_info.py +./ansible_collections/cisco/meraki/plugins/modules/organizations_wireless_devices_channel_utilization_by_network_info.py +./ansible_collections/cisco/meraki/plugins/modules/organizations_wireless_devices_channel_utilization_history_by_device_by_interval_info.py +./ansible_collections/cisco/meraki/plugins/modules/organizations_wireless_devices_channel_utilization_history_by_network_by_interval_info.py ./ansible_collections/cisco/meraki/plugins/modules/organizations_wireless_devices_ethernet_statuses_info.py +./ansible_collections/cisco/meraki/plugins/modules/organizations_wireless_devices_packet_loss_by_client_info.py +./ansible_collections/cisco/meraki/plugins/modules/organizations_wireless_devices_packet_loss_by_device_info.py +./ansible_collections/cisco/meraki/plugins/modules/organizations_wireless_devices_packet_loss_by_network_info.py ./ansible_collections/cisco/meraki/plugins/plugin_utils/__init__.py ./ansible_collections/cisco/meraki/plugins/plugin_utils/exceptions.py ./ansible_collections/cisco/meraki/plugins/plugin_utils/meraki.py @@ -5244,6 +5421,8 @@ tags.yaml ./ansible_collections/cisco/mso/plugins/modules/mso_schema_site_bd.py ./ansible_collections/cisco/mso/plugins/modules/mso_schema_site_bd_l3out.py ./ansible_collections/cisco/mso/plugins/modules/mso_schema_site_bd_subnet.py +./ansible_collections/cisco/mso/plugins/modules/mso_schema_site_contract_service_graph.py +./ansible_collections/cisco/mso/plugins/modules/mso_schema_site_contract_service_graph_listener.py ./ansible_collections/cisco/mso/plugins/modules/mso_schema_site_external_epg.py ./ansible_collections/cisco/mso/plugins/modules/mso_schema_site_external_epg_selector.py ./ansible_collections/cisco/mso/plugins/modules/mso_schema_site_l3out.py @@ -5919,6 +6098,7 @@ tags.yaml ./ansible_collections/community/aws/plugins/modules/dms_endpoint.py ./ansible_collections/community/aws/plugins/modules/dms_replication_subnet_group.py ./ansible_collections/community/aws/plugins/modules/dynamodb_table.py +./ansible_collections/community/aws/plugins/modules/dynamodb_table_info.py ./ansible_collections/community/aws/plugins/modules/dynamodb_ttl.py ./ansible_collections/community/aws/plugins/modules/ec2_ami_copy.py ./ansible_collections/community/aws/plugins/modules/ec2_carrier_gateway.py @@ -6183,6 +6363,7 @@ tags.yaml ./ansible_collections/community/crypto/plugins/modules/openssl_signature.py ./ansible_collections/community/crypto/plugins/modules/openssl_signature_info.py ./ansible_collections/community/crypto/plugins/modules/x509_certificate.py +./ansible_collections/community/crypto/plugins/modules/x509_certificate_convert.py ./ansible_collections/community/crypto/plugins/modules/x509_certificate_info.py ./ansible_collections/community/crypto/plugins/modules/x509_certificate_pipe.py ./ansible_collections/community/crypto/plugins/modules/x509_crl.py @@ -6304,8 +6485,11 @@ tags.yaml ./ansible_collections/community/dns/plugins/filter/domain_suffix.py ./ansible_collections/community/dns/plugins/filter/get_public_suffix.yml ./ansible_collections/community/dns/plugins/filter/get_registrable_domain.yml +./ansible_collections/community/dns/plugins/filter/quote_txt.yml ./ansible_collections/community/dns/plugins/filter/remove_public_suffix.yml ./ansible_collections/community/dns/plugins/filter/remove_registrable_domain.yml +./ansible_collections/community/dns/plugins/filter/txt.py +./ansible_collections/community/dns/plugins/filter/unquote_txt.yml ./ansible_collections/community/dns/plugins/inventory/hetzner_dns_records.py ./ansible_collections/community/dns/plugins/inventory/hosttech_dns_records.py ./ansible_collections/community/dns/plugins/lookup/lookup.py @@ -6358,6 +6542,7 @@ tags.yaml ./ansible_collections/community/dns/plugins/plugin_utils/public_suffix.py ./ansible_collections/community/dns/plugins/plugin_utils/resolver.py ./ansible_collections/community/dns/plugins/plugin_utils/templated_options.py +./ansible_collections/community/dns/plugins/plugin_utils/unsafe.py ./ansible_collections/community/dns/plugins/plugin_utils/inventory/records.py ./ansible_collections/community/docker/CHANGELOG.md ./ansible_collections/community/docker/CHANGELOG.md.license @@ -6470,6 +6655,7 @@ tags.yaml ./ansible_collections/community/docker/plugins/plugin_utils/common.py ./ansible_collections/community/docker/plugins/plugin_utils/common_api.py ./ansible_collections/community/docker/plugins/plugin_utils/socket_handler.py +./ansible_collections/community/docker/plugins/plugin_utils/unsafe.py ./ansible_collections/community/general/CHANGELOG.md ./ansible_collections/community/general/CHANGELOG.md.license ./ansible_collections/community/general/CHANGELOG.rst @@ -6671,6 +6857,7 @@ tags.yaml ./ansible_collections/community/general/plugins/module_utils/consul.py ./ansible_collections/community/general/plugins/module_utils/csv.py ./ansible_collections/community/general/plugins/module_utils/database.py +./ansible_collections/community/general/plugins/module_utils/datetime.py ./ansible_collections/community/general/plugins/module_utils/deps.py ./ansible_collections/community/general/plugins/module_utils/dimensiondata.py ./ansible_collections/community/general/plugins/module_utils/gandi_livedns_api.py @@ -6968,6 +7155,7 @@ tags.yaml ./ansible_collections/community/general/plugins/modules/keycloak_authz_permission_info.py ./ansible_collections/community/general/plugins/modules/keycloak_client.py ./ansible_collections/community/general/plugins/modules/keycloak_client_rolemapping.py +./ansible_collections/community/general/plugins/modules/keycloak_client_rolescope.py ./ansible_collections/community/general/plugins/modules/keycloak_clientscope.py ./ansible_collections/community/general/plugins/modules/keycloak_clientscope_type.py ./ansible_collections/community/general/plugins/modules/keycloak_clientsecret_info.py @@ -7346,6 +7534,7 @@ tags.yaml ./ansible_collections/community/general/plugins/modules/zpool_facts.py ./ansible_collections/community/general/plugins/modules/zypper.py ./ansible_collections/community/general/plugins/modules/zypper_repository.py +./ansible_collections/community/general/plugins/plugin_utils/unsafe.py ./ansible_collections/community/general/plugins/test/a_module.py ./ansible_collections/community/general/plugins/test/fqdn_valid.py ./ansible_collections/community/grafana/CHANGELOG.rst @@ -7554,6 +7743,9 @@ tags.yaml ./ansible_collections/community/hrobot/plugins/modules/ssh_key.py ./ansible_collections/community/hrobot/plugins/modules/ssh_key_info.py ./ansible_collections/community/hrobot/plugins/modules/v_switch.py +./ansible_collections/community/hrobot/plugins/plugin_utils/unsafe.py +./ansible_collections/community/library_inventory_filtering_v1/CHANGELOG.md +./ansible_collections/community/library_inventory_filtering_v1/CHANGELOG.md.license ./ansible_collections/community/library_inventory_filtering_v1/CHANGELOG.rst ./ansible_collections/community/library_inventory_filtering_v1/CHANGELOG.rst.license ./ansible_collections/community/library_inventory_filtering_v1/COPYING @@ -8777,6 +8969,7 @@ tags.yaml ./ansible_collections/community/vmware/plugins/modules/vcenter_root_password_expiration.py ./ansible_collections/community/vmware/plugins/modules/vcenter_standard_key_provider.py ./ansible_collections/community/vmware/plugins/modules/vmware_about_info.py +./ansible_collections/community/vmware/plugins/modules/vmware_all_snapshots_info.py ./ansible_collections/community/vmware/plugins/modules/vmware_category.py ./ansible_collections/community/vmware/plugins/modules/vmware_category_info.py ./ansible_collections/community/vmware/plugins/modules/vmware_cfg_backup.py @@ -9370,6 +9563,7 @@ tags.yaml ./ansible_collections/containers/podman/plugins/module_utils/podman/common.py ./ansible_collections/containers/podman/plugins/module_utils/podman/podman_container_lib.py ./ansible_collections/containers/podman/plugins/module_utils/podman/podman_pod_lib.py +./ansible_collections/containers/podman/plugins/module_utils/podman/quadlet.py ./ansible_collections/containers/podman/plugins/modules/__init__.py ./ansible_collections/containers/podman/plugins/modules/podman_container.py ./ansible_collections/containers/podman/plugins/modules/podman_container_exec.py @@ -10638,6 +10832,7 @@ tags.yaml ./ansible_collections/dellemc/powerflex/playbooks/modules/protection_domain.yml ./ansible_collections/dellemc/powerflex/playbooks/modules/replication_consistency_group.yml ./ansible_collections/dellemc/powerflex/playbooks/modules/replication_pair.yml +./ansible_collections/dellemc/powerflex/playbooks/modules/resource_group.yml ./ansible_collections/dellemc/powerflex/playbooks/modules/sdc.yml ./ansible_collections/dellemc/powerflex/playbooks/modules/sds.yml ./ansible_collections/dellemc/powerflex/playbooks/modules/snapshot.yml @@ -10666,6 +10861,7 @@ tags.yaml ./ansible_collections/dellemc/powerflex/plugins/modules/protection_domain.py ./ansible_collections/dellemc/powerflex/plugins/modules/replication_consistency_group.py ./ansible_collections/dellemc/powerflex/plugins/modules/replication_pair.py +./ansible_collections/dellemc/powerflex/plugins/modules/resource_group.py ./ansible_collections/dellemc/powerflex/plugins/modules/sdc.py ./ansible_collections/dellemc/powerflex/plugins/modules/sds.py ./ansible_collections/dellemc/powerflex/plugins/modules/snapshot.py @@ -12400,8 +12596,10 @@ tags.yaml ./ansible_collections/fortinet/fortios/plugins/modules/fortios_cifs_profile.py ./ansible_collections/fortinet/fortios/plugins/modules/fortios_configuration_fact.py ./ansible_collections/fortinet/fortios/plugins/modules/fortios_credential_store_domain_controller.py +./ansible_collections/fortinet/fortios/plugins/modules/fortios_diameter_filter_profile.py ./ansible_collections/fortinet/fortios/plugins/modules/fortios_dlp_data_type.py ./ansible_collections/fortinet/fortios/plugins/modules/fortios_dlp_dictionary.py +./ansible_collections/fortinet/fortios/plugins/modules/fortios_dlp_exact_data_match.py ./ansible_collections/fortinet/fortios/plugins/modules/fortios_dlp_filepattern.py ./ansible_collections/fortinet/fortios/plugins/modules/fortios_dlp_fp_doc_source.py ./ansible_collections/fortinet/fortios/plugins/modules/fortios_dlp_fp_sensitivity.py @@ -12817,6 +13015,7 @@ tags.yaml ./ansible_collections/fortinet/fortios/plugins/modules/fortios_system_network_visibility.py ./ansible_collections/fortinet/fortios/plugins/modules/fortios_system_np6.py ./ansible_collections/fortinet/fortios/plugins/modules/fortios_system_npu.py +./ansible_collections/fortinet/fortios/plugins/modules/fortios_system_npu_vlink.py ./ansible_collections/fortinet/fortios/plugins/modules/fortios_system_ntp.py ./ansible_collections/fortinet/fortios/plugins/modules/fortios_system_object_tagging.py ./ansible_collections/fortinet/fortios/plugins/modules/fortios_system_password_policy.py @@ -12903,6 +13102,7 @@ tags.yaml ./ansible_collections/fortinet/fortios/plugins/modules/fortios_user_device_group.py ./ansible_collections/fortinet/fortios/plugins/modules/fortios_user_domain_controller.py ./ansible_collections/fortinet/fortios/plugins/modules/fortios_user_exchange.py +./ansible_collections/fortinet/fortios/plugins/modules/fortios_user_external_identity_provider.py ./ansible_collections/fortinet/fortios/plugins/modules/fortios_user_fortitoken.py ./ansible_collections/fortinet/fortios/plugins/modules/fortios_user_fsso.py ./ansible_collections/fortinet/fortios/plugins/modules/fortios_user_fsso_polling.py @@ -12921,6 +13121,7 @@ tags.yaml ./ansible_collections/fortinet/fortios/plugins/modules/fortios_user_security_exempt_list.py ./ansible_collections/fortinet/fortios/plugins/modules/fortios_user_setting.py ./ansible_collections/fortinet/fortios/plugins/modules/fortios_user_tacacsplus.py +./ansible_collections/fortinet/fortios/plugins/modules/fortios_videofilter_keyword.py ./ansible_collections/fortinet/fortios/plugins/modules/fortios_videofilter_profile.py ./ansible_collections/fortinet/fortios/plugins/modules/fortios_videofilter_youtube_channel_filter.py ./ansible_collections/fortinet/fortios/plugins/modules/fortios_videofilter_youtube_key.py @@ -12946,6 +13147,7 @@ tags.yaml ./ansible_collections/fortinet/fortios/plugins/modules/fortios_vpn_l2tp.py ./ansible_collections/fortinet/fortios/plugins/modules/fortios_vpn_ocvpn.py ./ansible_collections/fortinet/fortios/plugins/modules/fortios_vpn_pptp.py +./ansible_collections/fortinet/fortios/plugins/modules/fortios_vpn_qkd.py ./ansible_collections/fortinet/fortios/plugins/modules/fortios_vpn_ssl_client.py ./ansible_collections/fortinet/fortios/plugins/modules/fortios_vpn_ssl_settings.py ./ansible_collections/fortinet/fortios/plugins/modules/fortios_vpn_ssl_web_host_check_software.py @@ -13818,6 +14020,7 @@ tags.yaml ./ansible_collections/infinidat/infinibox/plugins/modules/infini_fibre_channel_switch.py ./ansible_collections/infinidat/infinibox/plugins/modules/infini_fs.py ./ansible_collections/infinidat/infinibox/plugins/modules/infini_host.py +./ansible_collections/infinidat/infinibox/plugins/modules/infini_infinimetrics.py ./ansible_collections/infinidat/infinibox/plugins/modules/infini_map.py ./ansible_collections/infinidat/infinibox/plugins/modules/infini_metadata.py ./ansible_collections/infinidat/infinibox/plugins/modules/infini_network_space.py @@ -15041,7 +15244,6 @@ tags.yaml ./ansible_collections/netapp/ontap/MANIFEST.json ./ansible_collections/netapp/ontap/README.md ./ansible_collections/netapp/ontap/requirements.txt -./ansible_collections/netapp/ontap/changelogs/.DS_Store ./ansible_collections/netapp/ontap/changelogs/.plugin-cache.yaml ./ansible_collections/netapp/ontap/changelogs/changelog.yaml ./ansible_collections/netapp/ontap/changelogs/config.yaml @@ -15511,6 +15713,7 @@ tags.yaml ./ansible_collections/netapp/ontap/changelogs/fragments/DEVOPS-6330.yaml ./ansible_collections/netapp/ontap/changelogs/fragments/DEVOPS-6331.yaml ./ansible_collections/netapp/ontap/changelogs/fragments/DEVOPS-6341.yaml +./ansible_collections/netapp/ontap/changelogs/fragments/DEVOPS-6356.yaml ./ansible_collections/netapp/ontap/changelogs/fragments/DEVOPS-6374.yaml ./ansible_collections/netapp/ontap/changelogs/fragments/DEVOPS-6386.yaml ./ansible_collections/netapp/ontap/changelogs/fragments/DEVOPS-6389.yaml @@ -15540,6 +15743,12 @@ tags.yaml ./ansible_collections/netapp/ontap/changelogs/fragments/DEVOPS-6671.yaml ./ansible_collections/netapp/ontap/changelogs/fragments/DEVOPS-6680.yaml ./ansible_collections/netapp/ontap/changelogs/fragments/DEVOPS-6681.yaml +./ansible_collections/netapp/ontap/changelogs/fragments/DEVOPS-6691.yaml +./ansible_collections/netapp/ontap/changelogs/fragments/DEVOPS-6715.yaml +./ansible_collections/netapp/ontap/changelogs/fragments/DEVOPS-6721.yaml +./ansible_collections/netapp/ontap/changelogs/fragments/DEVOPS-6747.yaml +./ansible_collections/netapp/ontap/changelogs/fragments/DEVOPS-6807.yaml +./ansible_collections/netapp/ontap/changelogs/fragments/DEVOPS-6825.yaml ./ansible_collections/netapp/ontap/changelogs/fragments/GITHUB-174.yaml ./ansible_collections/netapp/ontap/changelogs/fragments/github-110.yaml ./ansible_collections/netapp/ontap/changelogs/fragments/github-56.yaml @@ -17109,6 +17318,10 @@ tags.yaml ./ansible_collections/purestorage/flashblade/changelogs/fragments/263_fix_multiple_modules_idempotency.yaml ./ansible_collections/purestorage/flashblade/changelogs/fragments/266_bucket_fix.yaml ./ansible_collections/purestorage/flashblade/changelogs/fragments/268_multi-chassis-lag.yaml +./ansible_collections/purestorage/flashblade/changelogs/fragments/270_add_go.yaml +./ansible_collections/purestorage/flashblade/changelogs/fragments/271_add_worm.yaml +./ansible_collections/purestorage/flashblade/changelogs/fragments/273_add_nap.yaml +./ansible_collections/purestorage/flashblade/changelogs/fragments/274_fan_in.yaml ./ansible_collections/purestorage/flashblade/changelogs/fragments/76_default_fs_size.yaml ./ansible_collections/purestorage/flashblade/changelogs/fragments/77_filesystem_policies_info.yaml ./ansible_collections/purestorage/flashblade/changelogs/fragments/78_update_filesystem_replica_link.yaml @@ -19059,6 +19272,7 @@ ansible_collections/amazon/aws/tests/integration/targets/inventory_aws_ec2/playb ansible_collections/amazon/aws/tests/integration/targets/inventory_aws_ec2/tasks/setup.yml ansible_collections/amazon/aws/tests/integration/targets/inventory_aws_ec2/tasks/tear_down.yml ansible_collections/amazon/aws/tests/integration/targets/inventory_aws_ec2/tasks/test_refresh_inventory.yml +ansible_collections/amazon/aws/tests/integration/targets/inventory_aws_ec2/templates/config.ini.j2 ansible_collections/amazon/aws/tests/integration/targets/inventory_aws_ec2/templates/inventory.yml.j2 ansible_collections/amazon/aws/tests/integration/targets/inventory_aws_ec2/templates/inventory_with_cache.yml.j2 ansible_collections/amazon/aws/tests/integration/targets/inventory_aws_ec2/templates/inventory_with_concatenation.yml.j2 @@ -19412,6 +19626,7 @@ ansible_collections/amazon/aws/tests/unit/module_utils/errors/aws_error_handler/ ansible_collections/amazon/aws/tests/unit/module_utils/exceptions/__init__.py ansible_collections/amazon/aws/tests/unit/module_utils/exceptions/test_exceptions.py ansible_collections/amazon/aws/tests/unit/module_utils/iam/test_iam_error_handler.py +ansible_collections/amazon/aws/tests/unit/module_utils/iam/test_iam_resource_transforms.py ansible_collections/amazon/aws/tests/unit/module_utils/iam/test_validate_iam_identifiers.py ansible_collections/amazon/aws/tests/unit/module_utils/modules/__init__.py ansible_collections/amazon/aws/tests/unit/module_utils/modules/ansible_aws_module/__init__.py @@ -19431,6 +19646,7 @@ ansible_collections/amazon/aws/tests/unit/module_utils/retries/test_botocore_exc ansible_collections/amazon/aws/tests/unit/module_utils/retries/test_retry_wrapper.py ansible_collections/amazon/aws/tests/unit/module_utils/transformation/__init__.py ansible_collections/amazon/aws/tests/unit/module_utils/transformation/test_ansible_dict_to_boto3_filter_list.py +ansible_collections/amazon/aws/tests/unit/module_utils/transformation/test_boto3_resource_to_ansible_dict.py ansible_collections/amazon/aws/tests/unit/module_utils/transformation/test_map_complex_type.py ansible_collections/amazon/aws/tests/unit/module_utils/transformation/test_scrub_none_parameters.py ansible_collections/amazon/aws/tests/unit/plugin_utils/__init__.py @@ -23300,16 +23516,21 @@ ansible_collections/cisco/aci/plugins/doc_fragments/__init__.py ansible_collections/cisco/aci/plugins/doc_fragments/aci.py ansible_collections/cisco/aci/plugins/doc_fragments/annotation.py ansible_collections/cisco/aci/plugins/doc_fragments/owner.py +ansible_collections/cisco/aci/plugins/filter/listify.py ansible_collections/cisco/aci/plugins/httpapi/aci.py ansible_collections/cisco/aci/plugins/lookup/__init__.py ansible_collections/cisco/aci/plugins/lookup/interface_range.py ansible_collections/cisco/aci/plugins/module_utils/__init__.py ansible_collections/cisco/aci/plugins/module_utils/aci.py +ansible_collections/cisco/aci/plugins/module_utils/annotation_unsupported.py ansible_collections/cisco/aci/plugins/module_utils/constants.py ansible_collections/cisco/aci/plugins/modules/__init__.py +ansible_collections/cisco/aci/plugins/modules/aci_aaa_certificate_authority.py ansible_collections/cisco/aci/plugins/modules/aci_aaa_custom_privilege.py ansible_collections/cisco/aci/plugins/modules/aci_aaa_domain.py +ansible_collections/cisco/aci/plugins/modules/aci_aaa_key_ring.py ansible_collections/cisco/aci/plugins/modules/aci_aaa_role.py +ansible_collections/cisco/aci/plugins/modules/aci_aaa_security_default_settings.py ansible_collections/cisco/aci/plugins/modules/aci_aaa_ssh_auth.py ansible_collections/cisco/aci/plugins/modules/aci_aaa_user.py ansible_collections/cisco/aci/plugins/modules/aci_aaa_user_certificate.py @@ -23323,16 +23544,31 @@ ansible_collections/cisco/aci/plugins/modules/aci_access_span_filter_group_entry ansible_collections/cisco/aci/plugins/modules/aci_access_span_src_group.py ansible_collections/cisco/aci/plugins/modules/aci_access_span_src_group_src.py ansible_collections/cisco/aci/plugins/modules/aci_access_span_src_group_src_path.py +ansible_collections/cisco/aci/plugins/modules/aci_access_spine_interface_profile.py +ansible_collections/cisco/aci/plugins/modules/aci_access_spine_interface_profile_to_spine_switch_profile.py +ansible_collections/cisco/aci/plugins/modules/aci_access_spine_interface_selector.py +ansible_collections/cisco/aci/plugins/modules/aci_access_spine_switch_profile.py +ansible_collections/cisco/aci/plugins/modules/aci_access_spine_switch_selector.py ansible_collections/cisco/aci/plugins/modules/aci_access_sub_port_block_to_access_port.py +ansible_collections/cisco/aci/plugins/modules/aci_access_switch_policy_group.py +ansible_collections/cisco/aci/plugins/modules/aci_action_rule_additional_communities.py +ansible_collections/cisco/aci/plugins/modules/aci_action_rule_set_as_path.py +ansible_collections/cisco/aci/plugins/modules/aci_action_rule_set_as_path_asn.py ansible_collections/cisco/aci/plugins/modules/aci_aep.py ansible_collections/cisco/aci/plugins/modules/aci_aep_to_domain.py ansible_collections/cisco/aci/plugins/modules/aci_aep_to_epg.py ansible_collections/cisco/aci/plugins/modules/aci_ap.py ansible_collections/cisco/aci/plugins/modules/aci_bd.py ansible_collections/cisco/aci/plugins/modules/aci_bd_dhcp_label.py +ansible_collections/cisco/aci/plugins/modules/aci_bd_rogue_exception_mac.py ansible_collections/cisco/aci/plugins/modules/aci_bd_subnet.py ansible_collections/cisco/aci/plugins/modules/aci_bd_to_l3out.py +ansible_collections/cisco/aci/plugins/modules/aci_bd_to_netflow_monitor_policy.py +ansible_collections/cisco/aci/plugins/modules/aci_bfd_multihop_node_policy.py +ansible_collections/cisco/aci/plugins/modules/aci_bgp_address_family_context_policy.py ansible_collections/cisco/aci/plugins/modules/aci_bgp_best_path_policy.py +ansible_collections/cisco/aci/plugins/modules/aci_bgp_peer_prefix_policy.py +ansible_collections/cisco/aci/plugins/modules/aci_bgp_route_summarization_policy.py ansible_collections/cisco/aci/plugins/modules/aci_bgp_rr_asn.py ansible_collections/cisco/aci/plugins/modules/aci_bgp_rr_node.py ansible_collections/cisco/aci/plugins/modules/aci_bgp_timers_policy.py @@ -23359,6 +23595,8 @@ ansible_collections/cisco/aci/plugins/modules/aci_contract_export.py ansible_collections/cisco/aci/plugins/modules/aci_contract_subject.py ansible_collections/cisco/aci/plugins/modules/aci_contract_subject_to_filter.py ansible_collections/cisco/aci/plugins/modules/aci_contract_subject_to_service_graph.py +ansible_collections/cisco/aci/plugins/modules/aci_dhcp_option.py +ansible_collections/cisco/aci/plugins/modules/aci_dhcp_option_policy.py ansible_collections/cisco/aci/plugins/modules/aci_dhcp_relay.py ansible_collections/cisco/aci/plugins/modules/aci_dhcp_relay_provider.py ansible_collections/cisco/aci/plugins/modules/aci_dns_domain.py @@ -23376,17 +23614,28 @@ ansible_collections/cisco/aci/plugins/modules/aci_epg_to_contract.py ansible_collections/cisco/aci/plugins/modules/aci_epg_to_contract_interface.py ansible_collections/cisco/aci/plugins/modules/aci_epg_to_contract_master.py ansible_collections/cisco/aci/plugins/modules/aci_epg_to_domain.py +ansible_collections/cisco/aci/plugins/modules/aci_epg_useg_attribute_block_statement.py +ansible_collections/cisco/aci/plugins/modules/aci_epg_useg_attribute_simple_statement.py ansible_collections/cisco/aci/plugins/modules/aci_esg.py ansible_collections/cisco/aci/plugins/modules/aci_esg_contract_master.py ansible_collections/cisco/aci/plugins/modules/aci_esg_epg_selector.py ansible_collections/cisco/aci/plugins/modules/aci_esg_ip_subnet_selector.py ansible_collections/cisco/aci/plugins/modules/aci_esg_tag_selector.py +ansible_collections/cisco/aci/plugins/modules/aci_fabric_external_connection_profile.py +ansible_collections/cisco/aci/plugins/modules/aci_fabric_external_routing_profile.py ansible_collections/cisco/aci/plugins/modules/aci_fabric_interface_policy_group.py ansible_collections/cisco/aci/plugins/modules/aci_fabric_leaf_profile.py ansible_collections/cisco/aci/plugins/modules/aci_fabric_leaf_switch_assoc.py +ansible_collections/cisco/aci/plugins/modules/aci_fabric_management_access.py +ansible_collections/cisco/aci/plugins/modules/aci_fabric_management_access_https_cipher.py ansible_collections/cisco/aci/plugins/modules/aci_fabric_node.py ansible_collections/cisco/aci/plugins/modules/aci_fabric_node_control.py +ansible_collections/cisco/aci/plugins/modules/aci_fabric_pod.py +ansible_collections/cisco/aci/plugins/modules/aci_fabric_pod_connectivity_profile.py +ansible_collections/cisco/aci/plugins/modules/aci_fabric_pod_external_tep.py ansible_collections/cisco/aci/plugins/modules/aci_fabric_pod_policy_group.py +ansible_collections/cisco/aci/plugins/modules/aci_fabric_pod_profile.py +ansible_collections/cisco/aci/plugins/modules/aci_fabric_pod_remote_pool.py ansible_collections/cisco/aci/plugins/modules/aci_fabric_pod_selector.py ansible_collections/cisco/aci/plugins/modules/aci_fabric_scheduler.py ansible_collections/cisco/aci/plugins/modules/aci_fabric_span_dst_group.py @@ -23410,8 +23659,12 @@ ansible_collections/cisco/aci/plugins/modules/aci_igmp_interface_policy.py ansible_collections/cisco/aci/plugins/modules/aci_interface_blacklist.py ansible_collections/cisco/aci/plugins/modules/aci_interface_config.py ansible_collections/cisco/aci/plugins/modules/aci_interface_description.py +ansible_collections/cisco/aci/plugins/modules/aci_interface_policy_bfd.py +ansible_collections/cisco/aci/plugins/modules/aci_interface_policy_bfd_multihop.py ansible_collections/cisco/aci/plugins/modules/aci_interface_policy_cdp.py +ansible_collections/cisco/aci/plugins/modules/aci_interface_policy_eigrp.py ansible_collections/cisco/aci/plugins/modules/aci_interface_policy_fc.py +ansible_collections/cisco/aci/plugins/modules/aci_interface_policy_hsrp.py ansible_collections/cisco/aci/plugins/modules/aci_interface_policy_l2.py ansible_collections/cisco/aci/plugins/modules/aci_interface_policy_leaf_breakout_port_group.py ansible_collections/cisco/aci/plugins/modules/aci_interface_policy_leaf_fc_policy_group.py @@ -23422,11 +23675,15 @@ ansible_collections/cisco/aci/plugins/modules/aci_interface_policy_link_level.py ansible_collections/cisco/aci/plugins/modules/aci_interface_policy_lldp.py ansible_collections/cisco/aci/plugins/modules/aci_interface_policy_mcp.py ansible_collections/cisco/aci/plugins/modules/aci_interface_policy_ospf.py +ansible_collections/cisco/aci/plugins/modules/aci_interface_policy_pim.py ansible_collections/cisco/aci/plugins/modules/aci_interface_policy_port_channel.py ansible_collections/cisco/aci/plugins/modules/aci_interface_policy_port_security.py ansible_collections/cisco/aci/plugins/modules/aci_interface_policy_spanning_tree.py ansible_collections/cisco/aci/plugins/modules/aci_interface_policy_spine_policy_group.py +ansible_collections/cisco/aci/plugins/modules/aci_interface_policy_storm_control.py ansible_collections/cisco/aci/plugins/modules/aci_interface_selector_to_switch_policy_leaf_profile.py +ansible_collections/cisco/aci/plugins/modules/aci_key_policy.py +ansible_collections/cisco/aci/plugins/modules/aci_keychain_policy.py ansible_collections/cisco/aci/plugins/modules/aci_l2out.py ansible_collections/cisco/aci/plugins/modules/aci_l2out_extepg.py ansible_collections/cisco/aci/plugins/modules/aci_l2out_extepg_to_contract.py @@ -23434,11 +23691,22 @@ ansible_collections/cisco/aci/plugins/modules/aci_l2out_logical_interface_path.p ansible_collections/cisco/aci/plugins/modules/aci_l2out_logical_interface_profile.py ansible_collections/cisco/aci/plugins/modules/aci_l2out_logical_node_profile.py ansible_collections/cisco/aci/plugins/modules/aci_l3out.py +ansible_collections/cisco/aci/plugins/modules/aci_l3out_bfd_interface_profile.py +ansible_collections/cisco/aci/plugins/modules/aci_l3out_bfd_multihop_interface_profile.py ansible_collections/cisco/aci/plugins/modules/aci_l3out_bgp_peer.py ansible_collections/cisco/aci/plugins/modules/aci_l3out_bgp_protocol_profile.py +ansible_collections/cisco/aci/plugins/modules/aci_l3out_dhcp_relay_label.py +ansible_collections/cisco/aci/plugins/modules/aci_l3out_eigrp_interface_profile.py ansible_collections/cisco/aci/plugins/modules/aci_l3out_extepg.py ansible_collections/cisco/aci/plugins/modules/aci_l3out_extepg_to_contract.py ansible_collections/cisco/aci/plugins/modules/aci_l3out_extsubnet.py +ansible_collections/cisco/aci/plugins/modules/aci_l3out_floating_svi.py +ansible_collections/cisco/aci/plugins/modules/aci_l3out_floating_svi_path.py +ansible_collections/cisco/aci/plugins/modules/aci_l3out_floating_svi_path_secondary_ip.py +ansible_collections/cisco/aci/plugins/modules/aci_l3out_floating_svi_secondary_ip.py +ansible_collections/cisco/aci/plugins/modules/aci_l3out_hsrp_group.py +ansible_collections/cisco/aci/plugins/modules/aci_l3out_hsrp_interface_profile.py +ansible_collections/cisco/aci/plugins/modules/aci_l3out_hsrp_secondary_vip.py ansible_collections/cisco/aci/plugins/modules/aci_l3out_interface.py ansible_collections/cisco/aci/plugins/modules/aci_l3out_interface_secondary_ip.py ansible_collections/cisco/aci/plugins/modules/aci_l3out_logical_interface_profile.py @@ -23449,6 +23717,7 @@ ansible_collections/cisco/aci/plugins/modules/aci_l3out_logical_node_profile.py ansible_collections/cisco/aci/plugins/modules/aci_l3out_route_tag_policy.py ansible_collections/cisco/aci/plugins/modules/aci_l3out_static_routes.py ansible_collections/cisco/aci/plugins/modules/aci_l3out_static_routes_nexthop.py +ansible_collections/cisco/aci/plugins/modules/aci_l3out_to_sr_mpls_infra_l3out.py ansible_collections/cisco/aci/plugins/modules/aci_maintenance_group.py ansible_collections/cisco/aci/plugins/modules/aci_maintenance_group_node.py ansible_collections/cisco/aci/plugins/modules/aci_maintenance_policy.py @@ -23458,9 +23727,19 @@ ansible_collections/cisco/aci/plugins/modules/aci_match_community_regex_term.py ansible_collections/cisco/aci/plugins/modules/aci_match_community_term.py ansible_collections/cisco/aci/plugins/modules/aci_match_route_destination.py ansible_collections/cisco/aci/plugins/modules/aci_match_rule.py +ansible_collections/cisco/aci/plugins/modules/aci_netflow_exporter_policy.py +ansible_collections/cisco/aci/plugins/modules/aci_netflow_monitor_policy.py +ansible_collections/cisco/aci/plugins/modules/aci_netflow_monitor_to_exporter.py +ansible_collections/cisco/aci/plugins/modules/aci_netflow_record_policy.py +ansible_collections/cisco/aci/plugins/modules/aci_node_block.py ansible_collections/cisco/aci/plugins/modules/aci_node_mgmt_epg.py ansible_collections/cisco/aci/plugins/modules/aci_ntp_policy.py ansible_collections/cisco/aci/plugins/modules/aci_ntp_server.py +ansible_collections/cisco/aci/plugins/modules/aci_pim_route_map_entry.py +ansible_collections/cisco/aci/plugins/modules/aci_pim_route_map_policy.py +ansible_collections/cisco/aci/plugins/modules/aci_qos_custom_policy.py +ansible_collections/cisco/aci/plugins/modules/aci_qos_dot1p_class.py +ansible_collections/cisco/aci/plugins/modules/aci_qos_dscp_class.py ansible_collections/cisco/aci/plugins/modules/aci_rest.py ansible_collections/cisco/aci/plugins/modules/aci_route_control_context.py ansible_collections/cisco/aci/plugins/modules/aci_route_control_profile.py @@ -23471,6 +23750,7 @@ ansible_collections/cisco/aci/plugins/modules/aci_snmp_policy.py ansible_collections/cisco/aci/plugins/modules/aci_snmp_user.py ansible_collections/cisco/aci/plugins/modules/aci_static_binding_to_epg.py ansible_collections/cisco/aci/plugins/modules/aci_static_node_mgmt_address.py +ansible_collections/cisco/aci/plugins/modules/aci_subject_label.py ansible_collections/cisco/aci/plugins/modules/aci_switch_leaf_selector.py ansible_collections/cisco/aci/plugins/modules/aci_switch_policy_leaf_profile.py ansible_collections/cisco/aci/plugins/modules/aci_switch_policy_vpc_protection_group.py @@ -23499,17 +23779,27 @@ ansible_collections/cisco/aci/plugins/modules/aci_vmm_uplink_container.py ansible_collections/cisco/aci/plugins/modules/aci_vmm_vswitch_policy.py ansible_collections/cisco/aci/plugins/modules/aci_vrf.py ansible_collections/cisco/aci/plugins/modules/aci_vrf_leak_internal_subnet.py +ansible_collections/cisco/aci/plugins/modules/aci_vrf_multicast.py ansible_collections/cisco/aci/plugins/modules/aci_vzany_to_contract.py ansible_collections/cisco/aci/tests/.gitignore ansible_collections/cisco/aci/tests/integration/inventory.networking ansible_collections/cisco/aci/tests/integration/network-integration.requirements.txt ansible_collections/cisco/aci/tests/integration/target-prefixes.network +ansible_collections/cisco/aci/tests/integration/targets/aci_aaa_certificate_authority/aliases +ansible_collections/cisco/aci/tests/integration/targets/aci_aaa_certificate_authority/pki/admin.crt +ansible_collections/cisco/aci/tests/integration/targets/aci_aaa_certificate_authority/tasks/main.yml ansible_collections/cisco/aci/tests/integration/targets/aci_aaa_custom_privilege/aliases ansible_collections/cisco/aci/tests/integration/targets/aci_aaa_custom_privilege/tasks/main.yml ansible_collections/cisco/aci/tests/integration/targets/aci_aaa_domain/aliases ansible_collections/cisco/aci/tests/integration/targets/aci_aaa_domain/tasks/main.yml +ansible_collections/cisco/aci/tests/integration/targets/aci_aaa_key_ring/aliases +ansible_collections/cisco/aci/tests/integration/targets/aci_aaa_key_ring/pki/admin.crt +ansible_collections/cisco/aci/tests/integration/targets/aci_aaa_key_ring/pki/admin.key +ansible_collections/cisco/aci/tests/integration/targets/aci_aaa_key_ring/tasks/main.yml ansible_collections/cisco/aci/tests/integration/targets/aci_aaa_role/aliases ansible_collections/cisco/aci/tests/integration/targets/aci_aaa_role/tasks/main.yml +ansible_collections/cisco/aci/tests/integration/targets/aci_aaa_security_default_settings/aliases +ansible_collections/cisco/aci/tests/integration/targets/aci_aaa_security_default_settings/tasks/main.yml ansible_collections/cisco/aci/tests/integration/targets/aci_aaa_ssh_auth/aliases ansible_collections/cisco/aci/tests/integration/targets/aci_aaa_ssh_auth/pki/sshkey.pub ansible_collections/cisco/aci/tests/integration/targets/aci_aaa_ssh_auth/tasks/main.yml @@ -23544,8 +23834,26 @@ ansible_collections/cisco/aci/tests/integration/targets/aci_access_span_src_grou ansible_collections/cisco/aci/tests/integration/targets/aci_access_span_src_group_src/tasks/main.yml ansible_collections/cisco/aci/tests/integration/targets/aci_access_span_src_group_src_path/aliases ansible_collections/cisco/aci/tests/integration/targets/aci_access_span_src_group_src_path/tasks/main.yml +ansible_collections/cisco/aci/tests/integration/targets/aci_access_spine_interface_profile/aliases +ansible_collections/cisco/aci/tests/integration/targets/aci_access_spine_interface_profile/tasks/main.yml +ansible_collections/cisco/aci/tests/integration/targets/aci_access_spine_interface_profile_to_spine_switch_profile/aliases +ansible_collections/cisco/aci/tests/integration/targets/aci_access_spine_interface_profile_to_spine_switch_profile/tasks/main.yml +ansible_collections/cisco/aci/tests/integration/targets/aci_access_spine_interface_selector/aliases +ansible_collections/cisco/aci/tests/integration/targets/aci_access_spine_interface_selector/tasks/main.yml +ansible_collections/cisco/aci/tests/integration/targets/aci_access_spine_switch_profile/aliases +ansible_collections/cisco/aci/tests/integration/targets/aci_access_spine_switch_profile/tasks/main.yml +ansible_collections/cisco/aci/tests/integration/targets/aci_access_spine_switch_selector/aliases +ansible_collections/cisco/aci/tests/integration/targets/aci_access_spine_switch_selector/tasks/main.yml ansible_collections/cisco/aci/tests/integration/targets/aci_access_sub_port_block_to_access_port/aliases ansible_collections/cisco/aci/tests/integration/targets/aci_access_sub_port_block_to_access_port/tasks/main.yml +ansible_collections/cisco/aci/tests/integration/targets/aci_access_switch_policy_group/aliases +ansible_collections/cisco/aci/tests/integration/targets/aci_access_switch_policy_group/tasks/main.yml +ansible_collections/cisco/aci/tests/integration/targets/aci_action_rule_additional_communities/aliases +ansible_collections/cisco/aci/tests/integration/targets/aci_action_rule_additional_communities/tasks/main.yml +ansible_collections/cisco/aci/tests/integration/targets/aci_action_rule_set_as_path/aliases +ansible_collections/cisco/aci/tests/integration/targets/aci_action_rule_set_as_path/tasks/main.yml +ansible_collections/cisco/aci/tests/integration/targets/aci_action_rule_set_as_path_asn/aliases +ansible_collections/cisco/aci/tests/integration/targets/aci_action_rule_set_as_path_asn/tasks/main.yml ansible_collections/cisco/aci/tests/integration/targets/aci_aep/aliases ansible_collections/cisco/aci/tests/integration/targets/aci_aep/tasks/main.yml ansible_collections/cisco/aci/tests/integration/targets/aci_aep_to_domain/aliases @@ -23558,12 +23866,24 @@ ansible_collections/cisco/aci/tests/integration/targets/aci_bd/aliases ansible_collections/cisco/aci/tests/integration/targets/aci_bd/tasks/main.yml ansible_collections/cisco/aci/tests/integration/targets/aci_bd_dhcp_label/aliases ansible_collections/cisco/aci/tests/integration/targets/aci_bd_dhcp_label/tasks/main.yml +ansible_collections/cisco/aci/tests/integration/targets/aci_bd_rogue_exception_mac/aliases +ansible_collections/cisco/aci/tests/integration/targets/aci_bd_rogue_exception_mac/tasks/main.yml ansible_collections/cisco/aci/tests/integration/targets/aci_bd_subnet/aliases ansible_collections/cisco/aci/tests/integration/targets/aci_bd_subnet/tasks/main.yml ansible_collections/cisco/aci/tests/integration/targets/aci_bd_to_l3out/aliases ansible_collections/cisco/aci/tests/integration/targets/aci_bd_to_l3out/tasks/main.yml +ansible_collections/cisco/aci/tests/integration/targets/aci_bd_to_netflow_monitor_policy/aliases +ansible_collections/cisco/aci/tests/integration/targets/aci_bd_to_netflow_monitor_policy/tasks/main.yml +ansible_collections/cisco/aci/tests/integration/targets/aci_bfd_multihop_node_policy/aliases +ansible_collections/cisco/aci/tests/integration/targets/aci_bfd_multihop_node_policy/tasks/main.yml +ansible_collections/cisco/aci/tests/integration/targets/aci_bgp_address_family_context_policy/aliases +ansible_collections/cisco/aci/tests/integration/targets/aci_bgp_address_family_context_policy/tasks/main.yml ansible_collections/cisco/aci/tests/integration/targets/aci_bgp_best_path_policy/aliases ansible_collections/cisco/aci/tests/integration/targets/aci_bgp_best_path_policy/tasks/main.yml +ansible_collections/cisco/aci/tests/integration/targets/aci_bgp_peer_prefix_policy/aliases +ansible_collections/cisco/aci/tests/integration/targets/aci_bgp_peer_prefix_policy/tasks/main.yml +ansible_collections/cisco/aci/tests/integration/targets/aci_bgp_route_summarization_policy/aliases +ansible_collections/cisco/aci/tests/integration/targets/aci_bgp_route_summarization_policy/tasks/main.yml ansible_collections/cisco/aci/tests/integration/targets/aci_bgp_rr_asn/aliases ansible_collections/cisco/aci/tests/integration/targets/aci_bgp_rr_asn/tasks/main.yml ansible_collections/cisco/aci/tests/integration/targets/aci_bgp_rr_node/aliases @@ -23617,6 +23937,10 @@ ansible_collections/cisco/aci/tests/integration/targets/aci_contract_subject_to_ ansible_collections/cisco/aci/tests/integration/targets/aci_contract_subject_to_filter/tasks/main.yml ansible_collections/cisco/aci/tests/integration/targets/aci_contract_subject_to_service_graph/aliases ansible_collections/cisco/aci/tests/integration/targets/aci_contract_subject_to_service_graph/tasks/main.yml +ansible_collections/cisco/aci/tests/integration/targets/aci_dhcp_option/aliases +ansible_collections/cisco/aci/tests/integration/targets/aci_dhcp_option/tasks/main.yml +ansible_collections/cisco/aci/tests/integration/targets/aci_dhcp_option_policy/aliases +ansible_collections/cisco/aci/tests/integration/targets/aci_dhcp_option_policy/tasks/main.yml ansible_collections/cisco/aci/tests/integration/targets/aci_dhcp_relay/aliases ansible_collections/cisco/aci/tests/integration/targets/aci_dhcp_relay/tasks/main.yml ansible_collections/cisco/aci/tests/integration/targets/aci_dhcp_relay_provider/aliases @@ -23662,6 +23986,11 @@ ansible_collections/cisco/aci/tests/integration/targets/aci_epg_to_contract_mast ansible_collections/cisco/aci/tests/integration/targets/aci_epg_to_contract_master/tasks/main.yml ansible_collections/cisco/aci/tests/integration/targets/aci_epg_to_domain/aliases ansible_collections/cisco/aci/tests/integration/targets/aci_epg_to_domain/tasks/main.yml +ansible_collections/cisco/aci/tests/integration/targets/aci_epg_useg_attribute_block_statement/aliases +ansible_collections/cisco/aci/tests/integration/targets/aci_epg_useg_attribute_block_statement/tasks/main.yml +ansible_collections/cisco/aci/tests/integration/targets/aci_epg_useg_attribute_simple_statement/aliases +ansible_collections/cisco/aci/tests/integration/targets/aci_epg_useg_attribute_simple_statement/tasks/main.yml +ansible_collections/cisco/aci/tests/integration/targets/aci_epg_useg_attribute_simple_statement/tasks/simple_block_levels.yml ansible_collections/cisco/aci/tests/integration/targets/aci_esg/aliases ansible_collections/cisco/aci/tests/integration/targets/aci_esg/tasks/main.yml ansible_collections/cisco/aci/tests/integration/targets/aci_esg_contract_master/aliases @@ -23672,18 +24001,40 @@ ansible_collections/cisco/aci/tests/integration/targets/aci_esg_ip_subnet_select ansible_collections/cisco/aci/tests/integration/targets/aci_esg_ip_subnet_selector/tasks/main.yml ansible_collections/cisco/aci/tests/integration/targets/aci_esg_tag_selector/aliases ansible_collections/cisco/aci/tests/integration/targets/aci_esg_tag_selector/tasks/main.yml +ansible_collections/cisco/aci/tests/integration/targets/aci_fabric_external_connection_profile/aliases +ansible_collections/cisco/aci/tests/integration/targets/aci_fabric_external_connection_profile/tasks/main.yml +ansible_collections/cisco/aci/tests/integration/targets/aci_fabric_external_routing_profile/aliases +ansible_collections/cisco/aci/tests/integration/targets/aci_fabric_external_routing_profile/tasks/main.yml ansible_collections/cisco/aci/tests/integration/targets/aci_fabric_interface_policy_group/aliases ansible_collections/cisco/aci/tests/integration/targets/aci_fabric_interface_policy_group/tasks/main.yml ansible_collections/cisco/aci/tests/integration/targets/aci_fabric_leaf_profile/aliases ansible_collections/cisco/aci/tests/integration/targets/aci_fabric_leaf_profile/tasks/main.yml ansible_collections/cisco/aci/tests/integration/targets/aci_fabric_leaf_switch_assoc/aliases ansible_collections/cisco/aci/tests/integration/targets/aci_fabric_leaf_switch_assoc/tasks/main.yml +ansible_collections/cisco/aci/tests/integration/targets/aci_fabric_management_access/aliases +ansible_collections/cisco/aci/tests/integration/targets/aci_fabric_management_access/pki/admin.crt +ansible_collections/cisco/aci/tests/integration/targets/aci_fabric_management_access/pki/admin.key +ansible_collections/cisco/aci/tests/integration/targets/aci_fabric_management_access/tasks/main.yml +ansible_collections/cisco/aci/tests/integration/targets/aci_fabric_management_access_https_cipher/aliases +ansible_collections/cisco/aci/tests/integration/targets/aci_fabric_management_access_https_cipher/pki/admin.crt +ansible_collections/cisco/aci/tests/integration/targets/aci_fabric_management_access_https_cipher/pki/admin.key +ansible_collections/cisco/aci/tests/integration/targets/aci_fabric_management_access_https_cipher/tasks/main.yml ansible_collections/cisco/aci/tests/integration/targets/aci_fabric_node/aliases ansible_collections/cisco/aci/tests/integration/targets/aci_fabric_node/tasks/main.yml ansible_collections/cisco/aci/tests/integration/targets/aci_fabric_node_control/aliases ansible_collections/cisco/aci/tests/integration/targets/aci_fabric_node_control/tasks/main.yml +ansible_collections/cisco/aci/tests/integration/targets/aci_fabric_pod/aliases +ansible_collections/cisco/aci/tests/integration/targets/aci_fabric_pod/tasks/main.yml +ansible_collections/cisco/aci/tests/integration/targets/aci_fabric_pod_connectivity_profile/aliases +ansible_collections/cisco/aci/tests/integration/targets/aci_fabric_pod_connectivity_profile/tasks/main.yml +ansible_collections/cisco/aci/tests/integration/targets/aci_fabric_pod_external_tep/aliases +ansible_collections/cisco/aci/tests/integration/targets/aci_fabric_pod_external_tep/tasks/main.yml ansible_collections/cisco/aci/tests/integration/targets/aci_fabric_pod_policy_group/aliases ansible_collections/cisco/aci/tests/integration/targets/aci_fabric_pod_policy_group/tasks/main.yml +ansible_collections/cisco/aci/tests/integration/targets/aci_fabric_pod_profile/aliases +ansible_collections/cisco/aci/tests/integration/targets/aci_fabric_pod_profile/tasks/main.yml +ansible_collections/cisco/aci/tests/integration/targets/aci_fabric_pod_remote_pool/aliases +ansible_collections/cisco/aci/tests/integration/targets/aci_fabric_pod_remote_pool/tasks/main.yml ansible_collections/cisco/aci/tests/integration/targets/aci_fabric_pod_selector/aliases ansible_collections/cisco/aci/tests/integration/targets/aci_fabric_pod_selector/tasks/main.yml ansible_collections/cisco/aci/tests/integration/targets/aci_fabric_scheduler/aliases @@ -23715,6 +24066,8 @@ ansible_collections/cisco/aci/tests/integration/targets/aci_filter/aliases ansible_collections/cisco/aci/tests/integration/targets/aci_filter/tasks/main.yml ansible_collections/cisco/aci/tests/integration/targets/aci_filter_entry/aliases ansible_collections/cisco/aci/tests/integration/targets/aci_filter_entry/tasks/main.yml +ansible_collections/cisco/aci/tests/integration/targets/aci_filter_listify/aliases +ansible_collections/cisco/aci/tests/integration/targets/aci_filter_listify/tasks/main.yml ansible_collections/cisco/aci/tests/integration/targets/aci_firmware_group/aliases ansible_collections/cisco/aci/tests/integration/targets/aci_firmware_group/tasks/main.yml ansible_collections/cisco/aci/tests/integration/targets/aci_firmware_group_node/aliases @@ -23731,10 +24084,18 @@ ansible_collections/cisco/aci/tests/integration/targets/aci_interface_config/ali ansible_collections/cisco/aci/tests/integration/targets/aci_interface_config/tasks/main.yml ansible_collections/cisco/aci/tests/integration/targets/aci_interface_description/aliases ansible_collections/cisco/aci/tests/integration/targets/aci_interface_description/tasks/main.yml +ansible_collections/cisco/aci/tests/integration/targets/aci_interface_policy_bfd/aliases +ansible_collections/cisco/aci/tests/integration/targets/aci_interface_policy_bfd/tasks/main.yml +ansible_collections/cisco/aci/tests/integration/targets/aci_interface_policy_bfd_multihop/aliases +ansible_collections/cisco/aci/tests/integration/targets/aci_interface_policy_bfd_multihop/tasks/main.yml ansible_collections/cisco/aci/tests/integration/targets/aci_interface_policy_cdp/aliases ansible_collections/cisco/aci/tests/integration/targets/aci_interface_policy_cdp/tasks/main.yml +ansible_collections/cisco/aci/tests/integration/targets/aci_interface_policy_eigrp/aliases +ansible_collections/cisco/aci/tests/integration/targets/aci_interface_policy_eigrp/tasks/main.yml ansible_collections/cisco/aci/tests/integration/targets/aci_interface_policy_fc/aliases ansible_collections/cisco/aci/tests/integration/targets/aci_interface_policy_fc/tasks/main.yml +ansible_collections/cisco/aci/tests/integration/targets/aci_interface_policy_hsrp/aliases +ansible_collections/cisco/aci/tests/integration/targets/aci_interface_policy_hsrp/tasks/main.yml ansible_collections/cisco/aci/tests/integration/targets/aci_interface_policy_l2/aliases ansible_collections/cisco/aci/tests/integration/targets/aci_interface_policy_l2/tasks/main.yml ansible_collections/cisco/aci/tests/integration/targets/aci_interface_policy_leaf_breakout_port_group/aliases @@ -23755,6 +24116,8 @@ ansible_collections/cisco/aci/tests/integration/targets/aci_interface_policy_mcp ansible_collections/cisco/aci/tests/integration/targets/aci_interface_policy_mcp/tasks/main.yml ansible_collections/cisco/aci/tests/integration/targets/aci_interface_policy_ospf/aliases ansible_collections/cisco/aci/tests/integration/targets/aci_interface_policy_ospf/tasks/main.yml +ansible_collections/cisco/aci/tests/integration/targets/aci_interface_policy_pim/aliases +ansible_collections/cisco/aci/tests/integration/targets/aci_interface_policy_pim/tasks/main.yml ansible_collections/cisco/aci/tests/integration/targets/aci_interface_policy_port_channel/aliases ansible_collections/cisco/aci/tests/integration/targets/aci_interface_policy_port_channel/tasks/main.yml ansible_collections/cisco/aci/tests/integration/targets/aci_interface_policy_port_security/aliases @@ -23763,8 +24126,14 @@ ansible_collections/cisco/aci/tests/integration/targets/aci_interface_policy_spa ansible_collections/cisco/aci/tests/integration/targets/aci_interface_policy_spanning_tree/tasks/main.yml ansible_collections/cisco/aci/tests/integration/targets/aci_interface_policy_spine_policy_group/aliases ansible_collections/cisco/aci/tests/integration/targets/aci_interface_policy_spine_policy_group/tasks/main.yml +ansible_collections/cisco/aci/tests/integration/targets/aci_interface_policy_storm_control/aliases +ansible_collections/cisco/aci/tests/integration/targets/aci_interface_policy_storm_control/tasks/main.yml ansible_collections/cisco/aci/tests/integration/targets/aci_interface_selector_to_switch_policy_leaf_profile/aliases ansible_collections/cisco/aci/tests/integration/targets/aci_interface_selector_to_switch_policy_leaf_profile/tasks/main.yml +ansible_collections/cisco/aci/tests/integration/targets/aci_key_policy/aliases +ansible_collections/cisco/aci/tests/integration/targets/aci_key_policy/tasks/main.yml +ansible_collections/cisco/aci/tests/integration/targets/aci_keychain_policy/aliases +ansible_collections/cisco/aci/tests/integration/targets/aci_keychain_policy/tasks/main.yml ansible_collections/cisco/aci/tests/integration/targets/aci_l2out/aliases ansible_collections/cisco/aci/tests/integration/targets/aci_l2out/tasks/main.yml ansible_collections/cisco/aci/tests/integration/targets/aci_l2out_extepg/aliases @@ -23779,16 +24148,38 @@ ansible_collections/cisco/aci/tests/integration/targets/aci_l2out_logical_node_p ansible_collections/cisco/aci/tests/integration/targets/aci_l2out_logical_node_profile/tasks/main.yml ansible_collections/cisco/aci/tests/integration/targets/aci_l3out/aliases ansible_collections/cisco/aci/tests/integration/targets/aci_l3out/tasks/main.yml +ansible_collections/cisco/aci/tests/integration/targets/aci_l3out_bfd_interface_profile/aliases +ansible_collections/cisco/aci/tests/integration/targets/aci_l3out_bfd_interface_profile/tasks/main.yml +ansible_collections/cisco/aci/tests/integration/targets/aci_l3out_bfd_multihop_interface_profile/aliases +ansible_collections/cisco/aci/tests/integration/targets/aci_l3out_bfd_multihop_interface_profile/tasks/main.yml ansible_collections/cisco/aci/tests/integration/targets/aci_l3out_bgp_peer/aliases ansible_collections/cisco/aci/tests/integration/targets/aci_l3out_bgp_peer/tasks/main.yml ansible_collections/cisco/aci/tests/integration/targets/aci_l3out_bgp_protocol_profile/aliases ansible_collections/cisco/aci/tests/integration/targets/aci_l3out_bgp_protocol_profile/tasks/main.yml +ansible_collections/cisco/aci/tests/integration/targets/aci_l3out_dhcp_relay_label/aliases +ansible_collections/cisco/aci/tests/integration/targets/aci_l3out_dhcp_relay_label/tasks/main.yml +ansible_collections/cisco/aci/tests/integration/targets/aci_l3out_eigrp_interface_profile/aliases +ansible_collections/cisco/aci/tests/integration/targets/aci_l3out_eigrp_interface_profile/tasks/main.yml ansible_collections/cisco/aci/tests/integration/targets/aci_l3out_extepg/aliases ansible_collections/cisco/aci/tests/integration/targets/aci_l3out_extepg/tasks/main.yml ansible_collections/cisco/aci/tests/integration/targets/aci_l3out_extepg_to_contract/aliases ansible_collections/cisco/aci/tests/integration/targets/aci_l3out_extepg_to_contract/tasks/main.yml ansible_collections/cisco/aci/tests/integration/targets/aci_l3out_extsubnet/aliases ansible_collections/cisco/aci/tests/integration/targets/aci_l3out_extsubnet/tasks/main.yml +ansible_collections/cisco/aci/tests/integration/targets/aci_l3out_floating_svi/aliases +ansible_collections/cisco/aci/tests/integration/targets/aci_l3out_floating_svi/tasks/main.yml +ansible_collections/cisco/aci/tests/integration/targets/aci_l3out_floating_svi_path/aliases +ansible_collections/cisco/aci/tests/integration/targets/aci_l3out_floating_svi_path/tasks/main.yml +ansible_collections/cisco/aci/tests/integration/targets/aci_l3out_floating_svi_path_secondary_ip/aliases +ansible_collections/cisco/aci/tests/integration/targets/aci_l3out_floating_svi_path_secondary_ip/tasks/main.yml +ansible_collections/cisco/aci/tests/integration/targets/aci_l3out_floating_svi_secondary_ip/aliases +ansible_collections/cisco/aci/tests/integration/targets/aci_l3out_floating_svi_secondary_ip/tasks/main.yml +ansible_collections/cisco/aci/tests/integration/targets/aci_l3out_hsrp_group/aliases +ansible_collections/cisco/aci/tests/integration/targets/aci_l3out_hsrp_group/tasks/main.yml +ansible_collections/cisco/aci/tests/integration/targets/aci_l3out_hsrp_interface_profile/aliases +ansible_collections/cisco/aci/tests/integration/targets/aci_l3out_hsrp_interface_profile/tasks/main.yml +ansible_collections/cisco/aci/tests/integration/targets/aci_l3out_hsrp_secondary_vip/aliases +ansible_collections/cisco/aci/tests/integration/targets/aci_l3out_hsrp_secondary_vip/tasks/main.yml ansible_collections/cisco/aci/tests/integration/targets/aci_l3out_interface/aliases ansible_collections/cisco/aci/tests/integration/targets/aci_l3out_interface/tasks/main.yml ansible_collections/cisco/aci/tests/integration/targets/aci_l3out_interface_secondary_ip/aliases @@ -23809,6 +24200,8 @@ ansible_collections/cisco/aci/tests/integration/targets/aci_l3out_static_routes/ ansible_collections/cisco/aci/tests/integration/targets/aci_l3out_static_routes/tasks/main.yml ansible_collections/cisco/aci/tests/integration/targets/aci_l3out_static_routes_nexthop/aliases ansible_collections/cisco/aci/tests/integration/targets/aci_l3out_static_routes_nexthop/tasks/main.yml +ansible_collections/cisco/aci/tests/integration/targets/aci_l3out_to_sr_mpls_infra_l3out/aliases +ansible_collections/cisco/aci/tests/integration/targets/aci_l3out_to_sr_mpls_infra_l3out/tasks/main.yml ansible_collections/cisco/aci/tests/integration/targets/aci_lookup_interface_range/aliases ansible_collections/cisco/aci/tests/integration/targets/aci_lookup_interface_range/tasks/main.yml ansible_collections/cisco/aci/tests/integration/targets/aci_maintenance_group/aliases @@ -23829,12 +24222,32 @@ ansible_collections/cisco/aci/tests/integration/targets/aci_match_route_destinat ansible_collections/cisco/aci/tests/integration/targets/aci_match_route_destination/tasks/main.yml ansible_collections/cisco/aci/tests/integration/targets/aci_match_rule/aliases ansible_collections/cisco/aci/tests/integration/targets/aci_match_rule/tasks/main.yml +ansible_collections/cisco/aci/tests/integration/targets/aci_netflow_exporter_policy/aliases +ansible_collections/cisco/aci/tests/integration/targets/aci_netflow_exporter_policy/tasks/main.yml +ansible_collections/cisco/aci/tests/integration/targets/aci_netflow_monitor_policy/aliases +ansible_collections/cisco/aci/tests/integration/targets/aci_netflow_monitor_policy/tasks/main.yml +ansible_collections/cisco/aci/tests/integration/targets/aci_netflow_monitor_to_exporter/aliases +ansible_collections/cisco/aci/tests/integration/targets/aci_netflow_monitor_to_exporter/tasks/main.yml +ansible_collections/cisco/aci/tests/integration/targets/aci_netflow_record_policy/aliases +ansible_collections/cisco/aci/tests/integration/targets/aci_netflow_record_policy/tasks/main.yml +ansible_collections/cisco/aci/tests/integration/targets/aci_node_block/aliases +ansible_collections/cisco/aci/tests/integration/targets/aci_node_block/tasks/main.yml ansible_collections/cisco/aci/tests/integration/targets/aci_node_mgmt_epg/aliases ansible_collections/cisco/aci/tests/integration/targets/aci_node_mgmt_epg/tasks/main.yml ansible_collections/cisco/aci/tests/integration/targets/aci_ntp_policy/aliases ansible_collections/cisco/aci/tests/integration/targets/aci_ntp_policy/tasks/main.yml ansible_collections/cisco/aci/tests/integration/targets/aci_ntp_server/aliases ansible_collections/cisco/aci/tests/integration/targets/aci_ntp_server/tasks/main.yml +ansible_collections/cisco/aci/tests/integration/targets/aci_pim_route_map_entry/aliases +ansible_collections/cisco/aci/tests/integration/targets/aci_pim_route_map_entry/tasks/main.yml +ansible_collections/cisco/aci/tests/integration/targets/aci_pim_route_map_policy/aliases +ansible_collections/cisco/aci/tests/integration/targets/aci_pim_route_map_policy/tasks/main.yml +ansible_collections/cisco/aci/tests/integration/targets/aci_qos_custom_policy/aliases +ansible_collections/cisco/aci/tests/integration/targets/aci_qos_custom_policy/tasks/main.yml +ansible_collections/cisco/aci/tests/integration/targets/aci_qos_dot1p_class/aliases +ansible_collections/cisco/aci/tests/integration/targets/aci_qos_dot1p_class/tasks/main.yml +ansible_collections/cisco/aci/tests/integration/targets/aci_qos_dscp_class/aliases +ansible_collections/cisco/aci/tests/integration/targets/aci_qos_dscp_class/tasks/main.yml ansible_collections/cisco/aci/tests/integration/targets/aci_rest/aliases ansible_collections/cisco/aci/tests/integration/targets/aci_rest/tasks/error_handling.yml ansible_collections/cisco/aci/tests/integration/targets/aci_rest/tasks/json_inline.yml @@ -23848,6 +24261,9 @@ ansible_collections/cisco/aci/tests/integration/targets/aci_rest/tasks/pki/admin ansible_collections/cisco/aci/tests/integration/targets/aci_rest/tasks/pki/admin.key ansible_collections/cisco/aci/tests/integration/targets/aci_rest/tasks/xml_files/fail_parse.json ansible_collections/cisco/aci/tests/integration/targets/aci_rest/tasks/xml_files/fail_parse.xml +ansible_collections/cisco/aci/tests/integration/targets/aci_rest/tasks/xml_files/tag.xml +ansible_collections/cisco/aci/tests/integration/targets/aci_rest/tasks/xml_files/tn-ans_test_annotation.xml +ansible_collections/cisco/aci/tests/integration/targets/aci_rest/tasks/xml_files/tn-ans_test_annotation_children.xml ansible_collections/cisco/aci/tests/integration/targets/aci_rest/tasks/xml_files/tn-ans_test_create.xml ansible_collections/cisco/aci/tests/integration/targets/aci_rest/tasks/xml_files/tn-ans_test_delete.xml ansible_collections/cisco/aci/tests/integration/targets/aci_rest/tasks/xml_files/tn-ans_test_negative_update_check.xml @@ -23870,6 +24286,9 @@ ansible_collections/cisco/aci/tests/integration/targets/aci_static_binding_to_ep ansible_collections/cisco/aci/tests/integration/targets/aci_static_binding_to_epg/tasks/main.yml ansible_collections/cisco/aci/tests/integration/targets/aci_static_node_mgmt_address/aliases ansible_collections/cisco/aci/tests/integration/targets/aci_static_node_mgmt_address/tasks/main.yml +ansible_collections/cisco/aci/tests/integration/targets/aci_subject_label/aliases +ansible_collections/cisco/aci/tests/integration/targets/aci_subject_label/tasks/main.yml +ansible_collections/cisco/aci/tests/integration/targets/aci_subject_label/tasks/subject_label.yml ansible_collections/cisco/aci/tests/integration/targets/aci_switch_leaf_selector/aliases ansible_collections/cisco/aci/tests/integration/targets/aci_switch_leaf_selector/tasks/main.yml ansible_collections/cisco/aci/tests/integration/targets/aci_switch_policy_leaf_profile/aliases @@ -23938,6 +24357,8 @@ ansible_collections/cisco/aci/tests/integration/targets/aci_vrf/aliases ansible_collections/cisco/aci/tests/integration/targets/aci_vrf/tasks/main.yml ansible_collections/cisco/aci/tests/integration/targets/aci_vrf_leak_internal_subnet/aliases ansible_collections/cisco/aci/tests/integration/targets/aci_vrf_leak_internal_subnet/tasks/main.yml +ansible_collections/cisco/aci/tests/integration/targets/aci_vrf_multicast/aliases +ansible_collections/cisco/aci/tests/integration/targets/aci_vrf_multicast/tasks/main.yml ansible_collections/cisco/aci/tests/integration/targets/aci_vzany_to_contract/aliases ansible_collections/cisco/aci/tests/integration/targets/aci_vzany_to_contract/tasks/main.yml ansible_collections/cisco/aci/tests/sanity/requirements.txt @@ -24171,6 +24592,7 @@ ansible_collections/cisco/dnac/.github/ISSUE_TEMPLATE/config.yml ansible_collections/cisco/dnac/.github/ISSUE_TEMPLATE/feature_request.md ansible_collections/cisco/dnac/.github/workflows/docs.yml ansible_collections/cisco/dnac/.github/workflows/sanity_tests.yml +ansible_collections/cisco/dnac/.github/workflows/sanity_tests_devel.yml ansible_collections/cisco/dnac/changelogs/changelog.yaml ansible_collections/cisco/dnac/docs/Makefile ansible_collections/cisco/dnac/docs/conf.py @@ -27152,12 +27574,12 @@ ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/fixtures/clicon ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/fixtures/cliconf/iosxr/show_version__utility_head_-n_20 ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/fixtures/cliconf_ncs540/iosxr/show_running-config_hostname ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/fixtures/cliconf_ncs540/iosxr/show_version__utility_head_-n_20 -ansible_collections/cisco/ise/.DS_Store ansible_collections/cisco/ise/.gitignore ansible_collections/cisco/ise/FILES.json ansible_collections/cisco/ise/LICENSE ansible_collections/cisco/ise/MANIFEST.json ansible_collections/cisco/ise/Makefile +ansible_collections/cisco/ise/Pipfile ansible_collections/cisco/ise/README.md ansible_collections/cisco/ise/requirements.txt ansible_collections/cisco/ise/.github/ISSUE_TEMPLATE/bug_report.md @@ -27165,8 +27587,6 @@ ansible_collections/cisco/ise/.github/ISSUE_TEMPLATE/config.yml ansible_collections/cisco/ise/.github/ISSUE_TEMPLATE/feature_request.md ansible_collections/cisco/ise/.github/workflows/docs.yml ansible_collections/cisco/ise/.github/workflows/sanity_tests.yml -ansible_collections/cisco/ise/.vscode/launch.json -ansible_collections/cisco/ise/.vscode/settings.json ansible_collections/cisco/ise/changelogs/changelog.yaml ansible_collections/cisco/ise/docs/Makefile ansible_collections/cisco/ise/docs/conf.py @@ -27236,7 +27656,6 @@ ansible_collections/cisco/ise/playbooks/trustsec_vn.yml ansible_collections/cisco/ise/playbooks/trustsec_vn_vlan_mapping.yml ansible_collections/cisco/ise/playbooks/group_vars/ise_servers ansible_collections/cisco/ise/playbooks/vars/device_administration_time_date_conditions.yml -ansible_collections/cisco/ise/plugins/.DS_Store ansible_collections/cisco/ise/plugins/action/aci_bindings_info.py ansible_collections/cisco/ise/plugins/action/aci_settings.py ansible_collections/cisco/ise/plugins/action/aci_settings_info.py @@ -28043,7 +28462,6 @@ ansible_collections/cisco/meraki/README.md ansible_collections/cisco/meraki/requirements.txt ansible_collections/cisco/meraki/.github/workflows/docs.yml ansible_collections/cisco/meraki/.github/workflows/sanity_tests.yml -ansible_collections/cisco/meraki/.vscode/settings.json ansible_collections/cisco/meraki/changelogs/changelog.yaml ansible_collections/cisco/meraki/changelogs/config.yaml ansible_collections/cisco/meraki/docs/Makefile @@ -28110,8 +28528,16 @@ ansible_collections/cisco/meraki/playbooks/files/test.template ansible_collections/cisco/meraki/plugins/README.md ansible_collections/cisco/meraki/plugins/__init__.py ansible_collections/cisco/meraki/plugins/action/administered_identities_me_info.py +ansible_collections/cisco/meraki/plugins/action/administered_licensing_subscription_entitlements_info.py +ansible_collections/cisco/meraki/plugins/action/administered_licensing_subscription_subscriptions_bind.py +ansible_collections/cisco/meraki/plugins/action/administered_licensing_subscription_subscriptions_claim.py +ansible_collections/cisco/meraki/plugins/action/administered_licensing_subscription_subscriptions_claim_key_validate.py +ansible_collections/cisco/meraki/plugins/action/administered_licensing_subscription_subscriptions_compliance_statuses_info.py +ansible_collections/cisco/meraki/plugins/action/administered_licensing_subscription_subscriptions_info.py ansible_collections/cisco/meraki/plugins/action/devices.py ansible_collections/cisco/meraki/plugins/action/devices_appliance_performance_info.py +ansible_collections/cisco/meraki/plugins/action/devices_appliance_radio_settings.py +ansible_collections/cisco/meraki/plugins/action/devices_appliance_radio_settings_info.py ansible_collections/cisco/meraki/plugins/action/devices_appliance_uplinks_settings.py ansible_collections/cisco/meraki/plugins/action/devices_appliance_uplinks_settings_info.py ansible_collections/cisco/meraki/plugins/action/devices_appliance_vmx_authentication_token.py @@ -28136,10 +28562,18 @@ ansible_collections/cisco/meraki/plugins/action/devices_cellular_gateway_port_fo ansible_collections/cisco/meraki/plugins/action/devices_cellular_sims.py ansible_collections/cisco/meraki/plugins/action/devices_cellular_sims_info.py ansible_collections/cisco/meraki/plugins/action/devices_info.py +ansible_collections/cisco/meraki/plugins/action/devices_live_tools_arp_table.py +ansible_collections/cisco/meraki/plugins/action/devices_live_tools_arp_table_info.py +ansible_collections/cisco/meraki/plugins/action/devices_live_tools_cable_test.py +ansible_collections/cisco/meraki/plugins/action/devices_live_tools_cable_test_info.py ansible_collections/cisco/meraki/plugins/action/devices_live_tools_ping.py ansible_collections/cisco/meraki/plugins/action/devices_live_tools_ping_device.py ansible_collections/cisco/meraki/plugins/action/devices_live_tools_ping_device_info.py ansible_collections/cisco/meraki/plugins/action/devices_live_tools_ping_info.py +ansible_collections/cisco/meraki/plugins/action/devices_live_tools_throughput_test.py +ansible_collections/cisco/meraki/plugins/action/devices_live_tools_throughput_test_info.py +ansible_collections/cisco/meraki/plugins/action/devices_live_tools_wake_on_lan.py +ansible_collections/cisco/meraki/plugins/action/devices_live_tools_wake_on_lan_info.py ansible_collections/cisco/meraki/plugins/action/devices_lldp_cdp_info.py ansible_collections/cisco/meraki/plugins/action/devices_management_interface.py ansible_collections/cisco/meraki/plugins/action/devices_management_interface_info.py @@ -28157,6 +28591,7 @@ ansible_collections/cisco/meraki/plugins/action/devices_switch_routing_static_ro ansible_collections/cisco/meraki/plugins/action/devices_switch_routing_static_routes_info.py ansible_collections/cisco/meraki/plugins/action/devices_switch_warm_spare.py ansible_collections/cisco/meraki/plugins/action/devices_switch_warm_spare_info.py +ansible_collections/cisco/meraki/plugins/action/devices_wireless_alternate_management_interface_ipv6.py ansible_collections/cisco/meraki/plugins/action/devices_wireless_bluetooth_settings.py ansible_collections/cisco/meraki/plugins/action/devices_wireless_bluetooth_settings_info.py ansible_collections/cisco/meraki/plugins/action/devices_wireless_connection_stats_info.py @@ -28196,6 +28631,8 @@ ansible_collections/cisco/meraki/plugins/action/networks_appliance_ports.py ansible_collections/cisco/meraki/plugins/action/networks_appliance_ports_info.py ansible_collections/cisco/meraki/plugins/action/networks_appliance_prefixes_delegated_statics.py ansible_collections/cisco/meraki/plugins/action/networks_appliance_prefixes_delegated_statics_info.py +ansible_collections/cisco/meraki/plugins/action/networks_appliance_rf_profiles.py +ansible_collections/cisco/meraki/plugins/action/networks_appliance_rf_profiles_info.py ansible_collections/cisco/meraki/plugins/action/networks_appliance_security_intrusion.py ansible_collections/cisco/meraki/plugins/action/networks_appliance_security_intrusion_info.py ansible_collections/cisco/meraki/plugins/action/networks_appliance_security_malware.py @@ -28217,6 +28654,7 @@ ansible_collections/cisco/meraki/plugins/action/networks_appliance_traffic_shapi ansible_collections/cisco/meraki/plugins/action/networks_appliance_traffic_shaping_uplink_bandwidth_info.py ansible_collections/cisco/meraki/plugins/action/networks_appliance_traffic_shaping_uplink_selection.py ansible_collections/cisco/meraki/plugins/action/networks_appliance_traffic_shaping_uplink_selection_info.py +ansible_collections/cisco/meraki/plugins/action/networks_appliance_traffic_shaping_vpn_exclusions.py ansible_collections/cisco/meraki/plugins/action/networks_appliance_vlans.py ansible_collections/cisco/meraki/plugins/action/networks_appliance_vlans_info.py ansible_collections/cisco/meraki/plugins/action/networks_appliance_vlans_settings.py @@ -28304,14 +28742,18 @@ ansible_collections/cisco/meraki/plugins/action/networks_sm_devices_device_comma ansible_collections/cisco/meraki/plugins/action/networks_sm_devices_device_profiles_info.py ansible_collections/cisco/meraki/plugins/action/networks_sm_devices_fields.py ansible_collections/cisco/meraki/plugins/action/networks_sm_devices_info.py +ansible_collections/cisco/meraki/plugins/action/networks_sm_devices_install_apps.py ansible_collections/cisco/meraki/plugins/action/networks_sm_devices_lock.py ansible_collections/cisco/meraki/plugins/action/networks_sm_devices_modify_tags.py ansible_collections/cisco/meraki/plugins/action/networks_sm_devices_move.py ansible_collections/cisco/meraki/plugins/action/networks_sm_devices_network_adapters_info.py ansible_collections/cisco/meraki/plugins/action/networks_sm_devices_performance_history_info.py +ansible_collections/cisco/meraki/plugins/action/networks_sm_devices_reboot.py ansible_collections/cisco/meraki/plugins/action/networks_sm_devices_refresh_details.py ansible_collections/cisco/meraki/plugins/action/networks_sm_devices_security_centers_info.py +ansible_collections/cisco/meraki/plugins/action/networks_sm_devices_shutdown.py ansible_collections/cisco/meraki/plugins/action/networks_sm_devices_unenroll.py +ansible_collections/cisco/meraki/plugins/action/networks_sm_devices_uninstall_apps.py ansible_collections/cisco/meraki/plugins/action/networks_sm_devices_wipe.py ansible_collections/cisco/meraki/plugins/action/networks_sm_devices_wlan_lists_info.py ansible_collections/cisco/meraki/plugins/action/networks_sm_profiles_info.py @@ -28378,6 +28820,10 @@ ansible_collections/cisco/meraki/plugins/action/networks_traffic_analysis_info.p ansible_collections/cisco/meraki/plugins/action/networks_traffic_shaping_application_categories_info.py ansible_collections/cisco/meraki/plugins/action/networks_traffic_shaping_dscp_tagging_options_info.py ansible_collections/cisco/meraki/plugins/action/networks_unbind.py +ansible_collections/cisco/meraki/plugins/action/networks_vlan_profiles.py +ansible_collections/cisco/meraki/plugins/action/networks_vlan_profiles_assignments_by_device_info.py +ansible_collections/cisco/meraki/plugins/action/networks_vlan_profiles_assignments_reassign.py +ansible_collections/cisco/meraki/plugins/action/networks_vlan_profiles_info.py ansible_collections/cisco/meraki/plugins/action/networks_webhooks_http_servers.py ansible_collections/cisco/meraki/plugins/action/networks_webhooks_http_servers_info.py ansible_collections/cisco/meraki/plugins/action/networks_webhooks_payload_templates.py @@ -28396,6 +28842,10 @@ ansible_collections/cisco/meraki/plugins/action/networks_wireless_clients_latenc ansible_collections/cisco/meraki/plugins/action/networks_wireless_connection_stats_info.py ansible_collections/cisco/meraki/plugins/action/networks_wireless_data_rate_history_info.py ansible_collections/cisco/meraki/plugins/action/networks_wireless_devices_connection_stats_info.py +ansible_collections/cisco/meraki/plugins/action/networks_wireless_ethernet_ports_profiles.py +ansible_collections/cisco/meraki/plugins/action/networks_wireless_ethernet_ports_profiles_assign.py +ansible_collections/cisco/meraki/plugins/action/networks_wireless_ethernet_ports_profiles_info.py +ansible_collections/cisco/meraki/plugins/action/networks_wireless_ethernet_ports_profiles_set_default.py ansible_collections/cisco/meraki/plugins/action/networks_wireless_failed_connections_info.py ansible_collections/cisco/meraki/plugins/action/networks_wireless_latency_history_info.py ansible_collections/cisco/meraki/plugins/action/networks_wireless_latency_stats_info.py @@ -28450,6 +28900,9 @@ ansible_collections/cisco/meraki/plugins/action/organizations_api_requests_overv ansible_collections/cisco/meraki/plugins/action/organizations_api_requests_overview_response_codes_by_interval_info.py ansible_collections/cisco/meraki/plugins/action/organizations_appliance_security_intrusion.py ansible_collections/cisco/meraki/plugins/action/organizations_appliance_security_intrusion_info.py +ansible_collections/cisco/meraki/plugins/action/organizations_appliance_traffic_shaping_vpn_exclusions_by_network_info.py +ansible_collections/cisco/meraki/plugins/action/organizations_appliance_uplinks_statuses_overview_info.py +ansible_collections/cisco/meraki/plugins/action/organizations_appliance_uplinks_usage_by_network_info.py ansible_collections/cisco/meraki/plugins/action/organizations_appliance_vpn_third_party_vpnpeers.py ansible_collections/cisco/meraki/plugins/action/organizations_appliance_vpn_third_party_vpnpeers_info.py ansible_collections/cisco/meraki/plugins/action/organizations_appliance_vpn_vpn_firewall_rules.py @@ -28458,8 +28911,14 @@ ansible_collections/cisco/meraki/plugins/action/organizations_branding_policies. ansible_collections/cisco/meraki/plugins/action/organizations_branding_policies_info.py ansible_collections/cisco/meraki/plugins/action/organizations_branding_policies_priorities.py ansible_collections/cisco/meraki/plugins/action/organizations_branding_policies_priorities_info.py +ansible_collections/cisco/meraki/plugins/action/organizations_camera_boundaries_areas_by_device_info.py +ansible_collections/cisco/meraki/plugins/action/organizations_camera_boundaries_lines_by_device_info.py ansible_collections/cisco/meraki/plugins/action/organizations_camera_custom_analytics_artifacts.py ansible_collections/cisco/meraki/plugins/action/organizations_camera_custom_analytics_artifacts_info.py +ansible_collections/cisco/meraki/plugins/action/organizations_camera_detections_history_by_boundary_by_interval_info.py +ansible_collections/cisco/meraki/plugins/action/organizations_camera_permissions_info.py +ansible_collections/cisco/meraki/plugins/action/organizations_camera_roles.py +ansible_collections/cisco/meraki/plugins/action/organizations_camera_roles_info.py ansible_collections/cisco/meraki/plugins/action/organizations_cellular_gateway_uplink_statuses_info.py ansible_collections/cisco/meraki/plugins/action/organizations_claim.py ansible_collections/cisco/meraki/plugins/action/organizations_clients_bandwidth_usage_history_info.py @@ -28471,7 +28930,9 @@ ansible_collections/cisco/meraki/plugins/action/organizations_config_templates_i ansible_collections/cisco/meraki/plugins/action/organizations_config_templates_switch_profiles_info.py ansible_collections/cisco/meraki/plugins/action/organizations_config_templates_switch_profiles_ports.py ansible_collections/cisco/meraki/plugins/action/organizations_config_templates_switch_profiles_ports_info.py +ansible_collections/cisco/meraki/plugins/action/organizations_devices_availabilities_change_history_info.py ansible_collections/cisco/meraki/plugins/action/organizations_devices_availabilities_info.py +ansible_collections/cisco/meraki/plugins/action/organizations_devices_boots_history_info.py ansible_collections/cisco/meraki/plugins/action/organizations_devices_info.py ansible_collections/cisco/meraki/plugins/action/organizations_devices_power_modules_statuses_by_device_info.py ansible_collections/cisco/meraki/plugins/action/organizations_devices_provisioning_statuses_info.py @@ -28521,7 +28982,11 @@ ansible_collections/cisco/meraki/plugins/action/organizations_saml_roles.py ansible_collections/cisco/meraki/plugins/action/organizations_saml_roles_info.py ansible_collections/cisco/meraki/plugins/action/organizations_sensor_readings_history_info.py ansible_collections/cisco/meraki/plugins/action/organizations_sensor_readings_latest_info.py +ansible_collections/cisco/meraki/plugins/action/organizations_sm_admins_roles.py +ansible_collections/cisco/meraki/plugins/action/organizations_sm_admins_roles_info.py ansible_collections/cisco/meraki/plugins/action/organizations_sm_apns_cert_info.py +ansible_collections/cisco/meraki/plugins/action/organizations_sm_sentry_policies_assignments.py +ansible_collections/cisco/meraki/plugins/action/organizations_sm_sentry_policies_assignments_by_network_info.py ansible_collections/cisco/meraki/plugins/action/organizations_sm_vpp_accounts_info.py ansible_collections/cisco/meraki/plugins/action/organizations_snmp.py ansible_collections/cisco/meraki/plugins/action/organizations_snmp_info.py @@ -28530,14 +28995,23 @@ ansible_collections/cisco/meraki/plugins/action/organizations_summary_top_client ansible_collections/cisco/meraki/plugins/action/organizations_summary_top_clients_manufacturers_by_usage_info.py ansible_collections/cisco/meraki/plugins/action/organizations_summary_top_devices_by_usage_info.py ansible_collections/cisco/meraki/plugins/action/organizations_summary_top_devices_models_by_usage_info.py +ansible_collections/cisco/meraki/plugins/action/organizations_summary_top_networks_by_status_info.py ansible_collections/cisco/meraki/plugins/action/organizations_summary_top_ssids_by_usage_info.py ansible_collections/cisco/meraki/plugins/action/organizations_summary_top_switches_by_energy_usage_info.py ansible_collections/cisco/meraki/plugins/action/organizations_switch_devices_clone.py ansible_collections/cisco/meraki/plugins/action/organizations_switch_ports_by_switch_info.py ansible_collections/cisco/meraki/plugins/action/organizations_uplinks_statuses_info.py ansible_collections/cisco/meraki/plugins/action/organizations_users.py +ansible_collections/cisco/meraki/plugins/action/organizations_webhooks_callbacks_statuses_info.py ansible_collections/cisco/meraki/plugins/action/organizations_webhooks_logs_info.py +ansible_collections/cisco/meraki/plugins/action/organizations_wireless_devices_channel_utilization_by_device_info.py +ansible_collections/cisco/meraki/plugins/action/organizations_wireless_devices_channel_utilization_by_network_info.py +ansible_collections/cisco/meraki/plugins/action/organizations_wireless_devices_channel_utilization_history_by_device_by_interval_info.py +ansible_collections/cisco/meraki/plugins/action/organizations_wireless_devices_channel_utilization_history_by_network_by_interval_info.py ansible_collections/cisco/meraki/plugins/action/organizations_wireless_devices_ethernet_statuses_info.py +ansible_collections/cisco/meraki/plugins/action/organizations_wireless_devices_packet_loss_by_client_info.py +ansible_collections/cisco/meraki/plugins/action/organizations_wireless_devices_packet_loss_by_device_info.py +ansible_collections/cisco/meraki/plugins/action/organizations_wireless_devices_packet_loss_by_network_info.py ansible_collections/cisco/meraki/plugins/doc_fragments/__init__.py ansible_collections/cisco/meraki/plugins/doc_fragments/meraki.py ansible_collections/cisco/meraki/plugins/doc_fragments/module.py @@ -28547,8 +29021,16 @@ ansible_collections/cisco/meraki/plugins/module_utils/network/meraki/__init__.py ansible_collections/cisco/meraki/plugins/module_utils/network/meraki/meraki.py ansible_collections/cisco/meraki/plugins/modules/__init__.py ansible_collections/cisco/meraki/plugins/modules/administered_identities_me_info.py +ansible_collections/cisco/meraki/plugins/modules/administered_licensing_subscription_entitlements_info.py +ansible_collections/cisco/meraki/plugins/modules/administered_licensing_subscription_subscriptions_bind.py +ansible_collections/cisco/meraki/plugins/modules/administered_licensing_subscription_subscriptions_claim.py +ansible_collections/cisco/meraki/plugins/modules/administered_licensing_subscription_subscriptions_claim_key_validate.py +ansible_collections/cisco/meraki/plugins/modules/administered_licensing_subscription_subscriptions_compliance_statuses_info.py +ansible_collections/cisco/meraki/plugins/modules/administered_licensing_subscription_subscriptions_info.py ansible_collections/cisco/meraki/plugins/modules/devices.py ansible_collections/cisco/meraki/plugins/modules/devices_appliance_performance_info.py +ansible_collections/cisco/meraki/plugins/modules/devices_appliance_radio_settings.py +ansible_collections/cisco/meraki/plugins/modules/devices_appliance_radio_settings_info.py ansible_collections/cisco/meraki/plugins/modules/devices_appliance_uplinks_settings.py ansible_collections/cisco/meraki/plugins/modules/devices_appliance_uplinks_settings_info.py ansible_collections/cisco/meraki/plugins/modules/devices_appliance_vmx_authentication_token.py @@ -28573,10 +29055,18 @@ ansible_collections/cisco/meraki/plugins/modules/devices_cellular_gateway_port_f ansible_collections/cisco/meraki/plugins/modules/devices_cellular_sims.py ansible_collections/cisco/meraki/plugins/modules/devices_cellular_sims_info.py ansible_collections/cisco/meraki/plugins/modules/devices_info.py +ansible_collections/cisco/meraki/plugins/modules/devices_live_tools_arp_table.py +ansible_collections/cisco/meraki/plugins/modules/devices_live_tools_arp_table_info.py +ansible_collections/cisco/meraki/plugins/modules/devices_live_tools_cable_test.py +ansible_collections/cisco/meraki/plugins/modules/devices_live_tools_cable_test_info.py ansible_collections/cisco/meraki/plugins/modules/devices_live_tools_ping.py ansible_collections/cisco/meraki/plugins/modules/devices_live_tools_ping_device.py ansible_collections/cisco/meraki/plugins/modules/devices_live_tools_ping_device_info.py ansible_collections/cisco/meraki/plugins/modules/devices_live_tools_ping_info.py +ansible_collections/cisco/meraki/plugins/modules/devices_live_tools_throughput_test.py +ansible_collections/cisco/meraki/plugins/modules/devices_live_tools_throughput_test_info.py +ansible_collections/cisco/meraki/plugins/modules/devices_live_tools_wake_on_lan.py +ansible_collections/cisco/meraki/plugins/modules/devices_live_tools_wake_on_lan_info.py ansible_collections/cisco/meraki/plugins/modules/devices_lldp_cdp_info.py ansible_collections/cisco/meraki/plugins/modules/devices_management_interface.py ansible_collections/cisco/meraki/plugins/modules/devices_management_interface_info.py @@ -28594,6 +29084,7 @@ ansible_collections/cisco/meraki/plugins/modules/devices_switch_routing_static_r ansible_collections/cisco/meraki/plugins/modules/devices_switch_routing_static_routes_info.py ansible_collections/cisco/meraki/plugins/modules/devices_switch_warm_spare.py ansible_collections/cisco/meraki/plugins/modules/devices_switch_warm_spare_info.py +ansible_collections/cisco/meraki/plugins/modules/devices_wireless_alternate_management_interface_ipv6.py ansible_collections/cisco/meraki/plugins/modules/devices_wireless_bluetooth_settings.py ansible_collections/cisco/meraki/plugins/modules/devices_wireless_bluetooth_settings_info.py ansible_collections/cisco/meraki/plugins/modules/devices_wireless_connection_stats_info.py @@ -28676,6 +29167,8 @@ ansible_collections/cisco/meraki/plugins/modules/networks_appliance_ports.py ansible_collections/cisco/meraki/plugins/modules/networks_appliance_ports_info.py ansible_collections/cisco/meraki/plugins/modules/networks_appliance_prefixes_delegated_statics.py ansible_collections/cisco/meraki/plugins/modules/networks_appliance_prefixes_delegated_statics_info.py +ansible_collections/cisco/meraki/plugins/modules/networks_appliance_rf_profiles.py +ansible_collections/cisco/meraki/plugins/modules/networks_appliance_rf_profiles_info.py ansible_collections/cisco/meraki/plugins/modules/networks_appliance_security_intrusion.py ansible_collections/cisco/meraki/plugins/modules/networks_appliance_security_intrusion_info.py ansible_collections/cisco/meraki/plugins/modules/networks_appliance_security_malware.py @@ -28697,6 +29190,7 @@ ansible_collections/cisco/meraki/plugins/modules/networks_appliance_traffic_shap ansible_collections/cisco/meraki/plugins/modules/networks_appliance_traffic_shaping_uplink_bandwidth_info.py ansible_collections/cisco/meraki/plugins/modules/networks_appliance_traffic_shaping_uplink_selection.py ansible_collections/cisco/meraki/plugins/modules/networks_appliance_traffic_shaping_uplink_selection_info.py +ansible_collections/cisco/meraki/plugins/modules/networks_appliance_traffic_shaping_vpn_exclusions.py ansible_collections/cisco/meraki/plugins/modules/networks_appliance_vlans.py ansible_collections/cisco/meraki/plugins/modules/networks_appliance_vlans_info.py ansible_collections/cisco/meraki/plugins/modules/networks_appliance_vlans_settings.py @@ -28784,14 +29278,18 @@ ansible_collections/cisco/meraki/plugins/modules/networks_sm_devices_device_comm ansible_collections/cisco/meraki/plugins/modules/networks_sm_devices_device_profiles_info.py ansible_collections/cisco/meraki/plugins/modules/networks_sm_devices_fields.py ansible_collections/cisco/meraki/plugins/modules/networks_sm_devices_info.py +ansible_collections/cisco/meraki/plugins/modules/networks_sm_devices_install_apps.py ansible_collections/cisco/meraki/plugins/modules/networks_sm_devices_lock.py ansible_collections/cisco/meraki/plugins/modules/networks_sm_devices_modify_tags.py ansible_collections/cisco/meraki/plugins/modules/networks_sm_devices_move.py ansible_collections/cisco/meraki/plugins/modules/networks_sm_devices_network_adapters_info.py ansible_collections/cisco/meraki/plugins/modules/networks_sm_devices_performance_history_info.py +ansible_collections/cisco/meraki/plugins/modules/networks_sm_devices_reboot.py ansible_collections/cisco/meraki/plugins/modules/networks_sm_devices_refresh_details.py ansible_collections/cisco/meraki/plugins/modules/networks_sm_devices_security_centers_info.py +ansible_collections/cisco/meraki/plugins/modules/networks_sm_devices_shutdown.py ansible_collections/cisco/meraki/plugins/modules/networks_sm_devices_unenroll.py +ansible_collections/cisco/meraki/plugins/modules/networks_sm_devices_uninstall_apps.py ansible_collections/cisco/meraki/plugins/modules/networks_sm_devices_wipe.py ansible_collections/cisco/meraki/plugins/modules/networks_sm_devices_wlan_lists_info.py ansible_collections/cisco/meraki/plugins/modules/networks_sm_profiles_info.py @@ -28858,6 +29356,10 @@ ansible_collections/cisco/meraki/plugins/modules/networks_traffic_analysis_info. ansible_collections/cisco/meraki/plugins/modules/networks_traffic_shaping_application_categories_info.py ansible_collections/cisco/meraki/plugins/modules/networks_traffic_shaping_dscp_tagging_options_info.py ansible_collections/cisco/meraki/plugins/modules/networks_unbind.py +ansible_collections/cisco/meraki/plugins/modules/networks_vlan_profiles.py +ansible_collections/cisco/meraki/plugins/modules/networks_vlan_profiles_assignments_by_device_info.py +ansible_collections/cisco/meraki/plugins/modules/networks_vlan_profiles_assignments_reassign.py +ansible_collections/cisco/meraki/plugins/modules/networks_vlan_profiles_info.py ansible_collections/cisco/meraki/plugins/modules/networks_webhooks_http_servers.py ansible_collections/cisco/meraki/plugins/modules/networks_webhooks_http_servers_info.py ansible_collections/cisco/meraki/plugins/modules/networks_webhooks_payload_templates.py @@ -28876,6 +29378,10 @@ ansible_collections/cisco/meraki/plugins/modules/networks_wireless_clients_laten ansible_collections/cisco/meraki/plugins/modules/networks_wireless_connection_stats_info.py ansible_collections/cisco/meraki/plugins/modules/networks_wireless_data_rate_history_info.py ansible_collections/cisco/meraki/plugins/modules/networks_wireless_devices_connection_stats_info.py +ansible_collections/cisco/meraki/plugins/modules/networks_wireless_ethernet_ports_profiles.py +ansible_collections/cisco/meraki/plugins/modules/networks_wireless_ethernet_ports_profiles_assign.py +ansible_collections/cisco/meraki/plugins/modules/networks_wireless_ethernet_ports_profiles_info.py +ansible_collections/cisco/meraki/plugins/modules/networks_wireless_ethernet_ports_profiles_set_default.py ansible_collections/cisco/meraki/plugins/modules/networks_wireless_failed_connections_info.py ansible_collections/cisco/meraki/plugins/modules/networks_wireless_latency_history_info.py ansible_collections/cisco/meraki/plugins/modules/networks_wireless_latency_stats_info.py @@ -28930,6 +29436,9 @@ ansible_collections/cisco/meraki/plugins/modules/organizations_api_requests_over ansible_collections/cisco/meraki/plugins/modules/organizations_api_requests_overview_response_codes_by_interval_info.py ansible_collections/cisco/meraki/plugins/modules/organizations_appliance_security_intrusion.py ansible_collections/cisco/meraki/plugins/modules/organizations_appliance_security_intrusion_info.py +ansible_collections/cisco/meraki/plugins/modules/organizations_appliance_traffic_shaping_vpn_exclusions_by_network_info.py +ansible_collections/cisco/meraki/plugins/modules/organizations_appliance_uplinks_statuses_overview_info.py +ansible_collections/cisco/meraki/plugins/modules/organizations_appliance_uplinks_usage_by_network_info.py ansible_collections/cisco/meraki/plugins/modules/organizations_appliance_vpn_third_party_vpnpeers.py ansible_collections/cisco/meraki/plugins/modules/organizations_appliance_vpn_third_party_vpnpeers_info.py ansible_collections/cisco/meraki/plugins/modules/organizations_appliance_vpn_vpn_firewall_rules.py @@ -28938,8 +29447,14 @@ ansible_collections/cisco/meraki/plugins/modules/organizations_branding_policies ansible_collections/cisco/meraki/plugins/modules/organizations_branding_policies_info.py ansible_collections/cisco/meraki/plugins/modules/organizations_branding_policies_priorities.py ansible_collections/cisco/meraki/plugins/modules/organizations_branding_policies_priorities_info.py +ansible_collections/cisco/meraki/plugins/modules/organizations_camera_boundaries_areas_by_device_info.py +ansible_collections/cisco/meraki/plugins/modules/organizations_camera_boundaries_lines_by_device_info.py ansible_collections/cisco/meraki/plugins/modules/organizations_camera_custom_analytics_artifacts.py ansible_collections/cisco/meraki/plugins/modules/organizations_camera_custom_analytics_artifacts_info.py +ansible_collections/cisco/meraki/plugins/modules/organizations_camera_detections_history_by_boundary_by_interval_info.py +ansible_collections/cisco/meraki/plugins/modules/organizations_camera_permissions_info.py +ansible_collections/cisco/meraki/plugins/modules/organizations_camera_roles.py +ansible_collections/cisco/meraki/plugins/modules/organizations_camera_roles_info.py ansible_collections/cisco/meraki/plugins/modules/organizations_cellular_gateway_uplink_statuses_info.py ansible_collections/cisco/meraki/plugins/modules/organizations_claim.py ansible_collections/cisco/meraki/plugins/modules/organizations_clients_bandwidth_usage_history_info.py @@ -28951,7 +29466,9 @@ ansible_collections/cisco/meraki/plugins/modules/organizations_config_templates_ ansible_collections/cisco/meraki/plugins/modules/organizations_config_templates_switch_profiles_info.py ansible_collections/cisco/meraki/plugins/modules/organizations_config_templates_switch_profiles_ports.py ansible_collections/cisco/meraki/plugins/modules/organizations_config_templates_switch_profiles_ports_info.py +ansible_collections/cisco/meraki/plugins/modules/organizations_devices_availabilities_change_history_info.py ansible_collections/cisco/meraki/plugins/modules/organizations_devices_availabilities_info.py +ansible_collections/cisco/meraki/plugins/modules/organizations_devices_boots_history_info.py ansible_collections/cisco/meraki/plugins/modules/organizations_devices_info.py ansible_collections/cisco/meraki/plugins/modules/organizations_devices_power_modules_statuses_by_device_info.py ansible_collections/cisco/meraki/plugins/modules/organizations_devices_provisioning_statuses_info.py @@ -29001,7 +29518,11 @@ ansible_collections/cisco/meraki/plugins/modules/organizations_saml_roles.py ansible_collections/cisco/meraki/plugins/modules/organizations_saml_roles_info.py ansible_collections/cisco/meraki/plugins/modules/organizations_sensor_readings_history_info.py ansible_collections/cisco/meraki/plugins/modules/organizations_sensor_readings_latest_info.py +ansible_collections/cisco/meraki/plugins/modules/organizations_sm_admins_roles.py +ansible_collections/cisco/meraki/plugins/modules/organizations_sm_admins_roles_info.py ansible_collections/cisco/meraki/plugins/modules/organizations_sm_apns_cert_info.py +ansible_collections/cisco/meraki/plugins/modules/organizations_sm_sentry_policies_assignments.py +ansible_collections/cisco/meraki/plugins/modules/organizations_sm_sentry_policies_assignments_by_network_info.py ansible_collections/cisco/meraki/plugins/modules/organizations_sm_vpp_accounts_info.py ansible_collections/cisco/meraki/plugins/modules/organizations_snmp.py ansible_collections/cisco/meraki/plugins/modules/organizations_snmp_info.py @@ -29010,14 +29531,23 @@ ansible_collections/cisco/meraki/plugins/modules/organizations_summary_top_clien ansible_collections/cisco/meraki/plugins/modules/organizations_summary_top_clients_manufacturers_by_usage_info.py ansible_collections/cisco/meraki/plugins/modules/organizations_summary_top_devices_by_usage_info.py ansible_collections/cisco/meraki/plugins/modules/organizations_summary_top_devices_models_by_usage_info.py +ansible_collections/cisco/meraki/plugins/modules/organizations_summary_top_networks_by_status_info.py ansible_collections/cisco/meraki/plugins/modules/organizations_summary_top_ssids_by_usage_info.py ansible_collections/cisco/meraki/plugins/modules/organizations_summary_top_switches_by_energy_usage_info.py ansible_collections/cisco/meraki/plugins/modules/organizations_switch_devices_clone.py ansible_collections/cisco/meraki/plugins/modules/organizations_switch_ports_by_switch_info.py ansible_collections/cisco/meraki/plugins/modules/organizations_uplinks_statuses_info.py ansible_collections/cisco/meraki/plugins/modules/organizations_users.py +ansible_collections/cisco/meraki/plugins/modules/organizations_webhooks_callbacks_statuses_info.py ansible_collections/cisco/meraki/plugins/modules/organizations_webhooks_logs_info.py +ansible_collections/cisco/meraki/plugins/modules/organizations_wireless_devices_channel_utilization_by_device_info.py +ansible_collections/cisco/meraki/plugins/modules/organizations_wireless_devices_channel_utilization_by_network_info.py +ansible_collections/cisco/meraki/plugins/modules/organizations_wireless_devices_channel_utilization_history_by_device_by_interval_info.py +ansible_collections/cisco/meraki/plugins/modules/organizations_wireless_devices_channel_utilization_history_by_network_by_interval_info.py ansible_collections/cisco/meraki/plugins/modules/organizations_wireless_devices_ethernet_statuses_info.py +ansible_collections/cisco/meraki/plugins/modules/organizations_wireless_devices_packet_loss_by_client_info.py +ansible_collections/cisco/meraki/plugins/modules/organizations_wireless_devices_packet_loss_by_device_info.py +ansible_collections/cisco/meraki/plugins/modules/organizations_wireless_devices_packet_loss_by_network_info.py ansible_collections/cisco/meraki/plugins/plugin_utils/__init__.py ansible_collections/cisco/meraki/plugins/plugin_utils/exceptions.py ansible_collections/cisco/meraki/plugins/plugin_utils/meraki.py @@ -29139,6 +29669,8 @@ ansible_collections/cisco/mso/plugins/modules/mso_schema_site_anp_epg_useg_attri ansible_collections/cisco/mso/plugins/modules/mso_schema_site_bd.py ansible_collections/cisco/mso/plugins/modules/mso_schema_site_bd_l3out.py ansible_collections/cisco/mso/plugins/modules/mso_schema_site_bd_subnet.py +ansible_collections/cisco/mso/plugins/modules/mso_schema_site_contract_service_graph.py +ansible_collections/cisco/mso/plugins/modules/mso_schema_site_contract_service_graph_listener.py ansible_collections/cisco/mso/plugins/modules/mso_schema_site_external_epg.py ansible_collections/cisco/mso/plugins/modules/mso_schema_site_external_epg_selector.py ansible_collections/cisco/mso/plugins/modules/mso_schema_site_l3out.py @@ -29246,6 +29778,13 @@ ansible_collections/cisco/mso/tests/integration/targets/mso_schema_site_bd_l3out ansible_collections/cisco/mso/tests/integration/targets/mso_schema_site_bd_l3out/tasks/main.yml ansible_collections/cisco/mso/tests/integration/targets/mso_schema_site_bd_subnet/aliases ansible_collections/cisco/mso/tests/integration/targets/mso_schema_site_bd_subnet/tasks/main.yml +ansible_collections/cisco/mso/tests/integration/targets/mso_schema_site_contract_service_graph/aliases +ansible_collections/cisco/mso/tests/integration/targets/mso_schema_site_contract_service_graph/tasks/l4_l7_devices.yml +ansible_collections/cisco/mso/tests/integration/targets/mso_schema_site_contract_service_graph/tasks/main.yml +ansible_collections/cisco/mso/tests/integration/targets/mso_schema_site_contract_service_graph_listener/aliases +ansible_collections/cisco/mso/tests/integration/targets/mso_schema_site_contract_service_graph_listener/tasks/l4_l7_devices.yml +ansible_collections/cisco/mso/tests/integration/targets/mso_schema_site_contract_service_graph_listener/tasks/main.yml +ansible_collections/cisco/mso/tests/integration/targets/mso_schema_site_contract_service_graph_listener/tasks/pki/admin.crt ansible_collections/cisco/mso/tests/integration/targets/mso_schema_site_external_epg/aliases ansible_collections/cisco/mso/tests/integration/targets/mso_schema_site_external_epg/tasks/main.yml ansible_collections/cisco/mso/tests/integration/targets/mso_schema_site_external_epg_selector/aliases @@ -29253,6 +29792,7 @@ ansible_collections/cisco/mso/tests/integration/targets/mso_schema_site_external ansible_collections/cisco/mso/tests/integration/targets/mso_schema_site_l3out/aliases ansible_collections/cisco/mso/tests/integration/targets/mso_schema_site_l3out/tasks/main.yml ansible_collections/cisco/mso/tests/integration/targets/mso_schema_site_service_graph/aliases +ansible_collections/cisco/mso/tests/integration/targets/mso_schema_site_service_graph/tasks/l4_l7_devices.yml ansible_collections/cisco/mso/tests/integration/targets/mso_schema_site_service_graph/tasks/main.yml ansible_collections/cisco/mso/tests/integration/targets/mso_schema_site_vrf_region/aliases ansible_collections/cisco/mso/tests/integration/targets/mso_schema_site_vrf_region/tasks/main.yml @@ -31363,6 +31903,7 @@ ansible_collections/community/aws/plugins/modules/directconnect_virtual_interfac ansible_collections/community/aws/plugins/modules/dms_endpoint.py ansible_collections/community/aws/plugins/modules/dms_replication_subnet_group.py ansible_collections/community/aws/plugins/modules/dynamodb_table.py +ansible_collections/community/aws/plugins/modules/dynamodb_table_info.py ansible_collections/community/aws/plugins/modules/dynamodb_ttl.py ansible_collections/community/aws/plugins/modules/ec2_ami_copy.py ansible_collections/community/aws/plugins/modules/ec2_carrier_gateway.py @@ -32826,6 +33367,7 @@ ansible_collections/community/crypto/changelogs/changelog.yaml ansible_collections/community/crypto/changelogs/changelog.yaml.license ansible_collections/community/crypto/changelogs/config.yaml ansible_collections/community/crypto/changelogs/fragments/.keep +ansible_collections/community/crypto/docs/docsite/config.yml ansible_collections/community/crypto/docs/docsite/extra-docs.yml ansible_collections/community/crypto/docs/docsite/links.yml ansible_collections/community/crypto/docs/docsite/rst/guide_ownca.rst @@ -32928,6 +33470,7 @@ ansible_collections/community/crypto/plugins/modules/openssl_publickey_info.py ansible_collections/community/crypto/plugins/modules/openssl_signature.py ansible_collections/community/crypto/plugins/modules/openssl_signature_info.py ansible_collections/community/crypto/plugins/modules/x509_certificate.py +ansible_collections/community/crypto/plugins/modules/x509_certificate_convert.py ansible_collections/community/crypto/plugins/modules/x509_certificate_info.py ansible_collections/community/crypto/plugins/modules/x509_certificate_pipe.py ansible_collections/community/crypto/plugins/modules/x509_crl.py @@ -33218,6 +33761,10 @@ ansible_collections/community/crypto/tests/integration/targets/x509_certificate/ ansible_collections/community/crypto/tests/integration/targets/x509_certificate/tasks/selfsigned.yml ansible_collections/community/crypto/tests/integration/targets/x509_certificate/tests/validate_ownca.yml ansible_collections/community/crypto/tests/integration/targets/x509_certificate/tests/validate_selfsigned.yml +ansible_collections/community/crypto/tests/integration/targets/x509_certificate_convert/aliases +ansible_collections/community/crypto/tests/integration/targets/x509_certificate_convert/meta/main.yml +ansible_collections/community/crypto/tests/integration/targets/x509_certificate_convert/tasks/impl.yml +ansible_collections/community/crypto/tests/integration/targets/x509_certificate_convert/tasks/main.yml ansible_collections/community/crypto/tests/integration/targets/x509_certificate_info/aliases ansible_collections/community/crypto/tests/integration/targets/x509_certificate_info/files/cert1.pem ansible_collections/community/crypto/tests/integration/targets/x509_certificate_info/meta/main.yml @@ -33248,6 +33795,8 @@ ansible_collections/community/crypto/tests/sanity/ignore-2.16.txt ansible_collections/community/crypto/tests/sanity/ignore-2.16.txt.license ansible_collections/community/crypto/tests/sanity/ignore-2.17.txt ansible_collections/community/crypto/tests/sanity/ignore-2.17.txt.license +ansible_collections/community/crypto/tests/sanity/ignore-2.18.txt +ansible_collections/community/crypto/tests/sanity/ignore-2.18.txt.license ansible_collections/community/crypto/tests/sanity/ignore-2.9.txt ansible_collections/community/crypto/tests/sanity/ignore-2.9.txt.license ansible_collections/community/crypto/tests/sanity/extra/extra-docs.json @@ -33552,6 +34101,7 @@ ansible_collections/community/dns/changelogs/changelog.yaml ansible_collections/community/dns/changelogs/changelog.yaml.license ansible_collections/community/dns/changelogs/config.yaml ansible_collections/community/dns/changelogs/fragments/.keep +ansible_collections/community/dns/docs/docsite/config.yml ansible_collections/community/dns/docs/docsite/extra-docs.yml ansible_collections/community/dns/docs/docsite/links.yml ansible_collections/community/dns/docs/docsite/rst/filter_guide.rst @@ -33577,8 +34127,11 @@ ansible_collections/community/dns/plugins/doc_fragments/options.py ansible_collections/community/dns/plugins/filter/domain_suffix.py ansible_collections/community/dns/plugins/filter/get_public_suffix.yml ansible_collections/community/dns/plugins/filter/get_registrable_domain.yml +ansible_collections/community/dns/plugins/filter/quote_txt.yml ansible_collections/community/dns/plugins/filter/remove_public_suffix.yml ansible_collections/community/dns/plugins/filter/remove_registrable_domain.yml +ansible_collections/community/dns/plugins/filter/txt.py +ansible_collections/community/dns/plugins/filter/unquote_txt.yml ansible_collections/community/dns/plugins/inventory/hetzner_dns_records.py ansible_collections/community/dns/plugins/inventory/hosttech_dns_records.py ansible_collections/community/dns/plugins/lookup/lookup.py @@ -33631,6 +34184,7 @@ ansible_collections/community/dns/plugins/plugin_utils/ips.py ansible_collections/community/dns/plugins/plugin_utils/public_suffix.py ansible_collections/community/dns/plugins/plugin_utils/resolver.py ansible_collections/community/dns/plugins/plugin_utils/templated_options.py +ansible_collections/community/dns/plugins/plugin_utils/unsafe.py ansible_collections/community/dns/plugins/plugin_utils/inventory/records.py ansible_collections/community/dns/tests/config.yml ansible_collections/community/dns/tests/ee/all.yml @@ -33645,6 +34199,8 @@ ansible_collections/community/dns/tests/integration/requirements.txt ansible_collections/community/dns/tests/integration/requirements.yml ansible_collections/community/dns/tests/integration/targets/filter_domain_suffix/aliases ansible_collections/community/dns/tests/integration/targets/filter_domain_suffix/tasks/main.yml +ansible_collections/community/dns/tests/integration/targets/filter_txt/aliases +ansible_collections/community/dns/tests/integration/targets/filter_txt/tasks/main.yml ansible_collections/community/dns/tests/integration/targets/hetzner/aliases ansible_collections/community/dns/tests/integration/targets/hetzner/tasks/main.yml ansible_collections/community/dns/tests/integration/targets/hetzner/tasks/record-sets.yml @@ -33679,6 +34235,8 @@ ansible_collections/community/dns/tests/sanity/ignore-2.16.txt ansible_collections/community/dns/tests/sanity/ignore-2.16.txt.license ansible_collections/community/dns/tests/sanity/ignore-2.17.txt ansible_collections/community/dns/tests/sanity/ignore-2.17.txt.license +ansible_collections/community/dns/tests/sanity/ignore-2.18.txt +ansible_collections/community/dns/tests/sanity/ignore-2.18.txt.license ansible_collections/community/dns/tests/sanity/ignore-2.9.txt ansible_collections/community/dns/tests/sanity/ignore-2.9.txt.license ansible_collections/community/dns/tests/sanity/extra/extra-docs.json @@ -33877,6 +34435,7 @@ ansible_collections/community/docker/plugins/modules/docker_volume_info.py ansible_collections/community/docker/plugins/plugin_utils/common.py ansible_collections/community/docker/plugins/plugin_utils/common_api.py ansible_collections/community/docker/plugins/plugin_utils/socket_handler.py +ansible_collections/community/docker/plugins/plugin_utils/unsafe.py ansible_collections/community/docker/tests/config.yml ansible_collections/community/docker/tests/galaxy-importer.cfg ansible_collections/community/docker/tests/ee/all.yml @@ -33919,6 +34478,7 @@ ansible_collections/community/docker/tests/integration/targets/docker_compose_v2 ansible_collections/community/docker/tests/integration/targets/docker_compose_v2/meta/main.yml ansible_collections/community/docker/tests/integration/targets/docker_compose_v2/tasks/main.yml ansible_collections/community/docker/tests/integration/targets/docker_compose_v2/tasks/run-test.yml +ansible_collections/community/docker/tests/integration/targets/docker_compose_v2/tasks/tests/definition.yml ansible_collections/community/docker/tests/integration/targets/docker_compose_v2/tasks/tests/pull.yml ansible_collections/community/docker/tests/integration/targets/docker_compose_v2/tasks/tests/start-stop.yml ansible_collections/community/docker/tests/integration/targets/docker_compose_v2_pull/aliases @@ -34316,6 +34876,8 @@ ansible_collections/community/docker/tests/sanity/ignore-2.16.txt ansible_collections/community/docker/tests/sanity/ignore-2.16.txt.license ansible_collections/community/docker/tests/sanity/ignore-2.17.txt ansible_collections/community/docker/tests/sanity/ignore-2.17.txt.license +ansible_collections/community/docker/tests/sanity/ignore-2.18.txt +ansible_collections/community/docker/tests/sanity/ignore-2.18.txt.license ansible_collections/community/docker/tests/sanity/extra/action-group.json ansible_collections/community/docker/tests/sanity/extra/action-group.json.license ansible_collections/community/docker/tests/sanity/extra/action-group.py @@ -34424,6 +34986,7 @@ ansible_collections/community/general/changelogs/changelog.yaml ansible_collections/community/general/changelogs/changelog.yaml.license ansible_collections/community/general/changelogs/config.yaml ansible_collections/community/general/changelogs/fragments/.keep +ansible_collections/community/general/docs/docsite/config.yml ansible_collections/community/general/docs/docsite/extra-docs.yml ansible_collections/community/general/docs/docsite/links.yml ansible_collections/community/general/docs/docsite/helper/lists_mergeby/default-common.yml @@ -34658,6 +35221,7 @@ ansible_collections/community/general/plugins/module_utils/cmd_runner.py ansible_collections/community/general/plugins/module_utils/consul.py ansible_collections/community/general/plugins/module_utils/csv.py ansible_collections/community/general/plugins/module_utils/database.py +ansible_collections/community/general/plugins/module_utils/datetime.py ansible_collections/community/general/plugins/module_utils/deps.py ansible_collections/community/general/plugins/module_utils/dimensiondata.py ansible_collections/community/general/plugins/module_utils/gandi_livedns_api.py @@ -34955,6 +35519,7 @@ ansible_collections/community/general/plugins/modules/keycloak_authz_permission. ansible_collections/community/general/plugins/modules/keycloak_authz_permission_info.py ansible_collections/community/general/plugins/modules/keycloak_client.py ansible_collections/community/general/plugins/modules/keycloak_client_rolemapping.py +ansible_collections/community/general/plugins/modules/keycloak_client_rolescope.py ansible_collections/community/general/plugins/modules/keycloak_clientscope.py ansible_collections/community/general/plugins/modules/keycloak_clientscope_type.py ansible_collections/community/general/plugins/modules/keycloak_clientsecret_info.py @@ -35333,6 +35898,7 @@ ansible_collections/community/general/plugins/modules/znode.py ansible_collections/community/general/plugins/modules/zpool_facts.py ansible_collections/community/general/plugins/modules/zypper.py ansible_collections/community/general/plugins/modules/zypper_repository.py +ansible_collections/community/general/plugins/plugin_utils/unsafe.py ansible_collections/community/general/plugins/test/a_module.py ansible_collections/community/general/plugins/test/fqdn_valid.py ansible_collections/community/general/tests/.gitignore @@ -35761,6 +36327,7 @@ ansible_collections/community/general/tests/integration/targets/ini_file/tasks/t ansible_collections/community/general/tests/integration/targets/ini_file/tasks/tests/05-ignore_spaces.yml ansible_collections/community/general/tests/integration/targets/ini_file/tasks/tests/06-modify_inactive_option.yml ansible_collections/community/general/tests/integration/targets/ini_file/tasks/tests/07-section_name_spaces.yml +ansible_collections/community/general/tests/integration/targets/ini_file/tasks/tests/08-section.yml ansible_collections/community/general/tests/integration/targets/interfaces_file/aliases ansible_collections/community/general/tests/integration/targets/interfaces_file/files/interfaces_ff ansible_collections/community/general/tests/integration/targets/interfaces_file/files/interfaces_ff_3841 @@ -35864,6 +36431,10 @@ ansible_collections/community/general/tests/integration/targets/keycloak_authz_p ansible_collections/community/general/tests/integration/targets/keycloak_client/README.md ansible_collections/community/general/tests/integration/targets/keycloak_client/tasks/main.yml ansible_collections/community/general/tests/integration/targets/keycloak_client/vars/main.yml +ansible_collections/community/general/tests/integration/targets/keycloak_client_rolescope/README.md +ansible_collections/community/general/tests/integration/targets/keycloak_client_rolescope/aliases +ansible_collections/community/general/tests/integration/targets/keycloak_client_rolescope/tasks/main.yml +ansible_collections/community/general/tests/integration/targets/keycloak_client_rolescope/vars/main.yml ansible_collections/community/general/tests/integration/targets/keycloak_clientscope_type/README.md ansible_collections/community/general/tests/integration/targets/keycloak_clientscope_type/docker-compose.yml ansible_collections/community/general/tests/integration/targets/keycloak_clientscope_type/tasks/main.yml @@ -36689,6 +37260,8 @@ ansible_collections/community/general/tests/sanity/ignore-2.16.txt ansible_collections/community/general/tests/sanity/ignore-2.16.txt.license ansible_collections/community/general/tests/sanity/ignore-2.17.txt ansible_collections/community/general/tests/sanity/ignore-2.17.txt.license +ansible_collections/community/general/tests/sanity/ignore-2.18.txt +ansible_collections/community/general/tests/sanity/ignore-2.18.txt.license ansible_collections/community/general/tests/sanity/extra/aliases.json ansible_collections/community/general/tests/sanity/extra/aliases.json.license ansible_collections/community/general/tests/sanity/extra/aliases.py @@ -38169,6 +38742,7 @@ ansible_collections/community/hrobot/changelogs/changelog.yaml ansible_collections/community/hrobot/changelogs/changelog.yaml.license ansible_collections/community/hrobot/changelogs/config.yaml ansible_collections/community/hrobot/changelogs/fragments/.keep +ansible_collections/community/hrobot/docs/docsite/config.yml ansible_collections/community/hrobot/docs/docsite/links.yml ansible_collections/community/hrobot/meta/execution-environment.yml ansible_collections/community/hrobot/meta/runtime.yml @@ -38189,6 +38763,7 @@ ansible_collections/community/hrobot/plugins/modules/server_info.py ansible_collections/community/hrobot/plugins/modules/ssh_key.py ansible_collections/community/hrobot/plugins/modules/ssh_key_info.py ansible_collections/community/hrobot/plugins/modules/v_switch.py +ansible_collections/community/hrobot/plugins/plugin_utils/unsafe.py ansible_collections/community/hrobot/tests/config.yml ansible_collections/community/hrobot/tests/ee/all.yml ansible_collections/community/hrobot/tests/ee/roles/smoke/library/smoke_ipaddress.py @@ -38209,6 +38784,8 @@ ansible_collections/community/hrobot/tests/sanity/ignore-2.16.txt ansible_collections/community/hrobot/tests/sanity/ignore-2.16.txt.license ansible_collections/community/hrobot/tests/sanity/ignore-2.17.txt ansible_collections/community/hrobot/tests/sanity/ignore-2.17.txt.license +ansible_collections/community/hrobot/tests/sanity/ignore-2.18.txt +ansible_collections/community/hrobot/tests/sanity/ignore-2.18.txt.license ansible_collections/community/hrobot/tests/sanity/ignore-2.9.txt ansible_collections/community/hrobot/tests/sanity/ignore-2.9.txt.license ansible_collections/community/hrobot/tests/sanity/extra/extra-docs.json @@ -38238,6 +38815,8 @@ ansible_collections/community/hrobot/tests/unit/plugins/modules/test_server_info ansible_collections/community/hrobot/tests/unit/plugins/modules/test_ssh_key.py ansible_collections/community/hrobot/tests/unit/plugins/modules/test_ssh_key_info.py ansible_collections/community/hrobot/tests/unit/plugins/modules/test_v_switch.py +ansible_collections/community/library_inventory_filtering_v1/CHANGELOG.md +ansible_collections/community/library_inventory_filtering_v1/CHANGELOG.md.license ansible_collections/community/library_inventory_filtering_v1/CHANGELOG.rst ansible_collections/community/library_inventory_filtering_v1/CHANGELOG.rst.license ansible_collections/community/library_inventory_filtering_v1/COPYING @@ -38247,6 +38826,8 @@ ansible_collections/community/library_inventory_filtering_v1/README.md ansible_collections/community/library_inventory_filtering_v1/codecov.yml ansible_collections/community/library_inventory_filtering_v1/.github/dependabot.yml ansible_collections/community/library_inventory_filtering_v1/.github/workflows/ansible-test.yml +ansible_collections/community/library_inventory_filtering_v1/.github/workflows/docs-pr.yml +ansible_collections/community/library_inventory_filtering_v1/.github/workflows/docs-push.yml ansible_collections/community/library_inventory_filtering_v1/.github/workflows/extra-tests.yml ansible_collections/community/library_inventory_filtering_v1/.github/workflows/import-galaxy.yml ansible_collections/community/library_inventory_filtering_v1/.github/workflows/reuse.yml @@ -38256,6 +38837,10 @@ ansible_collections/community/library_inventory_filtering_v1/changelogs/changelo ansible_collections/community/library_inventory_filtering_v1/changelogs/changelog.yaml.license ansible_collections/community/library_inventory_filtering_v1/changelogs/config.yaml ansible_collections/community/library_inventory_filtering_v1/changelogs/fragments/.keep +ansible_collections/community/library_inventory_filtering_v1/docs/docsite/config.yml +ansible_collections/community/library_inventory_filtering_v1/docs/docsite/extra-docs.yml +ansible_collections/community/library_inventory_filtering_v1/docs/docsite/links.yml +ansible_collections/community/library_inventory_filtering_v1/docs/docsite/rst/usage_guide.rst ansible_collections/community/library_inventory_filtering_v1/meta/runtime.yml ansible_collections/community/library_inventory_filtering_v1/plugins/doc_fragments/inventory_filter.py ansible_collections/community/library_inventory_filtering_v1/plugins/plugin_utils/inventory_filter.py @@ -40747,6 +41332,7 @@ ansible_collections/community/rabbitmq/tests/integration/targets/rabbitmq_user/a ansible_collections/community/rabbitmq/tests/integration/targets/rabbitmq_user/meta/main.yml ansible_collections/community/rabbitmq/tests/integration/targets/rabbitmq_user/tasks/main.yml ansible_collections/community/rabbitmq/tests/integration/targets/rabbitmq_user/tasks/tests.yml +ansible_collections/community/rabbitmq/tests/integration/targets/rabbitmq_user/tasks/tests_api.yml ansible_collections/community/rabbitmq/tests/integration/targets/rabbitmq_user_limits/aliases ansible_collections/community/rabbitmq/tests/integration/targets/rabbitmq_user_limits/meta/main.yml ansible_collections/community/rabbitmq/tests/integration/targets/rabbitmq_user_limits/tasks/main.yml @@ -40774,14 +41360,12 @@ ansible_collections/community/rabbitmq/tests/integration/targets/setup_tls/files ansible_collections/community/rabbitmq/tests/integration/targets/setup_tls/files/server_certificate.pem ansible_collections/community/rabbitmq/tests/integration/targets/setup_tls/files/server_key.pem ansible_collections/community/rabbitmq/tests/integration/targets/setup_tls/tasks/main.yml -ansible_collections/community/rabbitmq/tests/sanity/ignore-2.10.txt -ansible_collections/community/rabbitmq/tests/sanity/ignore-2.11.txt ansible_collections/community/rabbitmq/tests/sanity/ignore-2.12.txt ansible_collections/community/rabbitmq/tests/sanity/ignore-2.13.txt ansible_collections/community/rabbitmq/tests/sanity/ignore-2.14.txt ansible_collections/community/rabbitmq/tests/sanity/ignore-2.15.txt -ansible_collections/community/rabbitmq/tests/sanity/ignore-2.9.txt -ansible_collections/community/rabbitmq/tests/sanity/ignore.txt +ansible_collections/community/rabbitmq/tests/sanity/ignore-2.16.txt +ansible_collections/community/rabbitmq/tests/sanity/ignore-2.17.txt ansible_collections/community/rabbitmq/tests/unit/compat/__init__.py ansible_collections/community/rabbitmq/tests/unit/compat/builtins.py ansible_collections/community/rabbitmq/tests/unit/compat/mock.py @@ -40837,6 +41421,7 @@ ansible_collections/community/routeros/changelogs/changelog.yaml ansible_collections/community/routeros/changelogs/changelog.yaml.license ansible_collections/community/routeros/changelogs/config.yaml ansible_collections/community/routeros/changelogs/fragments/.keep +ansible_collections/community/routeros/docs/docsite/config.yml ansible_collections/community/routeros/docs/docsite/extra-docs.yml ansible_collections/community/routeros/docs/docsite/links.yml ansible_collections/community/routeros/docs/docsite/rst/api-guide.rst @@ -40892,6 +41477,8 @@ ansible_collections/community/routeros/tests/sanity/ignore-2.16.txt ansible_collections/community/routeros/tests/sanity/ignore-2.16.txt.license ansible_collections/community/routeros/tests/sanity/ignore-2.17.txt ansible_collections/community/routeros/tests/sanity/ignore-2.17.txt.license +ansible_collections/community/routeros/tests/sanity/ignore-2.18.txt +ansible_collections/community/routeros/tests/sanity/ignore-2.18.txt.license ansible_collections/community/routeros/tests/sanity/ignore-2.9.txt ansible_collections/community/routeros/tests/sanity/ignore-2.9.txt.license ansible_collections/community/routeros/tests/sanity/extra/extra-docs.json @@ -41394,26 +41981,6 @@ ansible_collections/community/vmware/changelogs/changelog.yaml ansible_collections/community/vmware/changelogs/config.yaml ansible_collections/community/vmware/docs/docsite/extra-docs.yml ansible_collections/community/vmware/docs/docsite/rst/dev_guide.rst -ansible_collections/community/vmware/docs/docsite/rst/scenario_guide.rst -ansible_collections/community/vmware/docs/docsite/rst/vmware_scenarios/faq.rst -ansible_collections/community/vmware/docs/docsite/rst/vmware_scenarios/scenario_clone_template.rst -ansible_collections/community/vmware/docs/docsite/rst/vmware_scenarios/scenario_find_vm_folder.rst -ansible_collections/community/vmware/docs/docsite/rst/vmware_scenarios/scenario_remove_vm.rst -ansible_collections/community/vmware/docs/docsite/rst/vmware_scenarios/scenario_rename_vm.rst -ansible_collections/community/vmware/docs/docsite/rst/vmware_scenarios/scenario_vmware_http.rst -ansible_collections/community/vmware/docs/docsite/rst/vmware_scenarios/scenario_vmware_tools_connection.rst -ansible_collections/community/vmware/docs/docsite/rst/vmware_scenarios/vmware_concepts.rst -ansible_collections/community/vmware/docs/docsite/rst/vmware_scenarios/vmware_external_doc_links.rst -ansible_collections/community/vmware/docs/docsite/rst/vmware_scenarios/vmware_getting_started.rst -ansible_collections/community/vmware/docs/docsite/rst/vmware_scenarios/vmware_intro.rst -ansible_collections/community/vmware/docs/docsite/rst/vmware_scenarios/vmware_inventory.rst -ansible_collections/community/vmware/docs/docsite/rst/vmware_scenarios/vmware_inventory_filters.rst -ansible_collections/community/vmware/docs/docsite/rst/vmware_scenarios/vmware_inventory_hostnames.rst -ansible_collections/community/vmware/docs/docsite/rst/vmware_scenarios/vmware_inventory_vm_attributes.rst -ansible_collections/community/vmware/docs/docsite/rst/vmware_scenarios/vmware_module_reference.rst -ansible_collections/community/vmware/docs/docsite/rst/vmware_scenarios/vmware_requirements.rst -ansible_collections/community/vmware/docs/docsite/rst/vmware_scenarios/vmware_scenarios.rst -ansible_collections/community/vmware/docs/docsite/rst/vmware_scenarios/vmware_troubleshooting.rst ansible_collections/community/vmware/meta/runtime.yml ansible_collections/community/vmware/plugins/connection/__init__.py ansible_collections/community/vmware/plugins/connection/vmware_tools.py @@ -41440,6 +42007,7 @@ ansible_collections/community/vmware/plugins/modules/vcenter_license.py ansible_collections/community/vmware/plugins/modules/vcenter_root_password_expiration.py ansible_collections/community/vmware/plugins/modules/vcenter_standard_key_provider.py ansible_collections/community/vmware/plugins/modules/vmware_about_info.py +ansible_collections/community/vmware/plugins/modules/vmware_all_snapshots_info.py ansible_collections/community/vmware/plugins/modules/vmware_category.py ansible_collections/community/vmware/plugins/modules/vmware_category_info.py ansible_collections/community/vmware/plugins/modules/vmware_cfg_backup.py @@ -42036,6 +42604,7 @@ ansible_collections/community/vmware/tests/integration/targets/vsphere_file/task ansible_collections/community/vmware/tests/sanity/ignore-2.15.txt ansible_collections/community/vmware/tests/sanity/ignore-2.16.txt ansible_collections/community/vmware/tests/sanity/ignore-2.17.txt +ansible_collections/community/vmware/tests/sanity/ignore-2.18.txt ansible_collections/community/vmware/tests/unit/__init__.py ansible_collections/community/vmware/tests/unit/requirements.txt ansible_collections/community/vmware/tests/unit/mock/__init__.py @@ -43110,6 +43679,7 @@ ansible_collections/containers/podman/plugins/module_utils/podman/__init__.py ansible_collections/containers/podman/plugins/module_utils/podman/common.py ansible_collections/containers/podman/plugins/module_utils/podman/podman_container_lib.py ansible_collections/containers/podman/plugins/module_utils/podman/podman_pod_lib.py +ansible_collections/containers/podman/plugins/module_utils/podman/quadlet.py ansible_collections/containers/podman/plugins/modules/__init__.py ansible_collections/containers/podman/plugins/modules/podman_container.py ansible_collections/containers/podman/plugins/modules/podman_container_exec.py @@ -43181,12 +43751,14 @@ ansible_collections/containers/podman/tests/integration/targets/podman_logout/ta ansible_collections/containers/podman/tests/integration/targets/podman_network/tasks/main.yml ansible_collections/containers/podman/tests/integration/targets/podman_network_info/tasks/main.yml ansible_collections/containers/podman/tests/integration/targets/podman_play/tasks/main.yml +ansible_collections/containers/podman/tests/integration/targets/podman_play/tasks/play-multi-yaml.yml ansible_collections/containers/podman/tests/integration/targets/podman_play/tasks/play-with-build.yml ansible_collections/containers/podman/tests/integration/targets/podman_play/tasks/play-with-options.yml ansible_collections/containers/podman/tests/integration/targets/podman_play/tasks/root-play.yml ansible_collections/containers/podman/tests/integration/targets/podman_play/tasks/files/Containerfile ansible_collections/containers/podman/tests/integration/targets/podman_play/tasks/files/envdata.yaml ansible_collections/containers/podman/tests/integration/targets/podman_play/tasks/files/kube-buil-test.yaml +ansible_collections/containers/podman/tests/integration/targets/podman_play/tasks/files/multi-yaml.yml ansible_collections/containers/podman/tests/integration/targets/podman_play/tasks/files/play-pod.yaml ansible_collections/containers/podman/tests/integration/targets/podman_play/tasks/files/play-root1.yaml ansible_collections/containers/podman/tests/integration/targets/podman_play/tasks/files/play-root3.yaml @@ -45221,6 +45793,7 @@ ansible_collections/dellemc/powerflex/docs/modules/mdm_cluster.rst ansible_collections/dellemc/powerflex/docs/modules/protection_domain.rst ansible_collections/dellemc/powerflex/docs/modules/replication_consistency_group.rst ansible_collections/dellemc/powerflex/docs/modules/replication_pair.rst +ansible_collections/dellemc/powerflex/docs/modules/resource_group.rst ansible_collections/dellemc/powerflex/docs/modules/sdc.rst ansible_collections/dellemc/powerflex/docs/modules/sds.rst ansible_collections/dellemc/powerflex/docs/modules/snapshot.rst @@ -45236,6 +45809,7 @@ ansible_collections/dellemc/powerflex/playbooks/modules/mdm_cluster.yml ansible_collections/dellemc/powerflex/playbooks/modules/protection_domain.yml ansible_collections/dellemc/powerflex/playbooks/modules/replication_consistency_group.yml ansible_collections/dellemc/powerflex/playbooks/modules/replication_pair.yml +ansible_collections/dellemc/powerflex/playbooks/modules/resource_group.yml ansible_collections/dellemc/powerflex/playbooks/modules/sdc.yml ansible_collections/dellemc/powerflex/playbooks/modules/sds.yml ansible_collections/dellemc/powerflex/playbooks/modules/snapshot.yml @@ -45264,6 +45838,7 @@ ansible_collections/dellemc/powerflex/plugins/modules/mdm_cluster.py ansible_collections/dellemc/powerflex/plugins/modules/protection_domain.py ansible_collections/dellemc/powerflex/plugins/modules/replication_consistency_group.py ansible_collections/dellemc/powerflex/plugins/modules/replication_pair.py +ansible_collections/dellemc/powerflex/plugins/modules/resource_group.py ansible_collections/dellemc/powerflex/plugins/modules/sdc.py ansible_collections/dellemc/powerflex/plugins/modules/sds.py ansible_collections/dellemc/powerflex/plugins/modules/snapshot.py @@ -45480,6 +46055,7 @@ ansible_collections/dellemc/powerflex/tests/unit/plugins/module_utils/mock_mdm_c ansible_collections/dellemc/powerflex/tests/unit/plugins/module_utils/mock_protection_domain_api.py ansible_collections/dellemc/powerflex/tests/unit/plugins/module_utils/mock_replication_consistency_group_api.py ansible_collections/dellemc/powerflex/tests/unit/plugins/module_utils/mock_replication_pair_api.py +ansible_collections/dellemc/powerflex/tests/unit/plugins/module_utils/mock_resource_group_api.py ansible_collections/dellemc/powerflex/tests/unit/plugins/module_utils/mock_sdc_api.py ansible_collections/dellemc/powerflex/tests/unit/plugins/module_utils/mock_sdk_response.py ansible_collections/dellemc/powerflex/tests/unit/plugins/module_utils/mock_sds_api.py @@ -45498,6 +46074,7 @@ ansible_collections/dellemc/powerflex/tests/unit/plugins/modules/test_mdm_cluste ansible_collections/dellemc/powerflex/tests/unit/plugins/modules/test_protection_domain.py ansible_collections/dellemc/powerflex/tests/unit/plugins/modules/test_replication_consistency_group.py ansible_collections/dellemc/powerflex/tests/unit/plugins/modules/test_replication_pair.py +ansible_collections/dellemc/powerflex/tests/unit/plugins/modules/test_resource_group.py ansible_collections/dellemc/powerflex/tests/unit/plugins/modules/test_sdc.py ansible_collections/dellemc/powerflex/tests/unit/plugins/modules/test_sds.py ansible_collections/dellemc/powerflex/tests/unit/plugins/modules/test_snapshot_policy.py @@ -47110,8 +47687,10 @@ ansible_collections/fortinet/fortios/plugins/modules/fortios_cifs_domain_control ansible_collections/fortinet/fortios/plugins/modules/fortios_cifs_profile.py ansible_collections/fortinet/fortios/plugins/modules/fortios_configuration_fact.py ansible_collections/fortinet/fortios/plugins/modules/fortios_credential_store_domain_controller.py +ansible_collections/fortinet/fortios/plugins/modules/fortios_diameter_filter_profile.py ansible_collections/fortinet/fortios/plugins/modules/fortios_dlp_data_type.py ansible_collections/fortinet/fortios/plugins/modules/fortios_dlp_dictionary.py +ansible_collections/fortinet/fortios/plugins/modules/fortios_dlp_exact_data_match.py ansible_collections/fortinet/fortios/plugins/modules/fortios_dlp_filepattern.py ansible_collections/fortinet/fortios/plugins/modules/fortios_dlp_fp_doc_source.py ansible_collections/fortinet/fortios/plugins/modules/fortios_dlp_fp_sensitivity.py @@ -47527,6 +48106,7 @@ ansible_collections/fortinet/fortios/plugins/modules/fortios_system_netflow.py ansible_collections/fortinet/fortios/plugins/modules/fortios_system_network_visibility.py ansible_collections/fortinet/fortios/plugins/modules/fortios_system_np6.py ansible_collections/fortinet/fortios/plugins/modules/fortios_system_npu.py +ansible_collections/fortinet/fortios/plugins/modules/fortios_system_npu_vlink.py ansible_collections/fortinet/fortios/plugins/modules/fortios_system_ntp.py ansible_collections/fortinet/fortios/plugins/modules/fortios_system_object_tagging.py ansible_collections/fortinet/fortios/plugins/modules/fortios_system_password_policy.py @@ -47613,6 +48193,7 @@ ansible_collections/fortinet/fortios/plugins/modules/fortios_user_device_categor ansible_collections/fortinet/fortios/plugins/modules/fortios_user_device_group.py ansible_collections/fortinet/fortios/plugins/modules/fortios_user_domain_controller.py ansible_collections/fortinet/fortios/plugins/modules/fortios_user_exchange.py +ansible_collections/fortinet/fortios/plugins/modules/fortios_user_external_identity_provider.py ansible_collections/fortinet/fortios/plugins/modules/fortios_user_fortitoken.py ansible_collections/fortinet/fortios/plugins/modules/fortios_user_fsso.py ansible_collections/fortinet/fortios/plugins/modules/fortios_user_fsso_polling.py @@ -47631,6 +48212,7 @@ ansible_collections/fortinet/fortios/plugins/modules/fortios_user_saml.py ansible_collections/fortinet/fortios/plugins/modules/fortios_user_security_exempt_list.py ansible_collections/fortinet/fortios/plugins/modules/fortios_user_setting.py ansible_collections/fortinet/fortios/plugins/modules/fortios_user_tacacsplus.py +ansible_collections/fortinet/fortios/plugins/modules/fortios_videofilter_keyword.py ansible_collections/fortinet/fortios/plugins/modules/fortios_videofilter_profile.py ansible_collections/fortinet/fortios/plugins/modules/fortios_videofilter_youtube_channel_filter.py ansible_collections/fortinet/fortios/plugins/modules/fortios_videofilter_youtube_key.py @@ -47656,6 +48238,7 @@ ansible_collections/fortinet/fortios/plugins/modules/fortios_vpn_kmip_server.py ansible_collections/fortinet/fortios/plugins/modules/fortios_vpn_l2tp.py ansible_collections/fortinet/fortios/plugins/modules/fortios_vpn_ocvpn.py ansible_collections/fortinet/fortios/plugins/modules/fortios_vpn_pptp.py +ansible_collections/fortinet/fortios/plugins/modules/fortios_vpn_qkd.py ansible_collections/fortinet/fortios/plugins/modules/fortios_vpn_ssl_client.py ansible_collections/fortinet/fortios/plugins/modules/fortios_vpn_ssl_settings.py ansible_collections/fortinet/fortios/plugins/modules/fortios_vpn_ssl_web_host_check_software.py @@ -49484,6 +50067,7 @@ ansible_collections/infinidat/infinibox/plugins/modules/infini_export_client.py ansible_collections/infinidat/infinibox/plugins/modules/infini_fibre_channel_switch.py ansible_collections/infinidat/infinibox/plugins/modules/infini_fs.py ansible_collections/infinidat/infinibox/plugins/modules/infini_host.py +ansible_collections/infinidat/infinibox/plugins/modules/infini_infinimetrics.py ansible_collections/infinidat/infinibox/plugins/modules/infini_map.py ansible_collections/infinidat/infinibox/plugins/modules/infini_metadata.py ansible_collections/infinidat/infinibox/plugins/modules/infini_network_space.py @@ -49513,6 +50097,8 @@ ansible_collections/infinidat/infinibox/tests/hacking/infini_fs_stat.json ansible_collections/infinidat/infinibox/tests/hacking/infini_host_absent.json ansible_collections/infinidat/infinibox/tests/hacking/infini_host_present.json ansible_collections/infinidat/infinibox/tests/hacking/infini_host_stat.json +ansible_collections/infinidat/infinibox/tests/hacking/infini_infinimetrics_absent.json +ansible_collections/infinidat/infinibox/tests/hacking/infini_infinimetrics_present.json ansible_collections/infinidat/infinibox/tests/hacking/infini_map_absent.json ansible_collections/infinidat/infinibox/tests/hacking/infini_map_present.json ansible_collections/infinidat/infinibox/tests/hacking/infini_map_stat.json @@ -49523,13 +50109,22 @@ ansible_collections/infinidat/infinibox/tests/hacking/infini_network_space_absen ansible_collections/infinidat/infinibox/tests/hacking/infini_network_space_present.json ansible_collections/infinidat/infinibox/tests/hacking/infini_network_space_stat.json ansible_collections/infinidat/infinibox/tests/hacking/infini_notification_rule_absent.json +ansible_collections/infinidat/infinibox/tests/hacking/infini_notification_rule_absent_1521.json +ansible_collections/infinidat/infinibox/tests/hacking/infini_notification_rule_absent_vibox.json ansible_collections/infinidat/infinibox/tests/hacking/infini_notification_rule_present.json +ansible_collections/infinidat/infinibox/tests/hacking/infini_notification_rule_present_1521.json +ansible_collections/infinidat/infinibox/tests/hacking/infini_notification_rule_present_vibox.json ansible_collections/infinidat/infinibox/tests/hacking/infini_notification_rule_stat.json ansible_collections/infinidat/infinibox/tests/hacking/infini_notification_target_absent.json ansible_collections/infinidat/infinibox/tests/hacking/infini_notification_target_present.json ansible_collections/infinidat/infinibox/tests/hacking/infini_notification_target_stat.json +ansible_collections/infinidat/infinibox/tests/hacking/infini_pool_absent.json +ansible_collections/infinidat/infinibox/tests/hacking/infini_pool_present.json +ansible_collections/infinidat/infinibox/tests/hacking/infini_pool_stat.json ansible_collections/infinidat/infinibox/tests/hacking/infini_sso_absent.json ansible_collections/infinidat/infinibox/tests/hacking/infini_sso_present.json +ansible_collections/infinidat/infinibox/tests/hacking/infini_sso_present_1521.json +ansible_collections/infinidat/infinibox/tests/hacking/infini_sso_present_vibox.json ansible_collections/infinidat/infinibox/tests/hacking/infini_sso_stat.json ansible_collections/infinidat/infinibox/tests/hacking/infini_user_absent.json ansible_collections/infinidat/infinibox/tests/hacking/infini_user_ldap_absent.json @@ -52541,7 +53136,6 @@ ansible_collections/netapp/ontap/.github/ISSUE_TEMPLATE/feature_request.yml ansible_collections/netapp/ontap/.github/workflows/codeql-analysis.yml ansible_collections/netapp/ontap/.github/workflows/coverage.yml ansible_collections/netapp/ontap/.github/workflows/main.yml -ansible_collections/netapp/ontap/changelogs/.DS_Store ansible_collections/netapp/ontap/changelogs/.plugin-cache.yaml ansible_collections/netapp/ontap/changelogs/changelog.yaml ansible_collections/netapp/ontap/changelogs/config.yaml @@ -53011,6 +53605,7 @@ ansible_collections/netapp/ontap/changelogs/fragments/DEVOPS-6320.yaml ansible_collections/netapp/ontap/changelogs/fragments/DEVOPS-6330.yaml ansible_collections/netapp/ontap/changelogs/fragments/DEVOPS-6331.yaml ansible_collections/netapp/ontap/changelogs/fragments/DEVOPS-6341.yaml +ansible_collections/netapp/ontap/changelogs/fragments/DEVOPS-6356.yaml ansible_collections/netapp/ontap/changelogs/fragments/DEVOPS-6374.yaml ansible_collections/netapp/ontap/changelogs/fragments/DEVOPS-6386.yaml ansible_collections/netapp/ontap/changelogs/fragments/DEVOPS-6389.yaml @@ -53040,6 +53635,12 @@ ansible_collections/netapp/ontap/changelogs/fragments/DEVOPS-6667.yaml ansible_collections/netapp/ontap/changelogs/fragments/DEVOPS-6671.yaml ansible_collections/netapp/ontap/changelogs/fragments/DEVOPS-6680.yaml ansible_collections/netapp/ontap/changelogs/fragments/DEVOPS-6681.yaml +ansible_collections/netapp/ontap/changelogs/fragments/DEVOPS-6691.yaml +ansible_collections/netapp/ontap/changelogs/fragments/DEVOPS-6715.yaml +ansible_collections/netapp/ontap/changelogs/fragments/DEVOPS-6721.yaml +ansible_collections/netapp/ontap/changelogs/fragments/DEVOPS-6747.yaml +ansible_collections/netapp/ontap/changelogs/fragments/DEVOPS-6807.yaml +ansible_collections/netapp/ontap/changelogs/fragments/DEVOPS-6825.yaml ansible_collections/netapp/ontap/changelogs/fragments/GITHUB-174.yaml ansible_collections/netapp/ontap/changelogs/fragments/github-110.yaml ansible_collections/netapp/ontap/changelogs/fragments/github-56.yaml @@ -53503,12 +54104,6 @@ ansible_collections/netapp/ontap/tests/unit/plugins/modules/test_na_ontap_wait_f ansible_collections/netapp/ontap/tests/unit/plugins/modules/test_na_ontap_wwpn_alias.py ansible_collections/netapp/ontap/tests/unit/plugins/modules/test_na_ontap_zapit.py ansible_collections/netapp/ontap/tests/unit/plugins/modules/test_ontap_fdspt.py -ansible_collections/netapp/ontap/tests/unit/plugins/modules/.pytest_cache/.gitignore -ansible_collections/netapp/ontap/tests/unit/plugins/modules/.pytest_cache/CACHEDIR.TAG -ansible_collections/netapp/ontap/tests/unit/plugins/modules/.pytest_cache/README.md -ansible_collections/netapp/ontap/tests/unit/plugins/modules/.pytest_cache/v/cache/lastfailed -ansible_collections/netapp/ontap/tests/unit/plugins/modules/.pytest_cache/v/cache/nodeids -ansible_collections/netapp/ontap/tests/unit/plugins/modules/.pytest_cache/v/cache/stepwise ansible_collections/netapp/storagegrid/CHANGELOG.rst ansible_collections/netapp/storagegrid/COPYING ansible_collections/netapp/storagegrid/FILES.json @@ -55718,6 +56313,10 @@ ansible_collections/purestorage/flashblade/changelogs/fragments/258_add_public_b ansible_collections/purestorage/flashblade/changelogs/fragments/263_fix_multiple_modules_idempotency.yaml ansible_collections/purestorage/flashblade/changelogs/fragments/266_bucket_fix.yaml ansible_collections/purestorage/flashblade/changelogs/fragments/268_multi-chassis-lag.yaml +ansible_collections/purestorage/flashblade/changelogs/fragments/270_add_go.yaml +ansible_collections/purestorage/flashblade/changelogs/fragments/271_add_worm.yaml +ansible_collections/purestorage/flashblade/changelogs/fragments/273_add_nap.yaml +ansible_collections/purestorage/flashblade/changelogs/fragments/274_fan_in.yaml ansible_collections/purestorage/flashblade/changelogs/fragments/76_default_fs_size.yaml ansible_collections/purestorage/flashblade/changelogs/fragments/77_filesystem_policies_info.yaml ansible_collections/purestorage/flashblade/changelogs/fragments/78_update_filesystem_replica_link.yaml diff --git a/ansible.egg-info/requires.txt b/ansible.egg-info/requires.txt index ff4a01d1f..5d89f30f2 100644 --- a/ansible.egg-info/requires.txt +++ b/ansible.egg-info/requires.txt @@ -1 +1 @@ -ansible-core~=2.16.5 +ansible-core~=2.16.6 diff --git a/ansible_collections/amazon/aws/.github/workflows/docs-pr.yml b/ansible_collections/amazon/aws/.github/workflows/docs-pr.yml index 8cc39d8f5..9158b038f 100644 --- a/ansible_collections/amazon/aws/.github/workflows/docs-pr.yml +++ b/ansible_collections/amazon/aws/.github/workflows/docs-pr.yml @@ -21,6 +21,7 @@ jobs: intersphinx-links: | community_aws:https://ansible-collections.github.io/community.aws/branch/main/ ansible_devel:https://docs.ansible.com/ansible-core/devel/ + artifact-name: ${{ github.event.repository.name }}_validate_docs_${{ github.event.pull_request.head.sha }} build-docs: diff --git a/ansible_collections/amazon/aws/CHANGELOG.rst b/ansible_collections/amazon/aws/CHANGELOG.rst index 3e5dc1c2c..219d962b4 100644 --- a/ansible_collections/amazon/aws/CHANGELOG.rst +++ b/ansible_collections/amazon/aws/CHANGELOG.rst @@ -4,6 +4,27 @@ amazon.aws Release Notes .. contents:: Topics +v7.5.0 +====== + +Release Summary +--------------- + +This release includes a new feature for the ``iam_user_info`` module, bugfixes for the ``cloudwatchlogs_log_group_info`` and ``s3_object`` modules and the inventory plugins, and some internal refactoring of ``module_utils``. + +Minor Changes +------------- + +- iam_user_info - Add ``login_profile`` to return info that is get from a user, to know if they can login from AWS console (https://github.com/ansible-collections/amazon.aws/pull/2012). +- module_utils.iam - refactored normalization functions to use ``boto3_resource_to_ansible_dict()`` and ``boto3_resource_list_to_ansible_dict()`` (https://github.com/ansible-collections/amazon.aws/pull/2006). +- module_utils.transformations - add ``boto3_resource_to_ansible_dict()`` and ``boto3_resource_list_to_ansible_dict()`` helpers (https://github.com/ansible-collections/amazon.aws/pull/2006). + +Bugfixes +-------- + +- cloudwatchlogs_log_group_info - Implement exponential backoff when making API calls to prevent throttling exceptions (https://github.com/ansible-collections/amazon.aws/issues/2011). +- plugin_utils.inventory - Ensure templated options in lookup plugins are converted (https://github.com/ansible-collections/amazon.aws/issues/1955). +- s3_object - Fix the issue when copying an object with overriding metadata. (https://github.com/ansible-collections/amazon.aws/issues/1991). v7.4.0 ====== @@ -232,7 +253,6 @@ Release Summary This release is the last planned minor release of ``amazon.aws`` prior to the release of 7.0.0. It includes documentation fixes as well as minor changes and bug fixes for the ``ec2_ami`` and ``elb_application_lb_info`` modules. - Minor Changes ------------- @@ -564,7 +584,6 @@ Release Summary This release brings few bugfixes. - Bugfixes -------- @@ -585,7 +604,6 @@ Release Summary This release contains a number of bugfixes, new features and new modules. This is the last planned minor release prior to the release of version 6.0.0. - Minor Changes ------------- @@ -680,7 +698,6 @@ Release Summary A minor release containing bugfixes for the ``ec2_eni_info`` module and the ``aws_rds`` inventory plugin, as well as improvements to the ``rds_instance`` module. - Minor Changes ------------- @@ -904,7 +921,6 @@ Release Summary This release contains a minor bugfix for the ``ec2_vol`` module, some minor work on the ``ec2_key`` module, and various documentation fixes. This is the last planned release of the 4.x series. - Minor Changes ------------- @@ -944,7 +960,6 @@ The amazon.aws 4.3.0 release includes a number of minor bug fixes and improvemen Following the release of amazon.aws 5.0.0, backports to the 4.x series will be limited to security issues and bugfixes. - Minor Changes ------------- @@ -1099,7 +1114,6 @@ Release Summary Following the release of amazon.aws 5.0.0, 3.5.0 is a bugfix release and the final planned release for the 3.x series. - Minor Changes ------------- diff --git a/ansible_collections/amazon/aws/FILES.json b/ansible_collections/amazon/aws/FILES.json index 1f9947ab7..61352c6b6 100644 --- a/ansible_collections/amazon/aws/FILES.json +++ b/ansible_collections/amazon/aws/FILES.json @@ -123,7 +123,7 @@ "name": ".github/workflows/docs-pr.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "befbd2d31f5509f704e57c06b07c42fa7867dd353ab3d24856eb865cf8d44b00", + "chksum_sha256": "12f439dd44738a38b1468b670158eaf719539b91f0570d2b9a2f0565ef1de659", "format": 1 }, { @@ -221,7 +221,7 @@ "name": "changelogs/changelog.yaml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "8484f733ac3da28af9d97a0f85ecc2f3d601009ed6d55d02f8a3cac6dc32eea9", + "chksum_sha256": "fab623a9b576e9d450f5285c5ad77eed36f30882a396eeba97046f4b8fdbf3cd", "format": 1 }, { @@ -256,7 +256,7 @@ "name": "docs/docsite/rst/CHANGELOG.rst", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "b3a5af02bc807a9248c3820f9f07c6ce0fbf5f75f22613ae3e79a795d34165fc", + "chksum_sha256": "f60899f9e09f217d9c8963676ddad7d070ce9233e0f32c02b96ad1839ec3cd9f", "format": 1 }, { @@ -543,7 +543,7 @@ "name": "plugins/module_utils/common.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "c2056cf9ef583ee29ac1165aa03e5cf165830ed6d1703c275c4c9d154222f3c3", + "chksum_sha256": "cef7b396d560a646961755d2a54c7131e553dfe26fbb26e04be073cce5bb0095", "format": 1 }, { @@ -599,7 +599,7 @@ "name": "plugins/module_utils/iam.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "8aaa38e784250525c884b936370b2db5ff61b84fcd62a30c239a5e3dc8e20ca3", + "chksum_sha256": "1cd5d5532049e4afd2858a35480cd173f72c4ed9174c67bb26186e47fe183ba5", "format": 1 }, { @@ -662,7 +662,7 @@ "name": "plugins/module_utils/transformation.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "77e7b561643de0ed96b958af3ec6694edae360c8fb4e51ffa4144dace02063fe", + "chksum_sha256": "882308fe4ef2b74fcb41dd09b0e6575d47e2f3d6a3f2164d8dc1706cec213f0c", "format": 1 }, { @@ -851,7 +851,7 @@ "name": "plugins/modules/cloudwatchlogs_log_group_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "00a40c6593d6cc582205943f247a33d7621e4ffa49410c9476e6fefc4e800ccd", + "chksum_sha256": "03d947455d91f77a833dd705fc05d2882a62786e1e09968f7cc8b668964d56f6", "format": 1 }, { @@ -1243,7 +1243,7 @@ "name": "plugins/modules/iam_user_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "92d2d3f21e43a53f4e25ed497c76d2935ed533b8bdbf9aa5af41a4a8c27e2cb7", + "chksum_sha256": "11b3a159e2c6542b861c94c5d5f1eae8375f1e0e4ecef7ad413932254f6a3157", "format": 1 }, { @@ -1446,7 +1446,7 @@ "name": "plugins/modules/s3_object.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "36bf675910b9b5a9a932fc90c1ceb4f2c54d90a191bf9c2cb8a47cd5ebea032f", + "chksum_sha256": "47610c1c778b26def1d5c3aef8c5f6d2089537445ae420d1da5f1afb4a0b8600", "format": 1 }, { @@ -1495,7 +1495,7 @@ "name": "plugins/plugin_utils/inventory.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "1c652b1e2733fe92f7d95ea6f76bed638fbed402e7ffe15753e896328869f4b3", + "chksum_sha256": "2bbe05440920c867bd4b8935a0a97963211b74149ca6c83d9990f9b6a5e4e6ae", "format": 1 }, { @@ -2531,7 +2531,7 @@ "name": "tests/integration/targets/ec2_ami/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "9433c585f807cca76bb83c1cbe0a5d0a85966ead2ca30dde4cefd71be3cf155f", + "chksum_sha256": "919ee94ad149f90556ea20402e2393253157946b2d0e32a71957a4f58cfa6018", "format": 1 }, { @@ -4302,7 +4302,7 @@ "name": "tests/integration/targets/ec2_security_group/tasks/multi_nested_target.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "be781072f2d349ec5c93cbb05e40ef71846d2f4b5884ad297a736d3b0c72e542", + "chksum_sha256": "79aa1549464410bff8ff9f0272780d8b408a370d088100617656975024b6fef2", "format": 1 }, { @@ -6115,7 +6115,7 @@ "name": "tests/integration/targets/inventory_aws_ec2/playbooks/create_inventory_config.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "c031a3d0f6a2c17914bedc3a7b37c475cbd55420cb7ae7fe4c6f24855bb5565d", + "chksum_sha256": "44bab5285a394bde857e65e324b15039d248a20c9a05b5eec45eac2ce312550e", "format": 1 }, { @@ -6258,6 +6258,13 @@ "chksum_sha256": null, "format": 1 }, + { + "name": "tests/integration/targets/inventory_aws_ec2/templates/config.ini.j2", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "777e02f32a471e59d05fc66ef26716aaaa368085f991f179866d8f38a7d44aae", + "format": 1 + }, { "name": "tests/integration/targets/inventory_aws_ec2/templates/inventory.yml.j2", "ftype": "file", @@ -6332,7 +6339,7 @@ "name": "tests/integration/targets/inventory_aws_ec2/templates/inventory_with_template.yml.j2", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "156031d22e1ae780ea2012e96afd68679bd27ee0cfe4bec4b03bf556f5477375", + "chksum_sha256": "a15b10d8b1dc85d869d6df0054d44d95b68d53d5cda6c9372dc86d72e260a00d", "format": 1 }, { @@ -9447,7 +9454,7 @@ "name": "tests/integration/targets/s3_object/tasks/copy_object.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "9b412470d4ef414efef1f407f84c72f1685f77c6ef2551517cdfa4cd6ab1515d", + "chksum_sha256": "a935fc78dc9973eac71decd7308d4e827c27a7f30b29c7c416f9f676163b4ec7", "format": 1 }, { @@ -9475,7 +9482,7 @@ "name": "tests/integration/targets/s3_object/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "c7568cf168c02a65bef0d921cea02304fd568fa6cd93175395bed359e6a14cf7", + "chksum_sha256": "697d66379fe4c4b33f82b1f7ac363f1e25331480201701b23d28494165346043", "format": 1 }, { @@ -9503,7 +9510,7 @@ "name": "tests/integration/targets/s3_object/aliases", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "da6542f9ffbf6dfd96214cc7e7c08e8bd4662a5479a21ad1b3f79ad2b163c9ad", + "chksum_sha256": "e217807ba499d974106cc2132230a411f7564e6c337b0a731a6301c5a1d69619", "format": 1 }, { @@ -10283,6 +10290,13 @@ "chksum_sha256": "4d0eec99fb5fd1925ff03c05e02bd88abbd9f28f9a3c9e989c13d33d6c52dc93", "format": 1 }, + { + "name": "tests/unit/module_utils/iam/test_iam_resource_transforms.py", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "9ba95e45f5d2c2502a8ae6ea6dacc35e340f931a4d4d7fde2064ba0f89018ed0", + "format": 1 + }, { "name": "tests/unit/module_utils/iam/test_validate_iam_identifiers.py", "ftype": "file", @@ -10451,6 +10465,13 @@ "chksum_sha256": "650e6766b2490ddb566fc662b629975c3bd977c5754b6946a15161842953a076", "format": 1 }, + { + "name": "tests/unit/module_utils/transformation/test_boto3_resource_to_ansible_dict.py", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "8b27e0ccb712e9bf43897b4226b99318c42e27f344f660326d13699bf1b45c45", + "format": 1 + }, { "name": "tests/unit/module_utils/transformation/test_map_complex_type.py", "ftype": "file", @@ -10630,7 +10651,7 @@ "name": "tests/unit/plugin_utils/inventory/test_inventory_base.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "4668d08e6f30a2aae02c0b27174dc759f4ec554d7207bcf33f879e9dee67720e", + "chksum_sha256": "ebae64f9db5ec8444c35b5d41127f1a5191ed10cd34acb6c89d0e5de2879b33d", "format": 1 }, { @@ -10693,7 +10714,7 @@ "name": "tests/unit/plugins/inventory/test_aws_ec2.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "cbb0ce6de6b22c4d62588d230353de215a4ccb273838b4870c17da8548ad3f16", + "chksum_sha256": "8556d8258e0d0aaeadd02898d1198152c478fa23677ff51990a0e1420f99e482", "format": 1 }, { @@ -11659,7 +11680,7 @@ "name": "CHANGELOG.rst", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "b3a5af02bc807a9248c3820f9f07c6ce0fbf5f75f22613ae3e79a795d34165fc", + "chksum_sha256": "f60899f9e09f217d9c8963676ddad7d070ce9233e0f32c02b96ad1839ec3cd9f", "format": 1 }, { diff --git a/ansible_collections/amazon/aws/MANIFEST.json b/ansible_collections/amazon/aws/MANIFEST.json index 3eb50b454..cd19577e3 100644 --- a/ansible_collections/amazon/aws/MANIFEST.json +++ b/ansible_collections/amazon/aws/MANIFEST.json @@ -2,7 +2,7 @@ "collection_info": { "namespace": "amazon", "name": "aws", - "version": "7.4.0", + "version": "7.5.0", "authors": [ "Ansible (https://github.com/ansible)" ], @@ -25,7 +25,7 @@ "name": "FILES.json", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "524e7534581a787eb78ed1366e0d732b0673fcb3e4b5df5ffae1ca6c92c0ffe5", + "chksum_sha256": "34bdeb6686c662a0a524953b80ae953b67d328542ba5d43bc1e4058c45ed4136", "format": 1 }, "format": 1 diff --git a/ansible_collections/amazon/aws/changelogs/changelog.yaml b/ansible_collections/amazon/aws/changelogs/changelog.yaml index 24f7b8247..587c55a28 100644 --- a/ansible_collections/amazon/aws/changelogs/changelog.yaml +++ b/ansible_collections/amazon/aws/changelogs/changelog.yaml @@ -2692,7 +2692,7 @@ releases: - iam_user_info - the ``path`` parameter has been renamed ``path_prefix`` for consistency with other IAM modules, ``path`` remains as an alias. No change to playbooks is required (https://github.com/ansible-collections/amazon.aws/pull/1933). - release_summary: This release includes new features and a bugfix. + release_summary: This release includes new features and a bugfix. fragments: - 1918-ec2_instance-add-support-to-modify-metadata-options.yml - 20231206-iam_user_path.yml @@ -2777,3 +2777,28 @@ releases: - 20240227-iam-refactor.yml - release_summary.yml release_date: '2024-03-05' + 7.5.0: + changes: + bugfixes: + - cloudwatchlogs_log_group_info - Implement exponential backoff when making + API calls to prevent throttling exceptions (https://github.com/ansible-collections/amazon.aws/issues/2011). + - plugin_utils.inventory - Ensure templated options in lookup plugins are converted + (https://github.com/ansible-collections/amazon.aws/issues/1955). + - s3_object - Fix the issue when copying an object with overriding metadata. + (https://github.com/ansible-collections/amazon.aws/issues/1991). + minor_changes: + - iam_user_info - Add ``login_profile`` to return info that is get from a user, + to know if they can login from AWS console (https://github.com/ansible-collections/amazon.aws/pull/2012). + - module_utils.iam - refactored normalization functions to use ``boto3_resource_to_ansible_dict()`` + and ``boto3_resource_list_to_ansible_dict()`` (https://github.com/ansible-collections/amazon.aws/pull/2006). + - module_utils.transformations - add ``boto3_resource_to_ansible_dict()`` and + ``boto3_resource_list_to_ansible_dict()`` helpers (https://github.com/ansible-collections/amazon.aws/pull/2006). + release_summary: This release includes a new feature for the ``iam_user_info`` + module, bugfixes for the ``cloudwatchlogs_log_group_info`` and ``s3_object`` + modules and the inventory plugins, and some internal refactoring of ``module_utils``. + fragments: + - 2006-normalize-refactor.yml + - 20240314-cloudwatchlogs_log_group_info-fix-throttling-exceptions.yml + - 20240314-s3_object-copy-mode-with-metadata.yml + - 20240321-iam-user-info.yml + release_date: '2024-04-03' diff --git a/ansible_collections/amazon/aws/docs/docsite/rst/CHANGELOG.rst b/ansible_collections/amazon/aws/docs/docsite/rst/CHANGELOG.rst index 3e5dc1c2c..219d962b4 100644 --- a/ansible_collections/amazon/aws/docs/docsite/rst/CHANGELOG.rst +++ b/ansible_collections/amazon/aws/docs/docsite/rst/CHANGELOG.rst @@ -4,6 +4,27 @@ amazon.aws Release Notes .. contents:: Topics +v7.5.0 +====== + +Release Summary +--------------- + +This release includes a new feature for the ``iam_user_info`` module, bugfixes for the ``cloudwatchlogs_log_group_info`` and ``s3_object`` modules and the inventory plugins, and some internal refactoring of ``module_utils``. + +Minor Changes +------------- + +- iam_user_info - Add ``login_profile`` to return info that is get from a user, to know if they can login from AWS console (https://github.com/ansible-collections/amazon.aws/pull/2012). +- module_utils.iam - refactored normalization functions to use ``boto3_resource_to_ansible_dict()`` and ``boto3_resource_list_to_ansible_dict()`` (https://github.com/ansible-collections/amazon.aws/pull/2006). +- module_utils.transformations - add ``boto3_resource_to_ansible_dict()`` and ``boto3_resource_list_to_ansible_dict()`` helpers (https://github.com/ansible-collections/amazon.aws/pull/2006). + +Bugfixes +-------- + +- cloudwatchlogs_log_group_info - Implement exponential backoff when making API calls to prevent throttling exceptions (https://github.com/ansible-collections/amazon.aws/issues/2011). +- plugin_utils.inventory - Ensure templated options in lookup plugins are converted (https://github.com/ansible-collections/amazon.aws/issues/1955). +- s3_object - Fix the issue when copying an object with overriding metadata. (https://github.com/ansible-collections/amazon.aws/issues/1991). v7.4.0 ====== @@ -232,7 +253,6 @@ Release Summary This release is the last planned minor release of ``amazon.aws`` prior to the release of 7.0.0. It includes documentation fixes as well as minor changes and bug fixes for the ``ec2_ami`` and ``elb_application_lb_info`` modules. - Minor Changes ------------- @@ -564,7 +584,6 @@ Release Summary This release brings few bugfixes. - Bugfixes -------- @@ -585,7 +604,6 @@ Release Summary This release contains a number of bugfixes, new features and new modules. This is the last planned minor release prior to the release of version 6.0.0. - Minor Changes ------------- @@ -680,7 +698,6 @@ Release Summary A minor release containing bugfixes for the ``ec2_eni_info`` module and the ``aws_rds`` inventory plugin, as well as improvements to the ``rds_instance`` module. - Minor Changes ------------- @@ -904,7 +921,6 @@ Release Summary This release contains a minor bugfix for the ``ec2_vol`` module, some minor work on the ``ec2_key`` module, and various documentation fixes. This is the last planned release of the 4.x series. - Minor Changes ------------- @@ -944,7 +960,6 @@ The amazon.aws 4.3.0 release includes a number of minor bug fixes and improvemen Following the release of amazon.aws 5.0.0, backports to the 4.x series will be limited to security issues and bugfixes. - Minor Changes ------------- @@ -1099,7 +1114,6 @@ Release Summary Following the release of amazon.aws 5.0.0, 3.5.0 is a bugfix release and the final planned release for the 3.x series. - Minor Changes ------------- diff --git a/ansible_collections/amazon/aws/plugins/module_utils/common.py b/ansible_collections/amazon/aws/plugins/module_utils/common.py index 673915725..41ba80231 100644 --- a/ansible_collections/amazon/aws/plugins/module_utils/common.py +++ b/ansible_collections/amazon/aws/plugins/module_utils/common.py @@ -4,7 +4,7 @@ # GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) AMAZON_AWS_COLLECTION_NAME = "amazon.aws" -AMAZON_AWS_COLLECTION_VERSION = "7.4.0" +AMAZON_AWS_COLLECTION_VERSION = "7.5.0" _collection_info_context = { diff --git a/ansible_collections/amazon/aws/plugins/module_utils/iam.py b/ansible_collections/amazon/aws/plugins/module_utils/iam.py index 430823f3b..56920d53e 100644 --- a/ansible_collections/amazon/aws/plugins/module_utils/iam.py +++ b/ansible_collections/amazon/aws/plugins/module_utils/iam.py @@ -4,7 +4,6 @@ # GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) import re -from copy import deepcopy try: import botocore @@ -12,17 +11,20 @@ except ImportError: pass # Modules are responsible for handling this. from ansible.module_utils._text import to_native -from ansible.module_utils.common.dict_transformations import camel_dict_to_snake_dict from .arn import parse_aws_arn from .arn import validate_aws_arn from .botocore import is_boto3_error_code -from .botocore import normalize_boto3_result from .errors import AWSErrorHandler from .exceptions import AnsibleAWSError from .retries import AWSRetry from .tagging import ansible_dict_to_boto3_tag_list -from .tagging import boto3_tag_list_to_ansible_dict +from .transformation import AnsibleAWSResource +from .transformation import AnsibleAWSResourceList +from .transformation import BotoResource +from .transformation import BotoResourceList +from .transformation import boto3_resource_list_to_ansible_dict +from .transformation import boto3_resource_to_ansible_dict class AnsibleIAMError(AnsibleAWSError): @@ -198,66 +200,6 @@ def get_iam_managed_policy_version(client, arn, version): return client.get_policy_version(PolicyArn=arn, VersionId=version)["PolicyVersion"] -def normalize_iam_mfa_device(device): - """Converts IAM MFA Device from the CamelCase boto3 format to the snake_case Ansible format""" - if not device: - return device - camel_device = camel_dict_to_snake_dict(device) - camel_device["tags"] = boto3_tag_list_to_ansible_dict(device.pop("Tags", [])) - return camel_device - - -def normalize_iam_mfa_devices(devices): - """Converts a list of IAM MFA Devices from the CamelCase boto3 format to the snake_case Ansible format""" - if not devices: - return [] - devices = [normalize_iam_mfa_device(d) for d in devices] - return devices - - -def normalize_iam_user(user): - """Converts IAM users from the CamelCase boto3 format to the snake_case Ansible format""" - if not user: - return user - camel_user = camel_dict_to_snake_dict(user) - camel_user["tags"] = boto3_tag_list_to_ansible_dict(user.pop("Tags", [])) - return camel_user - - -def normalize_iam_policy(policy): - """Converts IAM policies from the CamelCase boto3 format to the snake_case Ansible format""" - if not policy: - return policy - camel_policy = camel_dict_to_snake_dict(policy) - camel_policy["tags"] = boto3_tag_list_to_ansible_dict(policy.get("Tags", [])) - return camel_policy - - -def normalize_iam_group(group): - """Converts IAM Groups from the CamelCase boto3 format to the snake_case Ansible format""" - if not group: - return group - camel_group = camel_dict_to_snake_dict(normalize_boto3_result(group)) - return camel_group - - -def normalize_iam_access_key(access_key): - """Converts IAM access keys from the CamelCase boto3 format to the snake_case Ansible format""" - if not access_key: - return access_key - camel_key = camel_dict_to_snake_dict(normalize_boto3_result(access_key)) - return camel_key - - -def normalize_iam_access_keys(access_keys): - """Converts a list of IAM access keys from the CamelCase boto3 format to the snake_case Ansible format""" - if not access_keys: - return [] - access_keys = [normalize_iam_access_key(k) for k in access_keys] - sorted_keys = sorted(access_keys, key=lambda d: d.get("create_date", None)) - return sorted_keys - - def convert_managed_policy_names_to_arns(client, policy_names): if all(validate_aws_arn(policy, service="iam") for policy in policy_names if policy is not None): return policy_names @@ -386,47 +328,6 @@ def list_iam_instance_profiles(client, name=None, prefix=None, role=None): return _list_iam_instance_profiles(client) -def normalize_iam_instance_profile(profile, _v7_compat=False): - """ - Converts a boto3 format IAM instance profile into "Ansible" format - - _v7_compat is deprecated and will be removed in release after 2025-05-01 DO NOT USE. - """ - - new_profile = camel_dict_to_snake_dict(deepcopy(profile)) - if profile.get("Roles"): - new_profile["roles"] = [normalize_iam_role(role, _v7_compat=_v7_compat) for role in profile.get("Roles")] - if profile.get("Tags"): - new_profile["tags"] = boto3_tag_list_to_ansible_dict(profile.get("Tags")) - else: - new_profile["tags"] = {} - new_profile["original"] = profile - return new_profile - - -def normalize_iam_role(role, _v7_compat=False): - """ - Converts a boto3 format IAM instance role into "Ansible" format - - _v7_compat is deprecated and will be removed in release after 2025-05-01 DO NOT USE. - """ - - new_role = camel_dict_to_snake_dict(deepcopy(role)) - if role.get("InstanceProfiles"): - new_role["instance_profiles"] = [ - normalize_iam_instance_profile(profile, _v7_compat=_v7_compat) for profile in role.get("InstanceProfiles") - ] - if role.get("AssumeRolePolicyDocument"): - if _v7_compat: - # new_role["assume_role_policy_document"] = role.get("AssumeRolePolicyDocument") - new_role["assume_role_policy_document_raw"] = role.get("AssumeRolePolicyDocument") - else: - new_role["assume_role_policy_document"] = role.get("AssumeRolePolicyDocument") - - new_role["tags"] = boto3_tag_list_to_ansible_dict(role.get("Tags", [])) - return new_role - - @IAMErrorHandler.common_error_handler("tag instance profile") @AWSRetry.jittered_backoff() def tag_iam_instance_profile(client, name, tags): @@ -497,3 +398,83 @@ def validate_iam_identifiers(resource_type, name=None, path=None): return path_problem return None + + +def normalize_iam_mfa_device(device: BotoResource) -> AnsibleAWSResource: + """Converts IAM MFA Device from the CamelCase boto3 format to the snake_case Ansible format""" + # MFA Devices don't support Tags (as of 1.34.52) + return boto3_resource_to_ansible_dict(device) + + +def normalize_iam_mfa_devices(devices: BotoResourceList) -> AnsibleAWSResourceList: + """Converts a list of IAM MFA Devices from the CamelCase boto3 format to the snake_case Ansible format""" + # MFA Devices don't support Tags (as of 1.34.52) + return boto3_resource_list_to_ansible_dict(devices) + + +def normalize_iam_user(user: BotoResource) -> AnsibleAWSResource: + """Converts IAM users from the CamelCase boto3 format to the snake_case Ansible format""" + return boto3_resource_to_ansible_dict(user) + + +def normalize_iam_policy(policy: BotoResource) -> AnsibleAWSResource: + """Converts IAM policies from the CamelCase boto3 format to the snake_case Ansible format""" + return boto3_resource_to_ansible_dict(policy) + + +def normalize_iam_group(group: BotoResource) -> AnsibleAWSResource: + """Converts IAM Groups from the CamelCase boto3 format to the snake_case Ansible format""" + # Groups don't support Tags (as of 1.34.52) + return boto3_resource_to_ansible_dict(group, force_tags=False) + + +def normalize_iam_access_key(access_key: BotoResource) -> AnsibleAWSResource: + """Converts IAM access keys from the CamelCase boto3 format to the snake_case Ansible format""" + # Access Keys don't support Tags (as of 1.34.52) + return boto3_resource_to_ansible_dict(access_key, force_tags=False) + + +def normalize_iam_access_keys(access_keys: BotoResourceList) -> AnsibleAWSResourceList: + """Converts a list of IAM access keys from the CamelCase boto3 format to the snake_case Ansible format""" + # Access Keys don't support Tags (as of 1.34.52) + if not access_keys: + return access_keys + access_keys = boto3_resource_list_to_ansible_dict(access_keys, force_tags=False) + return sorted(access_keys, key=lambda d: d.get("create_date", None)) + + +def normalize_iam_instance_profile(profile: BotoResource) -> AnsibleAWSResource: + """ + Converts a boto3 format IAM instance profile into "Ansible" format + + _v7_compat is deprecated and will be removed in release after 2025-05-01 DO NOT USE. + """ + transforms = {"Roles": _normalize_iam_roles} + transformed_profile = boto3_resource_to_ansible_dict(profile, nested_transforms=transforms) + return transformed_profile + + +def normalize_iam_role(role: BotoResource, _v7_compat: bool = False) -> AnsibleAWSResource: + """ + Converts a boto3 format IAM instance role into "Ansible" format + + _v7_compat is deprecated and will be removed in release after 2025-05-01 DO NOT USE. + """ + transforms = {"InstanceProfiles": _normalize_iam_instance_profiles} + ignore_list = [] if _v7_compat else ["AssumeRolePolicyDocument"] + transformed_role = boto3_resource_to_ansible_dict(role, nested_transforms=transforms, ignore_list=ignore_list) + if _v7_compat and role.get("AssumeRolePolicyDocument"): + transformed_role["assume_role_policy_document_raw"] = role["AssumeRolePolicyDocument"] + return transformed_role + + +def _normalize_iam_instance_profiles(profiles: BotoResourceList) -> AnsibleAWSResourceList: + if not profiles: + return profiles + return [normalize_iam_instance_profile(p) for p in profiles] + + +def _normalize_iam_roles(roles: BotoResourceList) -> AnsibleAWSResourceList: + if not roles: + return roles + return [normalize_iam_role(r) for r in roles] diff --git a/ansible_collections/amazon/aws/plugins/module_utils/transformation.py b/ansible_collections/amazon/aws/plugins/module_utils/transformation.py index 708736fc0..a5bc23607 100644 --- a/ansible_collections/amazon/aws/plugins/module_utils/transformation.py +++ b/ansible_collections/amazon/aws/plugins/module_utils/transformation.py @@ -28,9 +28,26 @@ # 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 copy import deepcopy +from typing import Any +from typing import Callable +from typing import Mapping +from typing import Optional +from typing import Sequence +from typing import Union + +from ansible.module_utils.common.dict_transformations import camel_dict_to_snake_dict from ansible.module_utils.six import integer_types from ansible.module_utils.six import string_types +from .botocore import normalize_boto3_result +from .tagging import boto3_tag_list_to_ansible_dict + +BotoResource = Union[None, Mapping[str, Any]] +BotoResourceList = Union[None, Sequence[Mapping[str, Any]]] +AnsibleAWSResource = Union[None, Mapping[str, Any]] +AnsibleAWSResourceList = Union[None, Sequence[Mapping[str, Any]]] + def ansible_dict_to_boto3_filter_list(filters_dict): """Convert an Ansible dict of filters to list of dicts that boto3 can use @@ -133,3 +150,82 @@ def scrub_none_parameters(parameters, descend_into_lists=True): clean_parameters[k] = v return clean_parameters + + +def _perform_nested_transforms( + resource: Mapping[str, Any], + nested_transforms: Optional[Mapping[str, Callable]], +) -> Mapping[str, Any]: + if not nested_transforms: + return resource + + for k, transform in nested_transforms.items(): + if k in resource: + resource[k] = transform(resource[k]) + + return resource + + +def boto3_resource_to_ansible_dict( + resource: BotoResource, + transform_tags: bool = True, + force_tags: bool = True, + normalize: bool = True, + ignore_list: Optional[Sequence[str]] = None, + nested_transforms: Optional[Mapping[str, Callable]] = None, +) -> AnsibleAWSResource: + """ + Transforms boto3-style (CamelCase) resource to the ansible-style (snake_case). + + :param resource: a dictionary representing the resource + :param transform_tags: whether or not to perform "tag list" to "dictionary" conversion on the "Tags" key + :param normalize: whether resources should be passed through .botocore.normalize_boto3_result + :param ignore_list: a list of keys, the contents of which should not be transformed + :param nested_transforms: a mapping of keys to Callable, the Callable will only be passed the value for the key + in the resource dictionary + :return: dictionary representing the transformed resource + """ + if not resource: + return resource + ignore_list = ignore_list or [] + nested_transforms = nested_transforms or {} + + transformed_resource = deepcopy(resource) + if normalize: + transformed_resource = normalize_boto3_result(transformed_resource) + transformed_resource = _perform_nested_transforms(transformed_resource, nested_transforms) + ignore_list = [*ignore_list, *nested_transforms] + camel_resource = camel_dict_to_snake_dict(transformed_resource, ignore_list=ignore_list) + if transform_tags and "Tags" in resource: + camel_resource["tags"] = boto3_tag_list_to_ansible_dict(resource["Tags"]) + if force_tags and "Tags" not in resource: + camel_resource["tags"] = {} + + return camel_resource + + +def boto3_resource_list_to_ansible_dict( + resource_list: BotoResourceList, + transform_tags: bool = True, + force_tags: bool = True, + normalize: bool = True, + ignore_list: Optional[Sequence[str]] = None, + nested_transforms: Optional[Mapping[str, Callable]] = None, +) -> AnsibleAWSResourceList: + """ + Transforms a list of boto3-style (CamelCase) resources to the ansible-style (snake_case). + + :param resource_list: a list of dictionaries representing the resources + :param transform_tags: whether or not to perform "tag list" to "dictionary" conversion on the "Tags" key + :param normalize: whether resources should be passed through .botocore.normalize_boto3_result() + :param ignore_list: a list of keys, the contents of which should not be transformed + :param nested_transforms: a mapping of keys to Callable, the Callable will only be passed the value for the key + in the resource dictionary + :return: list of dictionaries representing the transformed resources + """ + if not resource_list: + return resource_list + return [ + boto3_resource_to_ansible_dict(resource, transform_tags, force_tags, normalize, ignore_list, nested_transforms) + for resource in resource_list + ] diff --git a/ansible_collections/amazon/aws/plugins/modules/cloudwatchlogs_log_group_info.py b/ansible_collections/amazon/aws/plugins/modules/cloudwatchlogs_log_group_info.py index 0cfe22e22..453d268d5 100644 --- a/ansible_collections/amazon/aws/plugins/modules/cloudwatchlogs_log_group_info.py +++ b/ansible_collections/amazon/aws/plugins/modules/cloudwatchlogs_log_group_info.py @@ -82,6 +82,18 @@ from ansible.module_utils.common.dict_transformations import camel_dict_to_snake from ansible_collections.amazon.aws.plugins.module_utils.botocore import is_boto3_error_code from ansible_collections.amazon.aws.plugins.module_utils.modules import AnsibleAWSModule +from ansible_collections.amazon.aws.plugins.module_utils.retries import AWSRetry + + +@AWSRetry.exponential_backoff() +def list_tags_log_group_with_backoff(client, log_group_name): + return client.list_tags_log_group(logGroupName=log_group_name) + + +@AWSRetry.exponential_backoff() +def describe_log_groups_with_backoff(client, **kwargs): + paginator = client.get_paginator("describe_log_groups") + return paginator.paginate(**kwargs).build_full_result() def describe_log_group(client, log_group_name, module): @@ -89,15 +101,14 @@ def describe_log_group(client, log_group_name, module): if log_group_name: params["logGroupNamePrefix"] = log_group_name try: - paginator = client.get_paginator("describe_log_groups") - desc_log_group = paginator.paginate(**params).build_full_result() + desc_log_group = describe_log_groups_with_backoff(client, **params) except (botocore.exceptions.ClientError, botocore.exceptions.BotoCoreError) as e: module.fail_json_aws(e, msg=f"Unable to describe log group {log_group_name}") for log_group in desc_log_group["logGroups"]: log_group_name = log_group["logGroupName"] try: - tags = client.list_tags_log_group(logGroupName=log_group_name) + tags = list_tags_log_group_with_backoff(client, log_group_name) except is_boto3_error_code("AccessDeniedException"): tags = {} module.warn(f"Permission denied listing tags for log group {log_group_name}") diff --git a/ansible_collections/amazon/aws/plugins/modules/iam_user_info.py b/ansible_collections/amazon/aws/plugins/modules/iam_user_info.py index 259d26803..2ddbe1d5a 100644 --- a/ansible_collections/amazon/aws/plugins/modules/iam_user_info.py +++ b/ansible_collections/amazon/aws/plugins/modules/iam_user_info.py @@ -103,14 +103,27 @@ iam_users: type: dict returned: if user exists sample: '{"Env": "Prod"}' + login_profile: + description: Detailed login profile information if the user has access to log in from AWS default console. Returns an empty object {} if no access. + returned: always + type: dict + sample: {"create_date": "2024-03-20T12:50:56+00:00", "password_reset_required": false, "user_name": "i_am_a_user"} """ from ansible_collections.amazon.aws.plugins.module_utils.iam import AnsibleIAMError +from ansible_collections.amazon.aws.plugins.module_utils.iam import IAMErrorHandler from ansible_collections.amazon.aws.plugins.module_utils.iam import get_iam_group from ansible_collections.amazon.aws.plugins.module_utils.iam import get_iam_user from ansible_collections.amazon.aws.plugins.module_utils.iam import list_iam_users from ansible_collections.amazon.aws.plugins.module_utils.iam import normalize_iam_user from ansible_collections.amazon.aws.plugins.module_utils.modules import AnsibleAWSModule +from ansible_collections.amazon.aws.plugins.module_utils.retries import AWSRetry + + +@IAMErrorHandler.list_error_handler("get login profile", {}) +@AWSRetry.jittered_backoff() +def check_console_access(connection, user_name): + return connection.get_login_profile(UserName=user_name)["LoginProfile"] def _list_users(connection, name, group, path): @@ -136,6 +149,8 @@ def _list_users(connection, name, group, path): def list_users(connection, name, group, path): users = _list_users(connection, name, group, path) users = [u for u in users if u is not None] + for user in users: + user["LoginProfile"] = check_console_access(connection, user["UserName"]) return [normalize_iam_user(user) for user in users] @@ -147,7 +162,9 @@ def main(): ) module = AnsibleAWSModule( - argument_spec=argument_spec, mutually_exclusive=[["group", "path_prefix"]], supports_check_mode=True + argument_spec=argument_spec, + mutually_exclusive=[["group", "path_prefix"]], + supports_check_mode=True, ) name = module.params.get("name") diff --git a/ansible_collections/amazon/aws/plugins/modules/s3_object.py b/ansible_collections/amazon/aws/plugins/modules/s3_object.py index 2c4ebe9c3..2cd897c89 100644 --- a/ansible_collections/amazon/aws/plugins/modules/s3_object.py +++ b/ansible_collections/amazon/aws/plugins/modules/s3_object.py @@ -315,7 +315,9 @@ EXAMPLES = r""" object: /my/desired/key.txt src: /usr/local/myfile.txt mode: put - metadata: 'Content-Encoding=gzip,Cache-Control=no-cache' + metadata: + Content-Encoding: gzip + Cache-Control: no-cache - name: PUT/upload with custom headers amazon.aws.s3_object: @@ -1314,6 +1316,11 @@ def copy_object_to_bucket(module, s3, bucket, obj, encrypt, metadata, validate, metadata, ) ) + if metadata: + # 'MetadataDirective' Specifies whether the metadata is copied from the source object or replaced + # with metadata that's provided in the request. The default value is 'COPY', therefore when user + # specifies a metadata we should set it to 'REPLACE' + params.update({"MetadataDirective": "REPLACE"}) s3.copy_object(aws_retry=True, **params) put_object_acl(module, s3, bucket, obj) # Tags diff --git a/ansible_collections/amazon/aws/plugins/plugin_utils/inventory.py b/ansible_collections/amazon/aws/plugins/plugin_utils/inventory.py index 144f77a7a..b0e47f7ef 100644 --- a/ansible_collections/amazon/aws/plugins/plugin_utils/inventory.py +++ b/ansible_collections/amazon/aws/plugins/plugin_utils/inventory.py @@ -33,7 +33,10 @@ class AWSInventoryBase(BaseInventoryPlugin, Constructable, Cacheable, AWSPluginB "secret_key", "session_token", "profile", - "iam_role_name", + "endpoint_url", + "assume_role_arn", + "region", + "regions", ) def __init__(self, templar, options): @@ -48,20 +51,21 @@ class AWSInventoryBase(BaseInventoryPlugin, Constructable, Cacheable, AWSPluginB def get(self, *args): value = self.original_options.get(*args) - if not value: - return value - if args[0] not in self.TEMPLATABLE_OPTIONS: - return value - if not self.templar.is_template(value): + if ( + not value + or not self.templar + or args[0] not in self.TEMPLATABLE_OPTIONS + or not self.templar.is_template(value) + ): return value return self.templar.template(variable=value, disable_lookups=False) def get_options(self, *args): - original_options = super().get_options(*args) - if not self.templar: - return original_options - return self.TemplatedOptions(self.templar, original_options) + return self.TemplatedOptions(self.templar, super().get_options(*args)) + + def get_option(self, option, hostvars=None): + return self.TemplatedOptions(self.templar, {option: super().get_option(option, hostvars)}).get(option) def __init__(self): super().__init__() @@ -109,8 +113,7 @@ class AWSInventoryBase(BaseInventoryPlugin, Constructable, Cacheable, AWSPluginB } def _set_frozen_credentials(self): - options = self.get_options() - iam_role_arn = options.get("assume_role_arn") + iam_role_arn = self.get_option("assume_role_arn") if iam_role_arn: self._freeze_iam_role(iam_role_arn) @@ -136,10 +139,9 @@ class AWSInventoryBase(BaseInventoryPlugin, Constructable, Cacheable, AWSPluginB return None def _boto3_regions(self, service): - options = self.get_options() - - if options.get("regions"): - return options.get("regions") + regions = self.get_option("regions") + if regions: + return regions # boto3 has hard coded lists of available regions for resources, however this does bit-rot # As such we try to query the service, and fall back to ec2 for a list of regions @@ -149,7 +151,7 @@ class AWSInventoryBase(BaseInventoryPlugin, Constructable, Cacheable, AWSPluginB return regions # fallback to local list hardcoded in boto3 if still no regions - session = _boto3_session(options.get("profile")) + session = _boto3_session(self.get_option("profile")) regions = session.get_available_regions(service) if not regions: diff --git a/ansible_collections/amazon/aws/tests/integration/targets/ec2_ami/tasks/main.yml b/ansible_collections/amazon/aws/tests/integration/targets/ec2_ami/tasks/main.yml index a9289b3c1..267e52abb 100644 --- a/ansible_collections/amazon/aws/tests/integration/targets/ec2_ami/tasks/main.yml +++ b/ansible_collections/amazon/aws/tests/integration/targets/ec2_ami/tasks/main.yml @@ -708,8 +708,8 @@ tags: Name: "{{ ec2_ami_name }}_permissions" launch_permissions: - org_arns: [arn:aws:organizations::123456789012:organization/o-123ab4cdef] - org_unit_arns: [arn:aws:organizations::123456789012:ou/o-123example/ou-1234-5exampld] + org_arns: ["arn:aws:organizations::123456789012:organization/o-123ab4cdef"] + org_unit_arns: ["arn:aws:organizations::123456789012:ou/o-123example/ou-1234-5exampld"] register: permissions_update_result - name: Get ami info diff --git a/ansible_collections/amazon/aws/tests/integration/targets/ec2_security_group/tasks/multi_nested_target.yml b/ansible_collections/amazon/aws/tests/integration/targets/ec2_security_group/tasks/multi_nested_target.yml index dcb7ac7bb..02057003a 100644 --- a/ansible_collections/amazon/aws/tests/integration/targets/ec2_security_group/tasks/multi_nested_target.yml +++ b/ansible_collections/amazon/aws/tests/integration/targets/ec2_security_group/tasks/multi_nested_target.yml @@ -12,7 +12,7 @@ to_port: 8182 cidr_ipv6: - 64:ff9b::/96 - - [2620::/32] + - ["2620::/32"] - proto: tcp ports: 5665 cidr_ip: @@ -38,7 +38,7 @@ to_port: 8182 cidr_ipv6: - 64:ff9b::/96 - - [2620::/32] + - ["2620::/32"] - proto: tcp ports: 5665 cidr_ip: @@ -66,7 +66,7 @@ to_port: 8182 cidr_ipv6: - 64:ff9b::/96 - - [2620::/32] + - ["2620::/32"] - proto: tcp ports: 5665 cidr_ip: @@ -92,7 +92,7 @@ to_port: 8182 cidr_ipv6: - 64:ff9b::/96 - - [2620::/32] + - ["2620::/32"] - proto: tcp ports: 5665 cidr_ip: @@ -117,7 +117,7 @@ to_port: 8182 cidr_ipv6: - 64:ff9b::/96 - - [2620::/32] + - ["2620::/32"] - proto: tcp ports: 5665 cidr_ip: @@ -142,7 +142,7 @@ to_port: 8182 cidr_ipv6: - 64:ff9b::/96 - - [2620::/32] + - ["2620::/32"] - proto: tcp ports: 5665 cidr_ip: @@ -167,7 +167,7 @@ from_port: 8182 to_port: 8182 cidr_ipv6: - - [2620::/32, 64:ff9b::/96] + - ["2620::/32", "64:ff9b::/96"] - proto: tcp ports: 5665 cidr_ip: @@ -190,8 +190,8 @@ from_port: 8182 to_port: 8182 cidr_ipv6: - - [2620::/32, 64:ff9b::/96] - - [2001:DB8:A0B:12F0::1/64] + - ["2620::/32", "64:ff9b::/96"] + - ["2001:DB8:A0B:12F0::1/64"] - proto: tcp ports: 5665 cidr_ip: diff --git a/ansible_collections/amazon/aws/tests/integration/targets/inventory_aws_ec2/playbooks/create_inventory_config.yml b/ansible_collections/amazon/aws/tests/integration/targets/inventory_aws_ec2/playbooks/create_inventory_config.yml index 232911d24..282ca43ee 100644 --- a/ansible_collections/amazon/aws/tests/integration/targets/inventory_aws_ec2/playbooks/create_inventory_config.yml +++ b/ansible_collections/amazon/aws/tests/integration/targets/inventory_aws_ec2/playbooks/create_inventory_config.yml @@ -9,3 +9,8 @@ ansible.builtin.copy: dest: ../test.aws_ec2.yml content: "{{ lookup('template', template_name) }}" + + - name: write ini configuration + ansible.builtin.copy: + dest: ../config.ini + content: "{{ lookup('template', '../templates/config.ini.j2') }}" diff --git a/ansible_collections/amazon/aws/tests/integration/targets/inventory_aws_ec2/templates/config.ini.j2 b/ansible_collections/amazon/aws/tests/integration/targets/inventory_aws_ec2/templates/config.ini.j2 new file mode 100644 index 000000000..f7320a7fb --- /dev/null +++ b/ansible_collections/amazon/aws/tests/integration/targets/inventory_aws_ec2/templates/config.ini.j2 @@ -0,0 +1,3 @@ +[ansible-test] + +region = {{ aws_region }} \ No newline at end of file diff --git a/ansible_collections/amazon/aws/tests/integration/targets/inventory_aws_ec2/templates/inventory_with_template.yml.j2 b/ansible_collections/amazon/aws/tests/integration/targets/inventory_aws_ec2/templates/inventory_with_template.yml.j2 index 44a132c1c..dee7422a9 100644 --- a/ansible_collections/amazon/aws/tests/integration/targets/inventory_aws_ec2/templates/inventory_with_template.yml.j2 +++ b/ansible_collections/amazon/aws/tests/integration/targets/inventory_aws_ec2/templates/inventory_with_template.yml.j2 @@ -5,7 +5,7 @@ secret_key: '{{ aws_secret_key }}' session_token: '{{ security_token }}' {% endif %} regions: -- '{{ aws_region }}' +- '{{ '{{ lookup("ansible.builtin.ini", "region", section="ansible-test", file="config.ini") }}' }}' filters: tag:Name: - '{{ resource_prefix }}' diff --git a/ansible_collections/amazon/aws/tests/integration/targets/s3_object/aliases b/ansible_collections/amazon/aws/tests/integration/targets/s3_object/aliases index d34fac48d..2a1c5ccb6 100644 --- a/ansible_collections/amazon/aws/tests/integration/targets/s3_object/aliases +++ b/ansible_collections/amazon/aws/tests/integration/targets/s3_object/aliases @@ -1,3 +1,4 @@ cloud/aws aws_s3 s3_object_info +time=12m diff --git a/ansible_collections/amazon/aws/tests/integration/targets/s3_object/tasks/copy_object.yml b/ansible_collections/amazon/aws/tests/integration/targets/s3_object/tasks/copy_object.yml index 9ae36b952..994733d81 100644 --- a/ansible_collections/amazon/aws/tests/integration/targets/s3_object/tasks/copy_object.yml +++ b/ansible_collections/amazon/aws/tests/integration/targets/s3_object/tasks/copy_object.yml @@ -1,5 +1,12 @@ --- -- block: +- vars: + withmeta_data: + something: exists + version: "1.0.2" + metacopy_data: + name: metacopy + version: "1.0.3" + block: - name: define bucket name used for tests ansible.builtin.set_fact: copy_bucket: @@ -142,6 +149,68 @@ - result is not changed - result.msg == "Key this_key_does_not_exist.txt does not exist in bucket "+copy_bucket.src+"." + # Copy with metadata + - name: Set fact for bucket name + ansible.builtin.set_fact: + bucket_name: "{{ copy_bucket.dst }}" + + - name: Create test bucket + amazon.aws.s3_bucket: + name: "{{ bucket_name }}" + state: present + + - name: Create test object + amazon.aws.s3_object: + bucket: "{{ bucket_name }}" + object: nometa + mode: put + content: "some content" + + - name: Copy and add metadata + amazon.aws.s3_object: + bucket: "{{ bucket_name }}" + object: metacopy + mode: copy + copy_src: + bucket: "{{ bucket_name }}" + object: nometa + metadata: "{{ metacopy_data }}" + + - name: Create test object with metadata + amazon.aws.s3_object: + bucket: "{{ bucket_name }}" + object: withmeta + mode: put + content: "another content" + metadata: "{{ withmeta_data }}" + + - name: Copy and preserve metadata + amazon.aws.s3_object: + bucket: "{{ bucket_name }}" + object: copywithmeta + mode: copy + copy_src: + bucket: "{{ bucket_name }}" + object: withmeta + + - name: Get objects info + amazon.aws.s3_object_info: + bucket_name: "{{ bucket_name }}" + object_name: "{{ item }}" + loop: + - nometa + - metacopy + - withmeta + - copywithmeta + register: obj_info + + - assert: + that: + - obj_info.results | selectattr('item', 'equalto', 'nometa') | map(attribute='object_info.0.object_data.metadata') | first == {} + - obj_info.results | selectattr('item', 'equalto', 'withmeta') | map(attribute='object_info.0.object_data.metadata') | first == withmeta_data + - obj_info.results | selectattr('item', 'equalto', 'metacopy') | map(attribute='object_info.0.object_data.metadata') | first == metacopy_data + - obj_info.results | selectattr('item', 'equalto', 'copywithmeta') | map(attribute='object_info.0.object_data.metadata') | first == withmeta_data + always: - ansible.builtin.include_tasks: delete_bucket.yml with_items: diff --git a/ansible_collections/amazon/aws/tests/integration/targets/s3_object/tasks/main.yml b/ansible_collections/amazon/aws/tests/integration/targets/s3_object/tasks/main.yml index ed65fe31f..7a8a585de 100644 --- a/ansible_collections/amazon/aws/tests/integration/targets/s3_object/tasks/main.yml +++ b/ansible_collections/amazon/aws/tests/integration/targets/s3_object/tasks/main.yml @@ -837,8 +837,6 @@ that: - binary_files.results[0].stat.checksum == binary_files.results[1].stat.checksum - - ansible.builtin.include_tasks: copy_object.yml - - ansible.builtin.include_tasks: copy_object_acl_disabled_bucket.yml - name: Run tagging tests block: # ============================================================ @@ -1074,6 +1072,8 @@ - (result.tags | length) == 0 - ansible.builtin.include_tasks: copy_recursively.yml + - ansible.builtin.include_tasks: copy_object.yml + - ansible.builtin.include_tasks: copy_object_acl_disabled_bucket.yml always: - name: delete temporary files file: diff --git a/ansible_collections/amazon/aws/tests/unit/module_utils/iam/test_iam_resource_transforms.py b/ansible_collections/amazon/aws/tests/unit/module_utils/iam/test_iam_resource_transforms.py new file mode 100644 index 000000000..28090f993 --- /dev/null +++ b/ansible_collections/amazon/aws/tests/unit/module_utils/iam/test_iam_resource_transforms.py @@ -0,0 +1,583 @@ +# -*- coding: utf-8 -*- + +# Copyright: Contributors to the Ansible project +# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) + + +import dateutil + +from ansible_collections.amazon.aws.plugins.module_utils.iam import normalize_iam_access_key +from ansible_collections.amazon.aws.plugins.module_utils.iam import normalize_iam_access_keys +from ansible_collections.amazon.aws.plugins.module_utils.iam import normalize_iam_group +from ansible_collections.amazon.aws.plugins.module_utils.iam import normalize_iam_instance_profile +from ansible_collections.amazon.aws.plugins.module_utils.iam import normalize_iam_mfa_device +from ansible_collections.amazon.aws.plugins.module_utils.iam import normalize_iam_mfa_devices +from ansible_collections.amazon.aws.plugins.module_utils.iam import normalize_iam_policy +from ansible_collections.amazon.aws.plugins.module_utils.iam import normalize_iam_role +from ansible_collections.amazon.aws.plugins.module_utils.iam import normalize_iam_user + +# The various normalize_ functions are based upon ..transformation.boto3_resource_to_ansible_dict +# As such these tests will be relatively light touch. + +example_date1_txt = "2020-12-30T00:00:00.000Z" +example_date2_txt = "2021-04-26T01:23:58.000Z" +example_date1_iso = "2020-12-30T00:00:00+00:00" +example_date2_iso = "2021-04-26T01:23:58+00:00" +example_date1 = dateutil.parser.parse(example_date1_txt) +example_date2 = dateutil.parser.parse(example_date2_txt) + + +class TestIamResourceToAnsibleDict: + def setup_method(self): + pass + + def test_normalize_iam_mfa_device(self): + INPUT = { + "UserName": "ExampleUser", + "SerialNumber": "arn:aws:iam::123456789012:mfa/ExampleUser", + "EnableDate": example_date1, + } + OUTPUT = { + "user_name": "ExampleUser", + "serial_number": "arn:aws:iam::123456789012:mfa/ExampleUser", + "enable_date": example_date1_iso, + "tags": {}, + } + + assert OUTPUT == normalize_iam_mfa_device(INPUT) + + def test_normalize_iam_mfa_devices(self): + INPUT = [ + { + "UserName": "ExampleUser", + "SerialNumber": "arn:aws:iam::123456789012:mfa/ExampleUser", + "EnableDate": example_date1, + } + ] + OUTPUT = [ + { + "user_name": "ExampleUser", + "serial_number": "arn:aws:iam::123456789012:mfa/ExampleUser", + "enable_date": example_date1_iso, + "tags": {}, + } + ] + + assert OUTPUT == normalize_iam_mfa_devices(INPUT) + + def test_normalize_iam_user(self): + INPUT = { + "Path": "/MyPath/", + "UserName": "ExampleUser", + "UserId": "AIDU12345EXAMPLE12345", + "Arn": "arn:aws:iam::123456789012:user/MyPath/ExampleUser", + "CreateDate": example_date1, + "PasswordLastUsed": example_date2, + "PermissionsBoundary": { + "PermissionsBoundaryType": "PermissionsBoundaryPolicy", + "PermissionsBoundaryArn": "arn:aws:iam::123456789012:policy/ExamplePolicy", + }, + "Tags": [ + {"Key": "MyKey", "Value": "Example Value"}, + ], + } + + OUTPUT = { + "path": "/MyPath/", + "user_name": "ExampleUser", + "user_id": "AIDU12345EXAMPLE12345", + "arn": "arn:aws:iam::123456789012:user/MyPath/ExampleUser", + "create_date": example_date1_iso, + "password_last_used": example_date2_iso, + "permissions_boundary": { + "permissions_boundary_type": "PermissionsBoundaryPolicy", + "permissions_boundary_arn": "arn:aws:iam::123456789012:policy/ExamplePolicy", + }, + "tags": {"MyKey": "Example Value"}, + } + + assert OUTPUT == normalize_iam_user(INPUT) + + def test_normalize_iam_policy(self): + INPUT = { + "PolicyName": "AnsibleIntegratation-CI-ApplicationServices", + "PolicyId": "ANPA12345EXAMPLE12345", + "Arn": "arn:aws:iam::123456789012:policy/AnsibleIntegratation-CI-ApplicationServices", + "Path": "/examples/", + "DefaultVersionId": "v6", + "AttachmentCount": 2, + "PermissionsBoundaryUsageCount": 0, + "IsAttachable": True, + "CreateDate": example_date1, + "UpdateDate": example_date2, + "Tags": [ + {"Key": "MyKey", "Value": "Example Value"}, + ], + } + + OUTPUT = { + "policy_name": "AnsibleIntegratation-CI-ApplicationServices", + "policy_id": "ANPA12345EXAMPLE12345", + "arn": "arn:aws:iam::123456789012:policy/AnsibleIntegratation-CI-ApplicationServices", + "path": "/examples/", + "default_version_id": "v6", + "attachment_count": 2, + "permissions_boundary_usage_count": 0, + "is_attachable": True, + "create_date": example_date1_iso, + "update_date": example_date2_iso, + "tags": {"MyKey": "Example Value"}, + } + + assert OUTPUT == normalize_iam_policy(INPUT) + + def test_normalize_iam_group(self): + INPUT = { + "Users": [ + { + "Path": "/", + "UserName": "ansible_test", + "UserId": "AIDA12345EXAMPLE12345", + "Arn": "arn:aws:iam::123456789012:user/ansible_test", + "CreateDate": example_date1, + "PasswordLastUsed": example_date2, + } + ], + "Group": { + "Path": "/", + "GroupName": "ansible-integration-ci", + "GroupId": "AGPA01234EXAMPLE01234", + "Arn": "arn:aws:iam::123456789012:group/ansible-integration-ci", + "CreateDate": example_date1, + }, + "AttachedPolicies": [ + { + "PolicyName": "AnsibleIntegratation-CI-Paas", + "PolicyArn": "arn:aws:iam::123456789012:policy/AnsibleIntegratation-CI-Paas", + }, + { + "PolicyName": "AnsibleIntegratation-CI-ApplicationServices", + "PolicyArn": "arn:aws:iam::123456789012:policy/AnsibleIntegratation-CI-ApplicationServices", + }, + ], + } + + OUTPUT = { + "users": [ + { + "path": "/", + "user_name": "ansible_test", + "user_id": "AIDA12345EXAMPLE12345", + "arn": "arn:aws:iam::123456789012:user/ansible_test", + "create_date": example_date1_iso, + "password_last_used": example_date2_iso, + } + ], + "group": { + "path": "/", + "group_name": "ansible-integration-ci", + "group_id": "AGPA01234EXAMPLE01234", + "arn": "arn:aws:iam::123456789012:group/ansible-integration-ci", + "create_date": example_date1_iso, + }, + "attached_policies": [ + { + "policy_name": "AnsibleIntegratation-CI-Paas", + "policy_arn": "arn:aws:iam::123456789012:policy/AnsibleIntegratation-CI-Paas", + }, + { + "policy_name": "AnsibleIntegratation-CI-ApplicationServices", + "policy_arn": "arn:aws:iam::123456789012:policy/AnsibleIntegratation-CI-ApplicationServices", + }, + ], + } + + assert OUTPUT == normalize_iam_group(INPUT) + + def test_normalize_access_key(self): + INPUT = { + "UserName": "ansible_test", + "AccessKeyId": "AKIA12345EXAMPLE1234", + "Status": "Active", + "CreateDate": example_date1, + } + + OUTPUT = { + "user_name": "ansible_test", + "access_key_id": "AKIA12345EXAMPLE1234", + "status": "Active", + "create_date": example_date1_iso, + } + + assert OUTPUT == normalize_iam_access_key(INPUT) + + def test_normalize_access_keys(self): + INPUT = [ + { + "UserName": "ansible_test", + "AccessKeyId": "AKIA12345EXAMPLE1234", + "Status": "Active", + "CreateDate": example_date1, + }, + { + "UserName": "ansible_test", + "AccessKeyId": "AKIA01234EXAMPLE4321", + "Status": "Active", + "CreateDate": example_date2, + }, + ] + + OUTPUT = [ + { + "access_key_id": "AKIA12345EXAMPLE1234", + "create_date": example_date1_iso, + "status": "Active", + "user_name": "ansible_test", + }, + { + "access_key_id": "AKIA01234EXAMPLE4321", + "create_date": example_date2_iso, + "status": "Active", + "user_name": "ansible_test", + }, + ] + + assert OUTPUT == normalize_iam_access_keys(INPUT) + + # Switch order to test that they're sorted by Creation Date + INPUT = [ + { + "UserName": "ansible_test", + "AccessKeyId": "AKIA12345EXAMPLE1234", + "Status": "Active", + "CreateDate": example_date2, + }, + { + "UserName": "ansible_test", + "AccessKeyId": "AKIA01234EXAMPLE4321", + "Status": "Active", + "CreateDate": example_date1, + }, + ] + + OUTPUT = [ + { + "access_key_id": "AKIA01234EXAMPLE4321", + "create_date": example_date1_iso, + "status": "Active", + "user_name": "ansible_test", + }, + { + "access_key_id": "AKIA12345EXAMPLE1234", + "create_date": example_date2_iso, + "status": "Active", + "user_name": "ansible_test", + }, + ] + + assert OUTPUT == normalize_iam_access_keys(INPUT) + + def test_normalize_role(self): + INPUT = { + "Arn": "arn:aws:iam::123456789012:role/ansible-test-76640355", + "AssumeRolePolicyDocument": { + "Statement": [ + {"Action": "sts:AssumeRole", "Effect": "Deny", "Principal": {"Service": "ec2.amazonaws.com"}} + ], + "Version": "2012-10-17", + }, + "CreateDate": example_date1, + "Description": "Ansible Test Role (updated) ansible-test-76640355", + "InlinePolicies": ["inline-policy-a", "inline-policy-b"], + "InstanceProfiles": [ + { + "Arn": "arn:aws:iam::123456789012:instance-profile/ansible-test-76640355", + "CreateDate": example_date2, + "InstanceProfileId": "AIPA12345EXAMPLE12345", + "InstanceProfileName": "ansible-test-76640355", + "Path": "/", + "Roles": [ + { + "Arn": "arn:aws:iam::123456789012:role/ansible-test-76640355", + "AssumeRolePolicyDocument": { + "Statement": [ + { + "Action": "sts:AssumeRole", + "Effect": "Deny", + "Principal": {"Service": "ec2.amazonaws.com"}, + } + ], + "Version": "2012-10-17", + }, + "CreateDate": example_date1, + "Path": "/", + "RoleId": "AROA12345EXAMPLE12345", + "RoleName": "ansible-test-76640355", + # XXX Bug in iam_role_info - Tags should have been in here. + "Tags": [{"Key": "TagB", "Value": "ValueB"}], + } + ], + "Tags": [{"Key": "TagA", "Value": "Value A"}], + } + ], + "ManagedPolicies": [ + { + "PolicyArn": "arn:aws:iam::123456789012:policy/ansible-test-76640355", + "PolicyName": "ansible-test-76640355", + } + ], + "MaxSessionDuration": 43200, + "Path": "/", + "RoleId": "AROA12345EXAMPLE12345", + "RoleLastUsed": {}, + "RoleName": "ansible-test-76640355", + "Tags": [{"Key": "TagB", "Value": "ValueB"}], + } + + OUTPUT = { + "arn": "arn:aws:iam::123456789012:role/ansible-test-76640355", + "assume_role_policy_document": { + "Statement": [ + {"Action": "sts:AssumeRole", "Effect": "Deny", "Principal": {"Service": "ec2.amazonaws.com"}} + ], + "Version": "2012-10-17", + }, + "create_date": example_date1_iso, + "description": "Ansible Test Role (updated) ansible-test-76640355", + "inline_policies": ["inline-policy-a", "inline-policy-b"], + "instance_profiles": [ + { + "arn": "arn:aws:iam::123456789012:instance-profile/ansible-test-76640355", + "create_date": example_date2_iso, + "instance_profile_id": "AIPA12345EXAMPLE12345", + "instance_profile_name": "ansible-test-76640355", + "path": "/", + "roles": [ + { + "arn": "arn:aws:iam::123456789012:role/ansible-test-76640355", + "assume_role_policy_document": { + "Statement": [ + { + "Action": "sts:AssumeRole", + "Effect": "Deny", + "Principal": {"Service": "ec2.amazonaws.com"}, + } + ], + "Version": "2012-10-17", + }, + "create_date": example_date1_iso, + "path": "/", + "role_id": "AROA12345EXAMPLE12345", + "role_name": "ansible-test-76640355", + "tags": {"TagB": "ValueB"}, + } + ], + "tags": {"TagA": "Value A"}, + } + ], + "managed_policies": [ + { + "policy_arn": "arn:aws:iam::123456789012:policy/ansible-test-76640355", + "policy_name": "ansible-test-76640355", + } + ], + "max_session_duration": 43200, + "path": "/", + "role_id": "AROA12345EXAMPLE12345", + "role_last_used": {}, + "role_name": "ansible-test-76640355", + "tags": {"TagB": "ValueB"}, + } + + assert OUTPUT == normalize_iam_role(INPUT) + + def test_normalize_role_compat(self): + INPUT = { + "Arn": "arn:aws:iam::123456789012:role/ansible-test-76640355", + "AssumeRolePolicyDocument": { + "Statement": [ + {"Action": "sts:AssumeRole", "Effect": "Deny", "Principal": {"Service": "ec2.amazonaws.com"}} + ], + "Version": "2012-10-17", + }, + "CreateDate": example_date1, + "Description": "Ansible Test Role (updated) ansible-test-76640355", + "InlinePolicies": ["inline-policy-a", "inline-policy-b"], + "InstanceProfiles": [ + { + "Arn": "arn:aws:iam::123456789012:instance-profile/ansible-test-76640355", + "CreateDate": example_date2, + "InstanceProfileId": "AIPA12345EXAMPLE12345", + "InstanceProfileName": "ansible-test-76640355", + "Path": "/", + "Roles": [ + { + "Arn": "arn:aws:iam::123456789012:role/ansible-test-76640355", + "AssumeRolePolicyDocument": { + "Statement": [ + { + "Action": "sts:AssumeRole", + "Effect": "Deny", + "Principal": {"Service": "ec2.amazonaws.com"}, + } + ], + "Version": "2012-10-17", + }, + "CreateDate": example_date1, + "Path": "/", + "RoleId": "AROA12345EXAMPLE12345", + "RoleName": "ansible-test-76640355", + # XXX Bug in iam_role_info - Tags should have been in here. + "Tags": [{"Key": "TagB", "Value": "ValueB"}], + } + ], + "Tags": [{"Key": "TagA", "Value": "Value A"}], + } + ], + "ManagedPolicies": [ + { + "PolicyArn": "arn:aws:iam::123456789012:policy/ansible-test-76640355", + "PolicyName": "ansible-test-76640355", + } + ], + "MaxSessionDuration": 43200, + "Path": "/", + "RoleId": "AROA12345EXAMPLE12345", + "RoleLastUsed": {}, + "RoleName": "ansible-test-76640355", + "Tags": [{"Key": "TagB", "Value": "ValueB"}], + } + + OUTPUT = { + "arn": "arn:aws:iam::123456789012:role/ansible-test-76640355", + "assume_role_policy_document": { + "statement": [ + {"action": "sts:AssumeRole", "effect": "Deny", "principal": {"service": "ec2.amazonaws.com"}} + ], + "version": "2012-10-17", + }, + "assume_role_policy_document_raw": { + "Statement": [ + {"Action": "sts:AssumeRole", "Effect": "Deny", "Principal": {"Service": "ec2.amazonaws.com"}} + ], + "Version": "2012-10-17", + }, + "create_date": example_date1_iso, + "description": "Ansible Test Role (updated) ansible-test-76640355", + "inline_policies": ["inline-policy-a", "inline-policy-b"], + "instance_profiles": [ + { + "arn": "arn:aws:iam::123456789012:instance-profile/ansible-test-76640355", + "create_date": example_date2_iso, + "instance_profile_id": "AIPA12345EXAMPLE12345", + "instance_profile_name": "ansible-test-76640355", + "path": "/", + "roles": [ + { + "arn": "arn:aws:iam::123456789012:role/ansible-test-76640355", + "assume_role_policy_document": { + "Statement": [ + { + "Action": "sts:AssumeRole", + "Effect": "Deny", + "Principal": {"Service": "ec2.amazonaws.com"}, + } + ], + "Version": "2012-10-17", + }, + "create_date": example_date1_iso, + "path": "/", + "role_id": "AROA12345EXAMPLE12345", + "role_name": "ansible-test-76640355", + "tags": {"TagB": "ValueB"}, + } + ], + "tags": {"TagA": "Value A"}, + } + ], + "managed_policies": [ + { + "policy_arn": "arn:aws:iam::123456789012:policy/ansible-test-76640355", + "policy_name": "ansible-test-76640355", + } + ], + "max_session_duration": 43200, + "path": "/", + "role_id": "AROA12345EXAMPLE12345", + "role_last_used": {}, + "role_name": "ansible-test-76640355", + "tags": {"TagB": "ValueB"}, + } + + assert OUTPUT == normalize_iam_role(INPUT, _v7_compat=True) + + def test_normalize_instance_profile(self): + INPUT = { + "Arn": "arn:aws:iam::123456789012:instance-profile/ansible-test-40050922/ansible-test-40050922", + "CreateDate": example_date1, + "InstanceProfileId": "AIPA12345EXAMPLE12345", + "InstanceProfileName": "ansible-test-40050922", + "Path": "/ansible-test-40050922/", + "Roles": [ + { + "Arn": "arn:aws:iam::123456789012:role/ansible-test-40050922/ansible-test-40050922", + "AssumeRolePolicyDocument": { + "Statement": [ + { + "Action": "sts:AssumeRole", + "Effect": "Deny", + "Principal": {"Service": "ec2.amazonaws.com"}, + } + ], + "Version": "2012-10-17", + }, + "CreateDate": example_date2, + "Path": "/ansible-test-40050922/", + "RoleId": "AROA12345EXAMPLE12345", + "RoleName": "ansible-test-40050922", + "Tags": [{"Key": "TagC", "Value": "ValueC"}], + } + ], + "Tags": [ + {"Key": "Key with Spaces", "Value": "Value with spaces"}, + {"Key": "snake_case_key", "Value": "snake_case_value"}, + {"Key": "CamelCaseKey", "Value": "CamelCaseValue"}, + {"Key": "pascalCaseKey", "Value": "pascalCaseValue"}, + ], + } + + OUTPUT = { + "arn": "arn:aws:iam::123456789012:instance-profile/ansible-test-40050922/ansible-test-40050922", + "create_date": "2020-12-30T00:00:00+00:00", + "instance_profile_id": "AIPA12345EXAMPLE12345", + "instance_profile_name": "ansible-test-40050922", + "path": "/ansible-test-40050922/", + "roles": [ + { + "arn": "arn:aws:iam::123456789012:role/ansible-test-40050922/ansible-test-40050922", + "assume_role_policy_document": { + "Statement": [ + { + "Action": "sts:AssumeRole", + "Effect": "Deny", + "Principal": {"Service": "ec2.amazonaws.com"}, + } + ], + "Version": "2012-10-17", + }, + "create_date": "2021-04-26T01:23:58+00:00", + "path": "/ansible-test-40050922/", + "role_id": "AROA12345EXAMPLE12345", + "role_name": "ansible-test-40050922", + "tags": {"TagC": "ValueC"}, + } + ], + "tags": { + "CamelCaseKey": "CamelCaseValue", + "Key with Spaces": "Value with spaces", + "pascalCaseKey": "pascalCaseValue", + "snake_case_key": "snake_case_value", + }, + } + + assert OUTPUT == normalize_iam_instance_profile(INPUT) diff --git a/ansible_collections/amazon/aws/tests/unit/module_utils/transformation/test_boto3_resource_to_ansible_dict.py b/ansible_collections/amazon/aws/tests/unit/module_utils/transformation/test_boto3_resource_to_ansible_dict.py new file mode 100644 index 000000000..89a0a837c --- /dev/null +++ b/ansible_collections/amazon/aws/tests/unit/module_utils/transformation/test_boto3_resource_to_ansible_dict.py @@ -0,0 +1,140 @@ +# (c) 2017 Red Hat Inc. +# +# This file is part of Ansible +# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) + +from copy import deepcopy +from unittest.mock import sentinel + +import dateutil +import pytest + +from ansible.module_utils.common.dict_transformations import camel_dict_to_snake_dict + +from ansible_collections.amazon.aws.plugins.module_utils.transformation import boto3_resource_to_ansible_dict + +example_date_txt = "2020-12-30T00:00:00.000Z" +example_date_iso = "2020-12-30T00:00:00+00:00" +example_date = dateutil.parser.parse(example_date_txt) + +EXAMPLE_BOTO3 = [ + None, + {}, + {"ExampleDate": example_date}, + {"ExampleTxtDate": example_date_txt}, + {"Tags": [{"Key": "MyKey", "Value": "MyValue"}, {"Key": "Normal case", "Value": "Normal Value"}]}, + { + "Name": "ExampleResource", + "ExampleDate": example_date, + "Tags": [{"Key": "MyKey", "Value": "MyValue"}, {"Key": "Normal case", "Value": "Normal Value"}], + }, + {"ExampleNested": {"ExampleKey": "Example Value"}}, +] + +EXAMPLE_DICT = [ + None, + {}, + {"example_date": example_date_iso, "tags": {}}, + {"example_txt_date": example_date_txt, "tags": {}}, + {"tags": {"MyKey": "MyValue", "Normal case": "Normal Value"}}, + { + "name": "ExampleResource", + "example_date": example_date_iso, + "tags": {"MyKey": "MyValue", "Normal case": "Normal Value"}, + }, + {"example_nested": {"example_key": "Example Value"}, "tags": {}}, +] + +TEST_DATA = zip(EXAMPLE_BOTO3, EXAMPLE_DICT) + +NESTED_DATA = {"sentinal": sentinel.MY_VALUE} + + +def do_transform_nested(resource): + return {"sentinal": sentinel.MY_VALUE} + + +class TestBoto3ResourceToAnsibleDict: + def setup_method(self): + pass + + @pytest.mark.parametrize("input_params, output_params", deepcopy(TEST_DATA)) + def test_default_conversion(self, input_params, output_params): + # Test default behaviour + assert boto3_resource_to_ansible_dict(input_params) == output_params + + @pytest.mark.parametrize("input_params, output_params", deepcopy(TEST_DATA)) + def test_normalize(self, input_params, output_params): + # Test with normalize explicitly enabled + assert boto3_resource_to_ansible_dict(input_params, normalize=True) == output_params + + @pytest.mark.parametrize("input_params, output_params", deepcopy(TEST_DATA)) + def test_no_normalize(self, input_params, output_params): + # Test with normalize explicitly disabled + expected_value = deepcopy(output_params) + if input_params and "ExampleDate" in input_params: + expected_value["example_date"] = example_date + assert expected_value == boto3_resource_to_ansible_dict(input_params, normalize=False) + + @pytest.mark.parametrize("input_params, output_params", deepcopy(TEST_DATA)) + def test_no_skip(self, input_params, output_params): + # Test with ignore_list explicitly set to [] + assert boto3_resource_to_ansible_dict(input_params, ignore_list=[]) == output_params + assert boto3_resource_to_ansible_dict(input_params, ignore_list=["NotUsed"]) == output_params + + @pytest.mark.parametrize("input_params, output_params", deepcopy(TEST_DATA)) + def test_skip(self, input_params, output_params): + # Test with ignore_list explicitly set + expected_value = deepcopy(output_params) + if input_params and "ExampleNested" in input_params: + expected_value["example_nested"] = input_params["ExampleNested"] + assert expected_value == boto3_resource_to_ansible_dict(input_params, ignore_list=["ExampleNested"]) + assert expected_value == boto3_resource_to_ansible_dict(input_params, ignore_list=["NotUsed", "ExampleNested"]) + assert expected_value == boto3_resource_to_ansible_dict(input_params, ignore_list=["ExampleNested", "NotUsed"]) + + @pytest.mark.parametrize("input_params, output_params", deepcopy(TEST_DATA)) + def test_tags(self, input_params, output_params): + # Test with transform_tags explicitly enabled + assert boto3_resource_to_ansible_dict(input_params, transform_tags=True) == output_params + + @pytest.mark.parametrize("input_params, output_params", deepcopy(TEST_DATA)) + def test_no_tags(self, input_params, output_params): + # Test with transform_tags explicitly disabled + expected_value = deepcopy(output_params) + if input_params and "Tags" in input_params: + camel_tags = camel_dict_to_snake_dict({"tags": input_params["Tags"]}) + expected_value.update(camel_tags) + assert expected_value == boto3_resource_to_ansible_dict(input_params, transform_tags=False) + + @pytest.mark.parametrize("input_params, output_params", deepcopy(TEST_DATA)) + def test_no_nested(self, input_params, output_params): + # Test with transform_nested explicitly set to an empty dictionary + assert boto3_resource_to_ansible_dict(input_params, nested_transforms={}) == output_params + + @pytest.mark.parametrize("input_params, output_params", deepcopy(TEST_DATA)) + def test_nested(self, input_params, output_params): + # Test with a custom transformation of nested resources + transform_map = {"ExampleNested": do_transform_nested} + expected_value = deepcopy(output_params) + + actual_value = boto3_resource_to_ansible_dict(input_params, nested_transforms=transform_map) + + if input_params and "ExampleNested" in input_params: + assert actual_value["example_nested"] == NESTED_DATA + del actual_value["example_nested"] + del expected_value["example_nested"] + + assert expected_value == actual_value + + @pytest.mark.parametrize("input_params, output_params", deepcopy(TEST_DATA)) + def test_force_tags(self, input_params, output_params): + # Test with force_tags explicitly enabled + assert boto3_resource_to_ansible_dict(input_params, force_tags=True) == output_params + + @pytest.mark.parametrize("input_params, output_params", deepcopy(TEST_DATA)) + def test_no_force_tags(self, input_params, output_params): + # Test with force_tags explicitly enabled + expected_value = deepcopy(output_params) + if input_params and "Tags" not in input_params: + del expected_value["tags"] + assert boto3_resource_to_ansible_dict(input_params, force_tags=False) == expected_value diff --git a/ansible_collections/amazon/aws/tests/unit/plugin_utils/inventory/test_inventory_base.py b/ansible_collections/amazon/aws/tests/unit/plugin_utils/inventory/test_inventory_base.py index 32eb3f7ab..4da5792a8 100644 --- a/ansible_collections/amazon/aws/tests/unit/plugin_utils/inventory/test_inventory_base.py +++ b/ansible_collections/amazon/aws/tests/unit/plugin_utils/inventory/test_inventory_base.py @@ -3,6 +3,7 @@ # This file is part of Ansible # GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) +import re from unittest.mock import MagicMock from unittest.mock import call from unittest.mock import patch @@ -11,6 +12,8 @@ from unittest.mock import sentinel import pytest import ansible.plugins.inventory as base_inventory +from ansible.errors import AnsibleError +from ansible.module_utils.six import string_types import ansible_collections.amazon.aws.plugins.plugin_utils.inventory as utils_inventory @@ -65,3 +68,131 @@ def test_inventory_verify_file(monkeypatch, filename, result): assert inventory_plugin.verify_file(filename) is result base_verify.return_value = False assert inventory_plugin.verify_file(filename) is False + + +class AwsUnitTestTemplar: + def __init__(self, config): + self.config = config + + def is_template_string(self, key): + m = re.findall("{{([ ]*[a-zA-Z0-9_]*[ ]*)}}", key) + return bool(m) + + def is_template(self, data): + if isinstance(data, string_types): + return self.is_template_string(data) + elif isinstance(data, (list, tuple)): + for v in data: + if self.is_template(v): + return True + elif isinstance(data, dict): + for k in data: + if self.is_template(k) or self.is_template(data[k]): + return True + return False + + def template(self, variable, disable_lookups): + for k, v in self.config.items(): + variable = re.sub("{{([ ]*%s[ ]*)}}" % k, v, variable) + if self.is_template_string(variable): + m = re.findall("{{([ ]*[a-zA-Z0-9_]*[ ]*)}}", variable) + raise AnsibleError(f"Missing variables: {','.join([k.replace(' ', '') for k in m])}") + return variable + + +@pytest.fixture +def aws_inventory_base(): + inventory = utils_inventory.AWSInventoryBase() + inventory._options = {} + inventory.templar = None + return inventory + + +@pytest.mark.parametrize( + "option,value", + [ + ("access_key", "amazon_ansible_access_key_001"), + ("secret_key", "amazon_ansible_secret_key_890"), + ("session_token", None), + ("use_ssm_inventory", False), + ("This_field_is_undefined", None), + ("assume_role_arn", "arn:aws:iam::123456789012:role/ansible-test-inventory"), + ("region", "us-east-2"), + ], +) +def test_inventory_get_options_without_templar(aws_inventory_base, mocker, option, value): + inventory_options = { + "access_key": "amazon_ansible_access_key_001", + "secret_key": "amazon_ansible_secret_key_890", + "endpoint": "http//ansible.amazon.com", + "assume_role_arn": "arn:aws:iam::123456789012:role/ansible-test-inventory", + "region": "us-east-2", + "use_ssm_inventory": False, + } + aws_inventory_base._options = inventory_options + + super_get_options_patch = mocker.patch( + "ansible_collections.amazon.aws.plugins.plugin_utils.inventory.BaseInventoryPlugin.get_options" + ) + super_get_options_patch.return_value = aws_inventory_base._options + + options = aws_inventory_base.get_options() + assert value == options.get(option) + + +@pytest.mark.parametrize( + "option,value,error", + [ + ("access_key", "amazon_ansible_access_key_001", None), + ("session_token", None, None), + ("use_ssm_inventory", "{{ aws_inventory_use_ssm }}", None), + ("This_field_is_undefined", None, None), + ("region", "us-east-1", None), + ("profile", None, "Missing variables: ansible_version"), + ], +) +def test_inventory_get_options_with_templar(aws_inventory_base, mocker, option, value, error): + inventory_options = { + "access_key": "amazon_ansible_access_key_001", + "profile": "ansbile_{{ ansible_os }}_{{ ansible_version }}", + "endpoint": "{{ aws_endpoint }}", + "region": "{{ aws_region_country }}-east-{{ aws_region_id }}", + "use_ssm_inventory": "{{ aws_inventory_use_ssm }}", + } + aws_inventory_base._options = inventory_options + templar_config = { + "ansible_os": "RedHat", + "aws_region_country": "us", + "aws_region_id": "1", + "aws_endpoint": "http//ansible.amazon.com", + } + aws_inventory_base.templar = AwsUnitTestTemplar(templar_config) + + super_get_options_patch = mocker.patch( + "ansible_collections.amazon.aws.plugins.plugin_utils.inventory.BaseInventoryPlugin.get_options" + ) + super_get_options_patch.return_value = aws_inventory_base._options + + super_get_option_patch = mocker.patch( + "ansible_collections.amazon.aws.plugins.plugin_utils.inventory.BaseInventoryPlugin.get_option" + ) + super_get_option_patch.side_effect = lambda x, hostvars=None: aws_inventory_base._options.get(x) + + if error: + # test using get_options() + with pytest.raises(AnsibleError) as exc: + options = aws_inventory_base.get_options() + options.get(option) + assert error == str(exc.value) + + # test using get_option() + with pytest.raises(AnsibleError) as exc: + aws_inventory_base.get_option(option) + assert error == str(exc.value) + else: + # test using get_options() + options = aws_inventory_base.get_options() + assert value == options.get(option) + + # test using get_option() + assert value == aws_inventory_base.get_option(option) diff --git a/ansible_collections/amazon/aws/tests/unit/plugins/inventory/test_aws_ec2.py b/ansible_collections/amazon/aws/tests/unit/plugins/inventory/test_aws_ec2.py index 8cced1662..e33b78c51 100644 --- a/ansible_collections/amazon/aws/tests/unit/plugins/inventory/test_aws_ec2.py +++ b/ansible_collections/amazon/aws/tests/unit/plugins/inventory/test_aws_ec2.py @@ -240,6 +240,7 @@ def test_get_tag_hostname(preference, instance, expected): ) def test_inventory_build_include_filters(inventory, _options, expected): inventory._options = _options + inventory.templar = None assert inventory.build_include_filters() == expected diff --git a/ansible_collections/ansible_community.py b/ansible_collections/ansible_community.py index a6826bc1e..c0f531dea 100644 --- a/ansible_collections/ansible_community.py +++ b/ansible_collections/ansible_community.py @@ -15,7 +15,7 @@ def main(): parser.add_argument( '--version', action='version', - version='Ansible community version 9.4.0', + version='Ansible community version 9.5.1', help="show the version of the Ansible community package", ) parser.parse_args() diff --git a/ansible_collections/ansible_release.py b/ansible_collections/ansible_release.py index a9e9253ba..5802122ab 100644 --- a/ansible_collections/ansible_release.py +++ b/ansible_collections/ansible_release.py @@ -3,4 +3,4 @@ # GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) # SPDX-License-Identifier: GPL-3.0-or-later -ansible_version = '9.4.0' \ No newline at end of file +ansible_version = '9.5.1' \ No newline at end of file diff --git a/ansible_collections/cisco/aci/.github/workflows/ansible-test.yml b/ansible_collections/cisco/aci/.github/workflows/ansible-test.yml index 53799a4ab..91bb1f3dd 100644 --- a/ansible_collections/cisco/aci/.github/workflows/ansible-test.yml +++ b/ansible_collections/cisco/aci/.github/workflows/ansible-test.yml @@ -7,7 +7,7 @@ on: # * is a special character in YAML so you have to quote this string - cron: '0 8 * * *' env: - python_version: 3.9 + python_version: '3.10' jobs: build: name: Build collection @@ -15,7 +15,7 @@ jobs: strategy: fail-fast: false matrix: - ansible: [v2.9.27, v2.10.17, v2.11.12, v2.12.10, stable-2.13, stable-2.14] + ansible: [v2.14.13, v2.15.8, v2.16.2, stable-2.16] steps: - name: Check out code uses: actions/checkout@v3 @@ -65,8 +65,8 @@ jobs: with: python-version: ${{ env.python_version }} - - name: Install ansible-base (stable-2.14) - run: pip install https://github.com/ansible/ansible/archive/stable-2.14.tar.gz --disable-pip-version-check + - name: Install ansible-base (v2.15.8) + run: pip install https://github.com/ansible/ansible/archive/v2.15.8.tar.gz --disable-pip-version-check - name: Download migrated collection artifacts uses: actions/download-artifact@v3 @@ -107,7 +107,7 @@ jobs: strategy: fail-fast: false matrix: - ansible: [v2.9.27, v2.10.17, v2.11.12, v2.12.10, stable-2.13, stable-2.14] + ansible: [v2.14.13, v2.15.8, v2.16.2, stable-2.16] steps: - name: Set up Python ${{ env.python_version }} uses: actions/setup-python@v4 @@ -149,11 +149,8 @@ jobs: strategy: fail-fast: false matrix: - ansible: [v2.10.17, v2.11.12, v2.12.10, stable-2.13, stable-2.14] - python-version: [3.9] - include: - - ansible: v2.9.27 - python-version: 3.8 + ansible: [v2.14.13, v2.15.8, v2.16.2, stable-2.16] + python-version: ['3.10'] steps: - name: Set up Python ${{ matrix.python-version }} uses: actions/setup-python@v4 @@ -198,8 +195,8 @@ jobs: with: python-version: ${{ env.python_version }} - - name: Install ansible-base (stable-2.13) - run: pip install https://github.com/ansible/ansible/archive/stable-2.13.tar.gz --disable-pip-version-check + - name: Install ansible-base (v2.15.8) + run: pip install https://github.com/ansible/ansible/archive/v2.15.8.tar.gz --disable-pip-version-check - name: Install coverage (v4.5.4) run: pip install coverage==4.5.4 diff --git a/ansible_collections/cisco/aci/.github/workflows/galaxy-importer.cfg b/ansible_collections/cisco/aci/.github/workflows/galaxy-importer.cfg index 631359cf4..7208e7c1e 100644 --- a/ansible_collections/cisco/aci/.github/workflows/galaxy-importer.cfg +++ b/ansible_collections/cisco/aci/.github/workflows/galaxy-importer.cfg @@ -1,6 +1,6 @@ [galaxy-importer] LOG_LEVEL_MAIN = INFO -RUN_FLAKE8 = True +RUN_FLAKE8 = False RUN_ANSIBLE_DOC = True RUN_ANSIBLE_LINT = True RUN_ANSIBLE_TEST = False diff --git a/ansible_collections/cisco/aci/CHANGELOG.rst b/ansible_collections/cisco/aci/CHANGELOG.rst index 4f4887bb5..17b77334e 100644 --- a/ansible_collections/cisco/aci/CHANGELOG.rst +++ b/ansible_collections/cisco/aci/CHANGELOG.rst @@ -5,6 +5,84 @@ Cisco ACI Ansible Collection Release Notes .. contents:: Topics +v2.9.0 +====== + +Release Summary +--------------- + +Release v2.9.0 of the ``ansible-aci`` collection on 2024-04-06. +This changelog describes all changes made to the modules and plugins included in this collection since v2.8.0. + + +Minor Changes +------------- + +- Add Authentification option for EIGRP interface profile. +- Add L3out Floating SVI modules (aci_l3out_floating_svi, aci_l3out_floating_svi_path, aci_l3out_floating_svi_path_secondary_ip and aci_l3out_floating_svi_secondary_ip) (#478) +- Add No-verification flag option to reduce the number of API calls. If true, a verifying GET will not be sent after a POST update to APIC +- Add access spine interface selector and port block binding in aci_access_port_block_to_access_port +- Add aci_access_spine_interface_selector module +- Add aci_action_rule_additional_communities module +- Add aci_action_rule_set_as_path and aci_action_rule_set_as_path_asn modules +- Add aci_bgp_peer_prefix_policy, aci_bgp_route_summarization_policy and aci_bgp_address_family_context_policy modules +- Add aci_fabric_pod, aci_fabric_pod_external_tep, aci_fabric_pod_profile, aci_fabric_pod_remote_pool modules (#558) +- Add aci_hsrp_interface_policy, aci_l3out_hsrp_group, aci_l3out_hsrp_interface_profile and aci_l3out_hsrp_secondary_vip modules (#505) +- Add aci_interface_policy_eigrp (class:eigrpIfPol) module +- Add aci_interface_policy_pim module +- Add aci_interface_policy_storm_control module +- Add aci_keychain_policy and aci_key_policy modules +- Add aci_l3out_bfd_multihop_interface_profile, aci_l3out_bfd_interface_profile, aci_interface_policy_bfd_multihop, aci_interface_policy_bfd and aci_bfd_multihop_node_policy modules (#492) +- Add aci_l3out_dhcp_relay_label, aci_dhcp_option_policy and aci_dhcp_option modules +- Add aci_l3out_eigrp_interface_profile module +- Add aci_listify filter plugin to flattens nested dictionaries +- Add aci_netflow_exporter_policy module +- Add aci_netflow_monitor_policy and aci_netflow_record_policy modules +- Add aci_netflow_monitor_to_exporter module +- Add aci_node_block module +- Add aci_pim_route_map_policy and aci_pim_route_map_entry modules +- Add aci_qos_custom_policy and aci_qos_dscp_class modules +- Add aci_qos_dot1p_class module +- Add action rules attributes to aci_tenant_action_rule_profile. +- Add auto to speed attribute options in aci_interface_policy_link_level module (#577) +- Add missing options to aci_bd module +- Add modules aci_bd_to_netflow_monitor_policy and aci_bd_rogue_exception_mac (#600) +- Add modules for Fabric External Connection Policies and its childs +- Add option to set delimiter to _ in aci_epg_to_domain module +- Add qos_custom_policy, pim_interface_policy and igmp_interface_policy as new child_classes for aci_l3out_logical_interface_profile. +- Add support for annotation in aci_rest module (#437) +- Add support for block statements in useg attributes with the aci_epg_useg_attribute_block_statement module +- Add support for configuration of access switch policy groups with aci_access_switch_policy_group module +- Add support for configuration of certificate authorities in aci_aaa_certificate_authority +- Add support for configuration of fabric management access policies in aci_fabric_management_access +- Add support for configuration of vrf multicast with aci_vrf_multicast module +- Add support for configuring Azure cloud subnets using the aci_cloud_subnet module +- Add support for encap scope in aci_l3out_interface +- Add support for https ssl cipher configuration in aci_fabric_management_access_https_cipher +- Add support for infra l3out nodes bgp-evpn loopback, mpls transport loopback and segment id in aci_l3out_logical_node +- Add support for infra sr mpls micro bfd in aci_l3out_interface +- Add support for intra epg, taboo, and contract interface in aci_epg_to_contract +- Add support for key ring configuration in aci_aaa_key_ring +- Add support for mac and description in aci_l3out_interface +- Add support for mpls custom qos policy for infra sr mpls l3outs node profiles in aci_l3out_logical_node_profile +- Add support for security default settings configuration in aci_aaa_security_default_settings +- Add support for simple statements in useg attributes with the aci_epg_useg_attribute_simple_statement module +- Add support for sr-mpls bgpInfraPeerP and bgp_password in aci_l3out_bgp_peer module (#543) +- Add support for sr-mpls in aci_l3out module +- Add support for sr-mpls l3out to infra l3out in aci_l3out_to_sr_mpls_infra_l3out +- Add support for subject labels for EPG, EPG Contract, ESG, Contract Subject, L2Out External EPG, L3out External EPG, and L3out External EPG Contract with the aci_subject_label module +- Add support for taboo contract, contract interface and intra_epg contract in aci_l3out_extepg_to_contract +- Add support for useg default block statement configuration for useg epg in aci_epg +- Modify child class node block conditions to be optional in aci_switch_leaf_selector + +Bugfixes +-------- + +- Fix auto logout issue in aci connection plugin to keep connection active between tasks +- Fix idempotency for l3out configuration when l3protocol is used in aci_l3out +- Fix issues with new attributes in aci_interface_policy_leaf_policy_group module by adding conditions to include attributes in the payload only when they are specified by the user (#578) +- Fix query in aci_vmm_controller + v2.8.0 ====== diff --git a/ansible_collections/cisco/aci/FILES.json b/ansible_collections/cisco/aci/FILES.json index 5f5760ef8..f244e0907 100644 --- a/ansible_collections/cisco/aci/FILES.json +++ b/ansible_collections/cisco/aci/FILES.json @@ -130,7 +130,7 @@ "name": "plugins/doc_fragments/aci.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "631f5585bf747ab5c3fb044c2c877f21b459c06d7abdf3b3364c4be1b5d5e83d", + "chksum_sha256": "7b65fca7c78413da742eff21b6ae0c3b68cc4b87057705c4e66b49a843e5380a", "format": 1 }, { @@ -165,7 +165,7 @@ "name": "plugins/httpapi/aci.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "264746072bfde8e36623c5e266ad846c13d665f35d9180368a258c85c7899741", + "chksum_sha256": "1e7977fde068fe5c2a02f10b4b1ec65b783e4dddff0a63de46f6e8908fb6713f", "format": 1 }, { @@ -175,11 +175,18 @@ "chksum_sha256": null, "format": 1 }, + { + "name": "plugins/module_utils/annotation_unsupported.py", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "9284dfbf49459f5d06caddcd36e4417889946f8dab9a45d03b79ed4081614e45", + "format": 1 + }, { "name": "plugins/module_utils/constants.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "e15db3f08848a793cc4590cc19d160890d363b3f396d3e438b874e00e1ed9112", + "chksum_sha256": "cdfba5e66f41f3167b5a03a18d1aab7a4f90291b8e103ba344ce87c7dc62ea14", "format": 1 }, { @@ -193,7 +200,21 @@ "name": "plugins/module_utils/aci.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "1abc88c0d889479a346251e722ef7ad4e823d4eab9d326247fcc3af2865bf120", + "chksum_sha256": "3282cee20f7833d7a889920f9cbe8454f73f1128912d516131636560d09426e5", + "format": 1 + }, + { + "name": "plugins/filter", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, + "format": 1 + }, + { + "name": "plugins/filter/listify.py", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "7e17ad420086b785f6b4d724fdea3af70321e67f635fc96a3725c7da72b5c074", "format": 1 }, { @@ -217,25 +238,53 @@ "chksum_sha256": "6b68b735eb031eeeb4aa1cbf413009b37e144d084d4ead4f451c4eb9975a1c51", "format": 1 }, + { + "name": "plugins/modules/aci_l3out_floating_svi.py", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "0d35bd74046ae4e8b42a854062c74a6ab18314ddee2590b7325d8af72fc1020e", + "format": 1 + }, { "name": "plugins/modules/aci_l3out_bgp_peer.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "bc162cb93c76cb70063f916bc48f46326b3ee70aa444ef0f8c9a2fcfc8198532", + "chksum_sha256": "6230184c4b121cc5455fc641ce1275f128c63ac878c4b713cb4191622a7c264c", "format": 1 }, { "name": "plugins/modules/aci_bgp_timers_policy.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "3a449b3f6278ea5215c75674923e2c68e3219824866190a39e6af667e683f3c6", + "chksum_sha256": "015d871aab7f67a100475162beb125a51ef33054dee99591cfadbd4606c6c61b", "format": 1 }, { "name": "plugins/modules/aci_l2out.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "958ad0c1a52592bb969f139943c7d14b632ebfef8ce978f94a62418b01b9c476", + "chksum_sha256": "77bf806f40d6130a5218bfc4166d0c8cc4d09b0ca7e4a1272de9ae65f4416188", + "format": 1 + }, + { + "name": "plugins/modules/aci_l3out_hsrp_group.py", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "ca8bd82ccb564caba50c8ab1e6993d410fb2859ebd058d73de2357fd6142e707", + "format": 1 + }, + { + "name": "plugins/modules/aci_subject_label.py", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "8cec5a5f0fc0a7b3f22243b2aa7880094f7199830cccd9f65a7db1403699bdfd", + "format": 1 + }, + { + "name": "plugins/modules/aci_interface_policy_bfd.py", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "495f87cb4347a01889f6e3693731bd5b439f7f629282a785ff9a27b053d2bd6f", "format": 1 }, { @@ -277,21 +326,35 @@ "name": "plugins/modules/aci_vmm_vswitch_policy.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "2d6511c279fa09dd8e02de99fa09f2dc41dce4acd4a0729fc31f46fa1947365b", + "chksum_sha256": "60c932093daeaa29b19fb47f61e06f6e74e3a120376c6c43695d2d86fa95bcc3", + "format": 1 + }, + { + "name": "plugins/modules/aci_access_spine_interface_profile_to_spine_switch_profile.py", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "59585865eaf69e60bfabe97a3be44abe2b7662ff2d4fec127a578876a453bb3b", + "format": 1 + }, + { + "name": "plugins/modules/aci_fabric_pod.py", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "60fa6ec9851b3196c47ec816de2ec9fe22733e966d5f23365b03342aef0d5eef", "format": 1 }, { "name": "plugins/modules/aci_fabric_switch_policy_group.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "2f79ac032e25a85fc776be22cf03db453f83a6c130d11bd04bc5825e51b7fe00", + "chksum_sha256": "29ad2f038abd5b4f1c25bf7bbc9c040130224d9e55de8bc165aeec6b88b590ec", "format": 1 }, { "name": "plugins/modules/aci_l3out_logical_interface_profile_ospf_policy.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "22e305b0ab4190723cef3630013cacb40e10041143b10314be506b281f1601ee", + "chksum_sha256": "19d3ebf9e11120465f1ed070d7bef6cb1dd12112c6755ce98252299f9c007350", "format": 1 }, { @@ -315,32 +378,53 @@ "chksum_sha256": "101d246d0da768de469e06b2f20c172023edcb3a800f994d6dff3ea5edacea43", "format": 1 }, + { + "name": "plugins/modules/aci_l3out_hsrp_interface_profile.py", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "54b3b4e078f04024a8151020a2c83df600631c05d958e8af76154f39e7a0213a", + "format": 1 + }, { "name": "plugins/modules/aci_l3out_extsubnet.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "288b72fe6846b240950a7e41207ca0f8873bde6fdde7389fd43590904ee1123a", + "chksum_sha256": "536d3512e9e86a3cefb778fbe5d16134431aefb31433c9d1a264ccfb8c88fd6f", + "format": 1 + }, + { + "name": "plugins/modules/aci_key_policy.py", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "5331c810eb3de36be04afd7d0e3430a3b219c151fc306dba7b36e313845554c1", "format": 1 }, { "name": "plugins/modules/aci_l3out_logical_interface_profile.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "49e176ad8ece44f6c3d1e76e3ca82edfd005de6921d51171290262af06414aed", + "chksum_sha256": "d7397ff1210b6a004f8593ec42c5869e08734e7088991f62026e304e095768df", "format": 1 }, { "name": "plugins/modules/aci_l3out_static_routes.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "a75ad5dbd6e8eedce392adc2ccce2d2777d1aa60558f6ffc2a713840dde492bc", + "chksum_sha256": "4ab8c960de06bcd0202b6b84b7ea868cd4c88db2dfc5d6c2dcf66feaf24c1aeb", + "format": 1 + }, + { + "name": "plugins/modules/aci_interface_policy_pim.py", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "52e89ba2b37afd4018ea79621c07859625de0a69e24c05487ee061812bad8383", "format": 1 }, { "name": "plugins/modules/aci_epg.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "781272f3b994f159af0db9270b8a025ad8fc0aa626a137c5efe08ae8b2a85528", + "chksum_sha256": "ad8710ddf7761e66c3e72ce15269f95cc32697043de0df9eb349d3d301088197", "format": 1 }, { @@ -361,7 +445,7 @@ "name": "plugins/modules/aci_cloud_subnet.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "8d0025ef8ff2ceed859856f5eda8b3d1c9f15dd2d9d03e9c8787d2170133df88", + "chksum_sha256": "82263cfcf517105743790db9b882f8af315bcb380365aee9b321baef5575b155", "format": 1 }, { @@ -371,6 +455,13 @@ "chksum_sha256": "f1993e5ecd2b23c0a89eae972b51fabe0b3a694db2177bb6daa07e37b76195a0", "format": 1 }, + { + "name": "plugins/modules/aci_aaa_security_default_settings.py", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "d25c37a12f38c242709ae3bd0a21f8b6ee08bb688ced8ad118e68164bc9ab66b", + "format": 1 + }, { "name": "plugins/modules/aci_cloud_bgp_asn.py", "ftype": "file", @@ -385,6 +476,13 @@ "chksum_sha256": "a88505933cd7888031ac5463975ecc9275f33c1a58c45cb717f571f4e7d3e943", "format": 1 }, + { + "name": "plugins/modules/aci_fabric_pod_remote_pool.py", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "e0603a1de36f21cb899768bef43bc8bc1ea9c639bc31fb1ed99e76077212e3db", + "format": 1 + }, { "name": "plugins/modules/aci_config_export_policy.py", "ftype": "file", @@ -392,6 +490,13 @@ "chksum_sha256": "7d594a026f5432f6a58452219ce041bd1cc1d5c6dbcf20a2687623dee1057710", "format": 1 }, + { + "name": "plugins/modules/aci_netflow_record_policy.py", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "f3617ef80418f9ec2dfe73b6516f283db4ac42c96cfaa522a1ce48dee9200c2d", + "format": 1 + }, { "name": "plugins/modules/aci_firmware_group_node.py", "ftype": "file", @@ -410,7 +515,7 @@ "name": "plugins/modules/aci_fabric_switch_block.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "e89b14e86fe4503938daf4afa708f59283bd2c16fa7c2479d37c27daefcea30b", + "chksum_sha256": "e17bcc09f6cf73ed433035cb598c371dd42f0e4f264db8072c70a9fe86baba30", "format": 1 }, { @@ -424,14 +529,14 @@ "name": "plugins/modules/aci_aep_to_epg.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "a4fde4781f4ecfba7cecddf11cd1a84f5962076214e0fe4869891c6ed030e803", + "chksum_sha256": "aece66c7de89a624b930ba13f68a17d7f0bc04427e06731bd2222a30b9e048d1", "format": 1 }, { "name": "plugins/modules/aci_config_snapshot.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "d73660d7443d035f9af9602b69fa9d68bb650f9a746879c79d0f152cd8b49726", + "chksum_sha256": "09f9c15833f527017def13d8ed456740dc4faa58c34f6a7966adf1578e08d5d4", "format": 1 }, { @@ -448,6 +553,13 @@ "chksum_sha256": "90c73685a5171da49f2debab4521bf98ef5fafa2ec356231e7c88b7dc5f2074b", "format": 1 }, + { + "name": "plugins/modules/aci_fabric_management_access_https_cipher.py", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "3df7b6bc4f3bc25152578626e5340f963d437f039cc3a5d0ae01d395552691b5", + "format": 1 + }, { "name": "plugins/modules/aci_interface_policy_lldp.py", "ftype": "file", @@ -462,6 +574,13 @@ "chksum_sha256": "938ed82e982e1fac1b4c1aa35d952336cf466ec2b2ee5efcdb1107580698a491", "format": 1 }, + { + "name": "plugins/modules/aci_access_spine_switch_selector.py", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "4ea8c998b34d2cf76fab5b08a6b8b7e9ad4281f5371cd136bbc4874f69b38cf9", + "format": 1 + }, { "name": "plugins/modules/aci_vmm_uplink_container.py", "ftype": "file", @@ -487,7 +606,7 @@ "name": "plugins/modules/aci_vmm_controller.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "bf296cd7457a775c3ac07f5a1c902b2f498a85eb4c50193289dedc42eea12d93", + "chksum_sha256": "9775c2e58de346c098000bee99bd4bc0e9c8d06a4fb9978dc774a069bec4f0b2", "format": 1 }, { @@ -497,6 +616,20 @@ "chksum_sha256": "b1be616239d72fdd5c256c3055f397064e3d11b9a226445d2985146687ca691b", "format": 1 }, + { + "name": "plugins/modules/aci_netflow_monitor_policy.py", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "eb45e05e3709d7b4b8992e7c50e2be654ea12726fcbf57294cc381e34a269a8b", + "format": 1 + }, + { + "name": "plugins/modules/aci_pim_route_map_policy.py", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "f1834c534a4e766e6d764624062eee4bfae8001ea4186ab98ee13680501e6ed2", + "format": 1 + }, { "name": "plugins/modules/aci_static_binding_to_epg.py", "ftype": "file", @@ -511,6 +644,20 @@ "chksum_sha256": "ff84b7b4c411fd6417176718d1fe26c1d3604971f98e3138701165f168ba5af7", "format": 1 }, + { + "name": "plugins/modules/aci_bfd_multihop_node_policy.py", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "a839a695a5cc5ed226cfb1e2fc4c0bafb61dfee0fed1a6511009f772982120a3", + "format": 1 + }, + { + "name": "plugins/modules/aci_access_spine_interface_selector.py", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "424c59598ca97012cca166facb8c2fb92640cdfff53efc4270f128025833b640", + "format": 1 + }, { "name": "plugins/modules/aci_match_community_factor.py", "ftype": "file", @@ -522,14 +669,42 @@ "name": "plugins/modules/aci_fabric_interface_policy_group.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "f991680f4f3b96c2f1256317a457adfe5b736fb245e6b312f6faa1ee2de81d1f", + "chksum_sha256": "a6a8b078f9e928ee90d5e581e71b4b95baae1474664b9862af21e9c9dcd3d1ae", + "format": 1 + }, + { + "name": "plugins/modules/aci_aaa_key_ring.py", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "eb2f41677668c1867218aad70a0067041771343e49c2d24d46642ac212cb9f9f", + "format": 1 + }, + { + "name": "plugins/modules/aci_l3out_floating_svi_path_secondary_ip.py", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "af11de2dd6e1db6a25b6e88f0d9c88040838ec9f82523cd23725752ddcb6cccd", "format": 1 }, { "name": "plugins/modules/aci_l3out_interface_secondary_ip.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "4143a680247b3bd6f7a924b053464fc3d456e5ffb1ef4e2b0d21164b2132b7c8", + "chksum_sha256": "b73391a4d77efc3fe3715d6f75bdaab2cb8aa43164121c14f90a5d910208eb2f", + "format": 1 + }, + { + "name": "plugins/modules/aci_interface_policy_hsrp.py", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "343f4f001a77cf8cd7097e68c287fe7359b701168805b63e54e3e5e57c1e1e35", + "format": 1 + }, + { + "name": "plugins/modules/aci_qos_custom_policy.py", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "9c2c544a1e8094ac3475730d422eed1c262ed68aabd59a10b41cc7a812e32c83", "format": 1 }, { @@ -550,7 +725,7 @@ "name": "plugins/modules/aci_syslog_group.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "d6d6fcb23b4e3878c90a9498e6dc0ca0784e9115bc7003530d7e5b9b340e714d", + "chksum_sha256": "62fac942a3cf0956bf262280a23e48f7b55bd251e5eb8974cde8d443358ec848", "format": 1 }, { @@ -585,7 +760,7 @@ "name": "plugins/modules/aci_l3out.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "7671c4aa2a641a1f9c2a3020d9577b876edcee0533dd44da8b6e14177f48aa0c", + "chksum_sha256": "b569169142b8ad83fd6181123bd2d3f1822b16dc78771c506b6ea3417ef904c5", "format": 1 }, { @@ -595,18 +770,25 @@ "chksum_sha256": "ad1059205a850876d017993164033315d59d2999643906c3939aadcb4db1f72e", "format": 1 }, + { + "name": "plugins/modules/aci_fabric_external_connection_profile.py", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "abf23c7cdf2c2c6960bc445393a5331a1d4cde0b7f74608fe6d23762f177cb9a", + "format": 1 + }, { "name": "plugins/modules/aci_interface_policy_link_level.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "278b8caecae9575eefe1304bdf7fc1f70d3d28106394d4b4a20b678380e3eff6", + "chksum_sha256": "1919445dcc2c225f2b47ba8393f4d35a97b609e8880a2e757a6b29ea1d26aea7", "format": 1 }, { "name": "plugins/modules/aci_switch_policy_vpc_protection_group.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "a3885f31f00ae77d15576acee774d806d9910a11e5428483bb505cf44a98d4f0", + "chksum_sha256": "3c5aa5e987f844c0c229be29cb0072b31a7bd9f93a35556db5eb02a89d5468b5", "format": 1 }, { @@ -620,7 +802,28 @@ "name": "plugins/modules/aci_tenant_action_rule_profile.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "d37d41527ebd97ddf17cf2dac2579f3354a66a0be88132906533d21903873bce", + "chksum_sha256": "19bc6a49ef84a301e2b8b2fbd74542123d9cc5b37dbfa949e16aa2f29d49989a", + "format": 1 + }, + { + "name": "plugins/modules/aci_keychain_policy.py", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "f5f5fb5e5c92120f68b0eb323cee3af0552c398b870bff35ea1e96ee8b7babee", + "format": 1 + }, + { + "name": "plugins/modules/aci_netflow_monitor_to_exporter.py", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "f4376283e5cb6a4319e97aa383e392e97a8d424a0f8183d1231ad6695f7f1ee7", + "format": 1 + }, + { + "name": "plugins/modules/aci_fabric_pod_profile.py", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "126aa5e445d1210b0982cd31702c87272132816fcf62da28f80aa0b20b45eb3b", "format": 1 }, { @@ -630,6 +833,13 @@ "chksum_sha256": "fbdb0c2bccee0fe31eac303cff164f7e3f65b6fbaa8ac7be23fb500ee744845c", "format": 1 }, + { + "name": "plugins/modules/aci_fabric_management_access.py", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "f5646061904b187169fdc2103a53cdb784830f6a146a27623d2a3099db9e28ee", + "format": 1 + }, { "name": "plugins/modules/aci_interface_policy_mcp.py", "ftype": "file", @@ -644,6 +854,20 @@ "chksum_sha256": "1cda122f6d761e6a8038ab994914079056c1f24b9a3aa9b363f1e8d6901bab7a", "format": 1 }, + { + "name": "plugins/modules/aci_interface_policy_storm_control.py", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "883a2e6cb3a57acf3a588d2db08ca27804bb7a9236462564cbf279fe0cf8edd4", + "format": 1 + }, + { + "name": "plugins/modules/aci_l3out_hsrp_secondary_vip.py", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "e1f9bb7b762c822152b26dd8731a9a2feca5246484373c0af18158b9fafc1410", + "format": 1 + }, { "name": "plugins/modules/aci_maintenance_policy.py", "ftype": "file", @@ -651,11 +875,32 @@ "chksum_sha256": "cc16c435345467c701db77796f79085b83114454d4534588c16551dcd28b6f4a", "format": 1 }, + { + "name": "plugins/modules/aci_action_rule_set_as_path.py", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "8481d6f2c98dbd7307632bf1827c98899a0e4815adc90c6ad3d0ebc8889503e5", + "format": 1 + }, + { + "name": "plugins/modules/aci_l3out_floating_svi_secondary_ip.py", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "b7ea4286b273b5ed12d10a64deb906e6ee8a1a21cb2f1d38aa85a09a77012178", + "format": 1 + }, + { + "name": "plugins/modules/aci_netflow_exporter_policy.py", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "ed6829e37facedf366e30bb62e6445828d1e059da1a9397c31d36814c6f91961", + "format": 1 + }, { "name": "plugins/modules/aci_interface_policy_leaf_fc_policy_group.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "25f72bb8b07c4ce0caf364f5b8413e43bfe6b773c54414fa4de8f64c329dd0d9", + "chksum_sha256": "584358125ebaca48bcd0b12518dacd2d240ec1733b47e09eb8fa8fd6f8459f4f", "format": 1 }, { @@ -707,6 +952,13 @@ "chksum_sha256": "8d9925ec534dcaa27a1d21df95ea096fe3b68a981833d6661ee62190d7155180", "format": 1 }, + { + "name": "plugins/modules/aci_interface_policy_bfd_multihop.py", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "ee8a3a4553759ae8b7aff848da1a545640e5864598fd08f55f72eaf0ae4af036", + "format": 1 + }, { "name": "plugins/modules/aci_match_community_regex_term.py", "ftype": "file", @@ -721,6 +973,20 @@ "chksum_sha256": "51eccf37889832ae2284b28cea4fa1f7c40c9c293e9ae5c4bb1f125aba4733c5", "format": 1 }, + { + "name": "plugins/modules/aci_epg_useg_attribute_simple_statement.py", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "13086f90a8cd3289cf4a12411df900a2dd0c71c91e5edd23058477bc18c2abbf", + "format": 1 + }, + { + "name": "plugins/modules/aci_l3out_to_sr_mpls_infra_l3out.py", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "4a2b7bdabfd0f619a81db44a371d8fd5598b7edce8897093a49ec6a11f9bcd83", + "format": 1 + }, { "name": "plugins/modules/aci_access_span_src_group_src.py", "ftype": "file", @@ -763,11 +1029,32 @@ "chksum_sha256": "61ca3965bfbce19ef1a2aaf3ed41d7fecf187f06563acf4db3fb4ae9373ad736", "format": 1 }, + { + "name": "plugins/modules/aci_interface_policy_eigrp.py", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "8cb76d40339c358a157f9597e58018d5bb31d609c7e43ba89faac5eb9120b75e", + "format": 1 + }, + { + "name": "plugins/modules/aci_dhcp_option_policy.py", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "131c02cd148c86d322dc1db79eff8d86f20ac3288524e7203d082b065008b8fe", + "format": 1 + }, + { + "name": "plugins/modules/aci_access_spine_switch_profile.py", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "a4c972ac6d6648f531a6a8b815519d629dda2cacf1cd505e4cf96063b8fa8ce9", + "format": 1 + }, { "name": "plugins/modules/aci_epg_to_contract_interface.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "fb50ec097036f21192f0aa2bb0a16bede660d27ca942fa1862d2dbd98c7e0152", + "chksum_sha256": "c5913cdc2dcad978148a85a9029efb3234cedf328597399f0d90ac6d549eaf38", "format": 1 }, { @@ -795,7 +1082,14 @@ "name": "plugins/modules/aci_bgp_rr_asn.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "59522a6145c69f4e8f4d09c8fd4ee18a486d00f9cf4a6d5ccbc3b2a4133566f0", + "chksum_sha256": "8f37a10fa7519a267905ab216b4c6e8c76c14534829980dd3fecf2f3bc1bbf4b", + "format": 1 + }, + { + "name": "plugins/modules/aci_bgp_route_summarization_policy.py", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "6c642df7ecae79f991df54171c93fa2fac3357aaabd126b268772bd59748089c", "format": 1 }, { @@ -809,28 +1103,28 @@ "name": "plugins/modules/aci_dns_provider.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "22da1c0c3345aee698ec847a3c5c7ba274cacc611aea019236146ac20e279710", + "chksum_sha256": "b8a0867a23eb8bcb678ea49155f778865827a2e7fa3419fd43eea5ed9ffa1451", "format": 1 }, { "name": "plugins/modules/aci_snmp_user.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "90dd375a7441d6b293b0d889310f157a97d186ca8504cc3245da41a5eef8853a", + "chksum_sha256": "2b155074d3a4afd46c985baab1896080a95ed8c90f08821deaab2caa1ed41e3c", "format": 1 }, { "name": "plugins/modules/aci_l3out_static_routes_nexthop.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "f889ee4b222b52f2dff2baaa761ca75389be7726ce6a29e792c12ad681118877", + "chksum_sha256": "5a878a58f8a8edb7aa866014b592011a8321f7a12683e6a8fc2052731e80cc07", "format": 1 }, { "name": "plugins/modules/aci_epg_to_contract.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "76904fec70dbd9f81804ee9e56c9a0b868df226e924a586b5aec05950e3b9632", + "chksum_sha256": "050d9470762d02ce29a822a5d1ad5d9ab67cba1cc48e8ecf3de9de79d8dd4688", "format": 1 }, { @@ -844,7 +1138,14 @@ "name": "plugins/modules/aci_node_mgmt_epg.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "f17f5d0fd7d030d1d9edeac7e9748b3a27b137ad388850b8de847dad9c2458e0", + "chksum_sha256": "70dffdfd3c91be40c1b0840295f00203a74fa50e1cee529a3482c8d53f008e7a", + "format": 1 + }, + { + "name": "plugins/modules/aci_vrf_multicast.py", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "581d3cffb9571e14fb789d4c916d111d28a04e27a0c5cc288da7db4b295efb5a", "format": 1 }, { @@ -865,7 +1166,7 @@ "name": "plugins/modules/aci_encap_pool_range.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "0faeb5ce1485c0d0ef993c58de5eb8c7056b5c6964ee9765b9e4ee45049e905e", + "chksum_sha256": "0de6a9ab1a4839f6d85a92697985a764983bd27ef54b7fd1f5d90cf5aba54961", "format": 1 }, { @@ -879,14 +1180,14 @@ "name": "plugins/modules/aci_dns_profile.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "294401dde010dd3af324f0e4073db27b96c4e557b83ff801d41ff62ed47a32f5", + "chksum_sha256": "240fc467c21956eb1554d0e1fbb8367e4134321044cdc5e141a455511eb8b970", "format": 1 }, { "name": "plugins/modules/aci_vzany_to_contract.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "f8d0beb41985eea0fbb07c65f97a79d19ad6f1a526ae9e0a2fbc024371a63a93", + "chksum_sha256": "77e5d6cc4c8be1908de624deaa8b809447c2f01be6ea51e1a61d38d8c4cbc014", "format": 1 }, { @@ -900,14 +1201,14 @@ "name": "plugins/modules/aci_contract_subject_to_service_graph.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "68a1fe769d6506da41abc49090fc2d091d54601350f4cfbc371e01813f52619b", + "chksum_sha256": "765b3cedfcacdc7aeda746fce702297a7dc394fcf1fb40f9e05d58101a6a5237", "format": 1 }, { "name": "plugins/modules/aci_syslog_remote_dest.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "905f5f4286c4f4d306e9e174c838e71dd8027f751873d765bcf2671659a0ee30", + "chksum_sha256": "7c47bc88dddb0ab6a92f15ec802f499f0c6b11d86de09ef8b6477b3e91c39c56", "format": 1 }, { @@ -921,7 +1222,7 @@ "name": "plugins/modules/aci_system.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "bc0bdacedabcc2ac5372c22b7f4afcd58c2f1644c5843100d6d0331c022b79ad", + "chksum_sha256": "1ed52493e2d498a3a9827b273ef243188b2f6bdafe543caf5a93d33820924a54", "format": 1 }, { @@ -931,18 +1232,25 @@ "chksum_sha256": "a2245b78051930e1939be20957cef47b177c7a5132fe18971e95db197080fcbf", "format": 1 }, + { + "name": "plugins/modules/aci_pim_route_map_entry.py", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "a97b14e38a6d547f8872a7048d3a8d1bd80efe1eb71538e99bf3b3b0f34a8aba", + "format": 1 + }, { "name": "plugins/modules/aci_l3out_logical_node_profile.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "6e2104cbc94406fc36b5ce27f76c924f18c8199db79c4efdfcdc6ffb8ab07f94", + "chksum_sha256": "5510c4c25e12b0686cf30d60b5a0142999311a7c197b5e753d08ba55b3d5cabf", "format": 1 }, { "name": "plugins/modules/aci_maintenance_group_node.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "50b579ec246dd92a298d9438d1a127ec616c08a702cd744f3eebb5af12c5d352", + "chksum_sha256": "37669228be6271810e4ac87fdaf3287f4306e4a20f2e7fed7e54388d7b357f13", "format": 1 }, { @@ -963,7 +1271,14 @@ "name": "plugins/modules/aci_snmp_policy.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "302dd819fc6a454d2f9ec5cd124ed0edf6ca7e56de79dd8f5a6302bff7217c85", + "chksum_sha256": "1c72b7b6ca528952b96c103086545f8d1d66315ee68a77f190fc903d2413c494", + "format": 1 + }, + { + "name": "plugins/modules/aci_l3out_floating_svi_path.py", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "ad30f623b290629e4e9dc40c02dad2bc6af381afb653e60b3e2bdc7b1538608a", "format": 1 }, { @@ -973,6 +1288,13 @@ "chksum_sha256": "3090836575849a21c16126d8a7ff50073c287a008b38501e2ed1e69307ac2bce", "format": 1 }, + { + "name": "plugins/modules/aci_action_rule_additional_communities.py", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "62042dd3a37e6fba520ca06511070f6788d1de04f1ba63c68414c38a4cc541bc", + "format": 1 + }, { "name": "plugins/modules/aci_maintenance_group.py", "ftype": "file", @@ -991,14 +1313,14 @@ "name": "plugins/modules/aci_tag.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "7cef96d7872d8c72eec261ae88fb365d3357556d78192922f9e31bac6eddc2e8", + "chksum_sha256": "73904792f99df2cf754f07483f4c1975e9edbd54855d7abb759018c96d6c48ce", "format": 1 }, { "name": "plugins/modules/aci_fabric_leaf_profile.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "e7c47a9ae33f2601c3ebb18fe7a91c1428cf2b1e532bfe41989676e9dc5fd1ab", + "chksum_sha256": "4de73c2a8019fe586fb5bfa3f615626e863ee1719aa792e71a431d9bc83c33a8", "format": 1 }, { @@ -1012,14 +1334,14 @@ "name": "plugins/modules/aci_access_sub_port_block_to_access_port.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "68cd3d4199900db287946625f5caf7a661a1d8ec3dfaa6fb40028b637b3621df", + "chksum_sha256": "cd1610b19bb027fe8c6091fe9522637cec9e34a0cb00150de563d4c483548785", "format": 1 }, { "name": "plugins/modules/aci_match_route_destination.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "2e07f2b93fbad18f038cb0a3c9b417f02b1b21993885387d696ddeb9f99dba6d", + "chksum_sha256": "a64cb8eb6a3919778589c1b81104e00878921ad1f5c68acff25b78b6e25ae57b", "format": 1 }, { @@ -1029,6 +1351,20 @@ "chksum_sha256": "3e8f55259a42e3c2b495a85713441f4018e5a3f69210bf9eab5b0cf02601db0b", "format": 1 }, + { + "name": "plugins/modules/aci_aaa_certificate_authority.py", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "175f89268110ca497db26e93c771fa89bde956fe9cf992469d7f935116ebd552", + "format": 1 + }, + { + "name": "plugins/modules/aci_bd_to_netflow_monitor_policy.py", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "dbb43bf7a2049326223bc2a9f63584d7a923f35686b57a287bde8525cae2c151", + "format": 1 + }, { "name": "plugins/modules/aci_bd_subnet.py", "ftype": "file", @@ -1036,6 +1372,13 @@ "chksum_sha256": "58930e496a02c5b5edc9d629dc6947490aac1cd8062cd3a7a0947f0a86802445", "format": 1 }, + { + "name": "plugins/modules/aci_l3out_bfd_multihop_interface_profile.py", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "9ec885be4029b15e68d843ab5942a6b502bb2371142a31f8e3508239a293c37c", + "format": 1 + }, { "name": "plugins/modules/aci_cloud_zone.py", "ftype": "file", @@ -1047,14 +1390,21 @@ "name": "plugins/modules/aci_encap_pool.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "df4e00a21d863e612eec8ed91475e7431b8dabe150ee2d5b45ff1ce3ec7a3dc6", + "chksum_sha256": "3b5ed6ee619ff7f0308055d73e0d553919e6a298e75e93a219e9a2139509e0c3", "format": 1 }, { "name": "plugins/modules/aci_bgp_rr_node.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "b09067780ee01cf7ebe73e2ec29f9a66a01d72e330f10ed7c9a6591e7f0bdcdd", + "chksum_sha256": "aa5946d37e2f660a5a28221a5e99df03f37f41c740bff72543bcc18406af128b", + "format": 1 + }, + { + "name": "plugins/modules/aci_fabric_pod_connectivity_profile.py", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "53481b562d99a323f056474293d7dd9f25189bca7d897018f0b96eafbcd2ee7c", "format": 1 }, { @@ -1068,14 +1418,14 @@ "name": "plugins/modules/aci_dns_domain.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "b134b414207d3eeb255ff7bf016bdc75e169a0a3d137cb2e84cc319c3fea462a", + "chksum_sha256": "2dabb5042cdd2b96f643866f8a638c2dc5d8f3eda1acbdb94f1f88c5aa0d2abb", "format": 1 }, { "name": "plugins/modules/aci_fabric_wide_settings.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "14ae98b14724769b9dc68d8ba82a05a4822638373908bd35ac22124d4190aa76", + "chksum_sha256": "2ac4257982f31954248f2cb3d1b6946fbe39db07ce606b5eb17449bd6ee1e05b", "format": 1 }, { @@ -1085,11 +1435,18 @@ "chksum_sha256": "766783e2df7476a4de43d95f3f5fc163d32e92391fb84b4a3e52f5329d843d49", "format": 1 }, + { + "name": "plugins/modules/aci_action_rule_set_as_path_asn.py", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "f4ae65464969acb1fb93e75d47f0b044349f9fa62e9cb3fed0b762f0318ba2d4", + "format": 1 + }, { "name": "plugins/modules/aci_domain.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "82ec99a3dcfd6d626929e943b62a60fc60d5dcb2f686d4b9fdb5e00d5c9f959d", + "chksum_sha256": "43c2b0fbc8ca6096e52d35657922fae229ab88228b1ed6f482f7821a66426d05", "format": 1 }, { @@ -1103,21 +1460,21 @@ "name": "plugins/modules/aci_access_port_to_interface_policy_leaf_profile.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "bc69261f8fa08ba96021350c055a15a24c9b5f4d1ebdc5cd1811c35667c5005e", + "chksum_sha256": "3734300218e78b60c54f26197a5ef5b3c63f42e6a5f7d63d3dd8d7fc6c48e207", "format": 1 }, { "name": "plugins/modules/aci_l3out_interface.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "bf8af029c86fec511b9786c649cb44d4e91a3a10886cd224f04df5b589fe74a1", + "chksum_sha256": "8289da6e31326a2e57ee57f0f3e491b104535144767a6418b193d2b60757da4a", "format": 1 }, { "name": "plugins/modules/aci_fabric_spine_switch_assoc.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "c487540b110788907432a425b89e2c6fd58fc1da3f3bee9fe1097ac466e1e5fa", + "chksum_sha256": "de20dfa79cee8adb14d7f14a2cf96cf84c8ddb91914adab0d934e4c11441d975", "format": 1 }, { @@ -1131,7 +1488,7 @@ "name": "plugins/modules/aci_l3out_extepg_to_contract.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "cd9f2e1c4feb2932e7266c6a15164ab478c781d48345a062b825d7cc84613d66", + "chksum_sha256": "7dde1c1843012dd6090ef6c404e319bb2a1f341970be266df1f711c5bcc3320f", "format": 1 }, { @@ -1152,7 +1509,7 @@ "name": "plugins/modules/aci_snmp_client_group.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "c2afd339ea34f7668be627fb2e602a2fb7a4e642c3cc71420538121a5e554543", + "chksum_sha256": "b5ddf25075717b014b7e11aac5add45dde17b597d1ad36c7248ad8af882bfb3b", "format": 1 }, { @@ -1162,6 +1519,13 @@ "chksum_sha256": "562b639ecebe39eb545fb81fb18e0fecfd4227ab2f261ce061b7c890c1817faa", "format": 1 }, + { + "name": "plugins/modules/aci_access_spine_interface_profile.py", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "d1c73e641df78bfec90dbd312ab869d1d187baa079212ddb0e792a3ad393747c", + "format": 1 + }, { "name": "plugins/modules/aci_aaa_domain.py", "ftype": "file", @@ -1173,14 +1537,14 @@ "name": "plugins/modules/aci_access_port_block_to_access_port.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "bd2a7549ccfde9bc363e236629f64fa1bdf3ce402ae58ad7d2793beabb87673b", + "chksum_sha256": "bd80caf580b0e53bbaf6a8d0f6d3349c95e3c6d92f6b17e45cd0ec60af2d98bb", "format": 1 }, { "name": "plugins/modules/aci_ntp_server.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "eebd5403f803ebda15e9e15837f2e18afc66d6ebc0be58c44ed59520c87d9c52", + "chksum_sha256": "bdc611ccd63d213752849eef2a4f6403dd06f70d1ad811f6633ce3426324221c", "format": 1 }, { @@ -1190,32 +1554,46 @@ "chksum_sha256": "fd90fe8bcaf26e0a4c8d990439431a503d96cb844b1c614a46bf8563f6b48381", "format": 1 }, + { + "name": "plugins/modules/aci_bgp_address_family_context_policy.py", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "0ca03c2c9610ca1ecd91c13d7c42275498a2bb6bbd5a32052e34aed11ee1c863", + "format": 1 + }, { "name": "plugins/modules/aci_rest.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "a3e4869643545856630c76bab8af0c1e8a71ca3b4af7ef29a79b88c1ed2464f2", + "chksum_sha256": "ff743d38c1cff2c95843d9c22440630cc820d68f1345b598929820d02ac87d77", + "format": 1 + }, + { + "name": "plugins/modules/aci_access_switch_policy_group.py", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "9097a019442b974bfa9b66f9a9b52d900707021c5fa6fd404554d4908399acdf", "format": 1 }, { "name": "plugins/modules/aci_fabric_pod_selector.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "fead1bdf7c39203eb394f8fd96f7a454ed89de4d40206e3c735d6b5e870ec58d", + "chksum_sha256": "2c37c8c8724cbf21fced9e5ccd61696f40a3987056a64c06060f1c8ffec09b9b", "format": 1 }, { "name": "plugins/modules/aci_l3out_logical_interface_vpc_member.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "11a04697b9f93535d17b035bbe07954b47cad7c37673b8e9a5f0d8a1caf9bc31", + "chksum_sha256": "773e5486d8340dfa66ac727526218fec9cabce021a4dbb55eff26051c3b9ee2c", "format": 1 }, { "name": "plugins/modules/aci_snmp_community_policy.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "e29a26e77c7937e97e5661668e6cbdcb023334deced1d1767a5cfb90fb922fa7", + "chksum_sha256": "bf4b1bee0f6a15876bb7758d4c8f5b1bfbfa6d9625102e79bd19417d31b051d4", "format": 1 }, { @@ -1229,7 +1607,21 @@ "name": "plugins/modules/aci_snmp_client.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "320ed5765b8ea502dcf17a88651195079919eb5be623bb2332f926137fd989fc", + "chksum_sha256": "512a2ff7cdc3d295258eeeac297170e947a2b33729361e610114cf2432417da6", + "format": 1 + }, + { + "name": "plugins/modules/aci_qos_dot1p_class.py", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "d5054b5fbc6ae9dae9376d9d593eb41b0e3d6581e33ac2030ef474b69d4eede8", + "format": 1 + }, + { + "name": "plugins/modules/aci_epg_useg_attribute_block_statement.py", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "42aba45c6d80cc81da6b648f580fbf76be12a05e9c87acaeb755bd48a6c1717f", "format": 1 }, { @@ -1239,25 +1631,32 @@ "chksum_sha256": "61e92079ef547b98c9044b5ccddb60f710119b4061b758ad961402ac774f27c6", "format": 1 }, + { + "name": "plugins/modules/aci_qos_dscp_class.py", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "ccf605015cb3e075584197ce8e25b5db1b423cbac2849ef11849d5de753b75e0", + "format": 1 + }, { "name": "plugins/modules/aci_l2out_extepg_to_contract.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "9f2f4735ce7eeb926b98b1f4f0ad67a091e361e6a6eec007bd81e14659f2e527", + "chksum_sha256": "e88b27fe70d104e83209fb1077c32c25f7a8e791f189c3569ee6c03c9f4d5ae0", "format": 1 }, { "name": "plugins/modules/aci_l2out_logical_interface_profile.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "ef3ac4c31c8b128b7fc206f13e6a268a8e43e0b17bee5a073d9d9b2349a2d5b3", + "chksum_sha256": "2e46597067c3945e05d3cfa7f725d3873a476ceae0212b0ada6cca8b57f586d7", "format": 1 }, { "name": "plugins/modules/aci_l3out_logical_node.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "762ecc6681dab6e00794b8567a1cbadd5bd42ecdc6ab7af60f9b151d89e4a908", + "chksum_sha256": "6f665530114856a27ec52757da35b756bca96a5e8ed557bc26914783f145c88e", "format": 1 }, { @@ -1267,11 +1666,18 @@ "chksum_sha256": "7450320a7b99cde39c67dbb4357057f126b006f31e9a902fcfd6c6befc574c7c", "format": 1 }, + { + "name": "plugins/modules/aci_l3out_eigrp_interface_profile.py", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "382374fda6f15ff1ff50447cf256f9c68678e45870246d95d6b36a5438841aa6", + "format": 1 + }, { "name": "plugins/modules/aci_interface_policy_leaf_policy_group.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "606a16df31e90d074ff9c9c4e2b1cff46c7a2da68f43cc356a26aed1c4d2ee49", + "chksum_sha256": "8144a7e12b9ec8de017cdb71878219e53afed451faa1ee7e66f0f39379986db1", "format": 1 }, { @@ -1285,7 +1691,7 @@ "name": "plugins/modules/aci_ntp_policy.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "93beb84bcc3d2e9de66ebe55e076a3b0f5e2fb5a16b80d81d39f214d09b53924", + "chksum_sha256": "1d75cb4af507406070bd26eff775f7099c6037fabed8ce4bd6880aa614a27184", "format": 1 }, { @@ -1299,21 +1705,28 @@ "name": "plugins/modules/aci_aep.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "3a9b1d886d17fc8bfd05b4f324b6aa8fd6f6afd8496a9d5170077e30b6b7627f", + "chksum_sha256": "7ce0cce80492d93272720502499552464f587d76367a981619c268211bdc6990", "format": 1 }, { "name": "plugins/modules/aci_l3out_extepg.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "bcfd941ee89b3956e4f76b203ab20bdbe40c4af72e1c363e300447ac4ba81209", + "chksum_sha256": "e5add6a6372db4115a3e5d6d9c7433ecff48ed7cc802ea428176829bf87e437f", + "format": 1 + }, + { + "name": "plugins/modules/aci_fabric_external_routing_profile.py", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "82e146d037e0dcff8100d789ad1fffc8c2a624ec3a180c0d8b0f6cda4fc706df", "format": 1 }, { "name": "plugins/modules/aci_bgp_best_path_policy.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "866b0ec86a66ff6e2671e3127a60b11807d3fea75825576a5ebb72ac4cc4fd11", + "chksum_sha256": "2510955f815b08674acd4e7978f137f80358f5ebe7e8af98923fa7e0e1589e14", "format": 1 }, { @@ -1330,6 +1743,13 @@ "chksum_sha256": "95956d8a6861e45fd56fc9e15bd78673ca0a4f225b131b5a60898841f4d94c8c", "format": 1 }, + { + "name": "plugins/modules/aci_bgp_peer_prefix_policy.py", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "ab1a7aaaab66a46f3e6ac4ac12eb605ee07a829a45f7e327e98aaa9a36e5909a", + "format": 1 + }, { "name": "plugins/modules/aci_cloud_external_epg_selector.py", "ftype": "file", @@ -1341,7 +1761,14 @@ "name": "plugins/modules/aci_fabric_spine_profile.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "04b2937317e9cb6e30a2c835cce415d2056a851241e25421bb07b30ea766309d", + "chksum_sha256": "05d3ecd4a6829756cd205a2b4ef03f36ce0a6551a7ac2039d15ba0e74d615bb3", + "format": 1 + }, + { + "name": "plugins/modules/aci_node_block.py", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "d068826d6cca43d36f3dc6bec7971167bf4a17b5313ae3f2d698d4d6785c1952", "format": 1 }, { @@ -1362,14 +1789,21 @@ "name": "plugins/modules/aci_dhcp_relay.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "eb3bd3dc51d09790c499266a64790bfc40b6c0c87a9d4d9849f73aead09f6e96", + "chksum_sha256": "63c43d13b7b052976cd059fa82d377029ea865bd7b44ab856aa017231f35ceb4", + "format": 1 + }, + { + "name": "plugins/modules/aci_l3out_dhcp_relay_label.py", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "8ddb3cff30dd4c4dfb48ac703bb3dbaac4ae192b1fe17ce82cc0e592ebbfa3f1", "format": 1 }, { "name": "plugins/modules/aci_aaa_ssh_auth.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "1a11939efc42e5eef17de294c3f269363bd5ca2c33948169790960f56d1f66d0", + "chksum_sha256": "a0174a594fdb221bbeb72c669a93645e9fb1c64e3dba5b851053704b86be2f12", "format": 1 }, { @@ -1397,14 +1831,14 @@ "name": "plugins/modules/aci_l2out_extepg.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "4df3b9d894f1018992859d33ef04371677097ba439e477fa667281a11d8e013c", + "chksum_sha256": "474d1f24e39732788fb6552b079ec267d96f93e3b859af1db951cb55c2bbe868", "format": 1 }, { "name": "plugins/modules/aci_interface_description.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "66af31a14a88ae595203b8423c60ce0e0c5f6a6e227b77934e858b3f6ff8b8d3", + "chksum_sha256": "8443f8928c0acf67bd199a42bbb62783f72fa2d840687d0d16e88440a1752cc3", "format": 1 }, { @@ -1418,7 +1852,7 @@ "name": "plugins/modules/aci_epg_to_domain.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "7a6d853dfcaa26e3b875f37a5d6ac6f93985194fe049542915da491ad0a1898a", + "chksum_sha256": "5cca1da914e70dcb6ddd2492330fce8ce00356e38ebec79d6c03002ba4a0f7e7", "format": 1 }, { @@ -1439,7 +1873,7 @@ "name": "plugins/modules/aci_l2out_logical_node_profile.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "a2231736fe506b60286c5656a2030da7f9be1910f15da672abaefbe0b1d4caa6", + "chksum_sha256": "0fad05ff02df088faef3e5724349116f237bbf4c00f00fde28483ddd994cc339", "format": 1 }, { @@ -1453,7 +1887,7 @@ "name": "plugins/modules/aci_static_node_mgmt_address.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "38643b5e89186388f3e1e3f31b3f1cefd24c209c7317f8994ce8044a43bfc0b5", + "chksum_sha256": "9b099b5a0ed706ce351ca1515aca2892b97114cf29af4b83aa12325676f57b64", "format": 1 }, { @@ -1463,18 +1897,32 @@ "chksum_sha256": "4adf5b343bc0b07287358ea924891e4af638ffca6b0403e75a95fb0207f8ac5e", "format": 1 }, + { + "name": "plugins/modules/aci_fabric_pod_external_tep.py", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "390ad103958c088923973117925962b884914d0a9a886953bb545383f517dc21", + "format": 1 + }, + { + "name": "plugins/modules/aci_dhcp_option.py", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "f35467794ee204ccfd1f8e602c66e76c016b096588a3d8ed0eac0e33a0bbbf8b", + "format": 1 + }, { "name": "plugins/modules/aci_dhcp_relay_provider.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "c656312b9b7372480f95e1b2b1ee2d1c06981a91847415b602de675241f38783", + "chksum_sha256": "6d11d7f2bf3c8a58f93cbb10e7059db50827ae9f90412689f6363a62d3e4f3d7", "format": 1 }, { "name": "plugins/modules/aci_bd.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "b6f2d9e6e6c7f50cc7139fe425d498503580cd701bf959f93747867ae6e89dcb", + "chksum_sha256": "f34256d98e574710544ea3b5cd7edfba0c2b544de3a9a7453385191c674fb114", "format": 1 }, { @@ -1488,14 +1936,14 @@ "name": "plugins/modules/aci_esg_ip_subnet_selector.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "1cccaa749da04355d2c8ffeee3f37e2a7cf6e2965f3527da631caf77c0fa3c4f", + "chksum_sha256": "b5753aee69b9c0b956fef638a487badab47e2575faaad5896383a815c17308ca", "format": 1 }, { "name": "plugins/modules/aci_syslog_source.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "33378f1e3da1418b7b7bf2bf3c2b56e22d6017489b9cbb8480e160f7658b1638", + "chksum_sha256": "6ca6ec85ce969d27fb0c6e13f37896e91e2f9bafe784a7e59c79cfc2860c1875", "format": 1 }, { @@ -1509,7 +1957,7 @@ "name": "plugins/modules/aci_igmp_interface_policy.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "dcab75238e50636cf711e31dc06f39549c8f0349c1f842641e53be890feddc37", + "chksum_sha256": "4a669e24ee48f9feea05e59d298fb1fbb75c8c5eea90f7e10ff4697a6d0f9b0d", "format": 1 }, { @@ -1523,7 +1971,7 @@ "name": "plugins/modules/aci_interface_blacklist.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "354033a3d04dba5c2099f32453690b181528bfca52e1ae54b462f9ef4411fba5", + "chksum_sha256": "5f4b0ab0f9be0e662f875d3692614f6bcc86e403851515f888f09ebcaa09425c", "format": 1 }, { @@ -1540,11 +1988,18 @@ "chksum_sha256": "128637fe8018eb9a70c023ddb2e44713b01eabe3a2e80f0f29866f07d79eb7bd", "format": 1 }, + { + "name": "plugins/modules/aci_l3out_bfd_interface_profile.py", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "7b78b47c3f637dbad1f12fb5601e09f6532d920bf5032d97e1ed70ea615fa92e", + "format": 1 + }, { "name": "plugins/modules/aci_l2out_logical_interface_path.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "4b7326f21b04df50bdc8a36660e66d5b7c98ffb5c4dfd8b085014a8720bbf442", + "chksum_sha256": "8884fbb1ecec52a84f8e9704b7cd73c9452d2d518d458d18d08ff64f64d3e490", "format": 1 }, { @@ -1554,11 +2009,18 @@ "chksum_sha256": "212d763a6118558a12aa283cd107f5bd8ba932c9091c5fca84fbe95d05f82f79", "format": 1 }, + { + "name": "plugins/modules/aci_bd_rogue_exception_mac.py", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "c0ddc4a83798ffe29926e16ee9226ec55e2bbc7d8467285e5ff0a6c92c9b87ec", + "format": 1 + }, { "name": "plugins/modules/aci_switch_leaf_selector.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "1488618f3ab559384294ebb1459508c73469e8cdc2d609d33c662f614687e542", + "chksum_sha256": "2f72810a858ac96408ee58971e9f580674451e40530c54913787564a1f121336", "format": 1 }, { @@ -1593,7 +2055,7 @@ "name": "tests/unit/compat/builtins.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "ba13a350ade8ef804336f888d5883b8e54f8bddfb9d0fadc10277a8ca6540f4e", + "chksum_sha256": "3ab3c581035d277195322ffc42e41315d7c1f502a9c04227608836be1748ef49", "format": 1 }, { @@ -1649,7 +2111,7 @@ "name": "tests/unit/mock/loader.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "536cab78d0d94beced4f11fec254173e9d1e8309b3ea47a4caa9a77e1e5b65a0", + "chksum_sha256": "e1893e25a6ea2ca88ca0fc5b5dfe230d7fe97e634fa6f930e093b619290b6f12", "format": 1 }, { @@ -1761,7 +2223,7 @@ "name": "tests/unit/module_utils/test_aci.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "8480f1ff37482f4f260f5df3d1428585530c0fc9c0a3c0c388696a7109fd951f", + "chksum_sha256": "2ac6a68e874d272853c5f179993791a7ad66ea586c3297ef3d86d3dae6df9d5f", "format": 1 }, { @@ -1817,7 +2279,7 @@ "name": "tests/integration/targets/aci_l3out_static_routes_nexthop/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "bd0f30d3d16fa72bbd1b9893fcfc3b0d5fa0d022e1441701ae8428f741056967", + "chksum_sha256": "6a353dbc99717ed8177c119dff25131364efe1a53d1cd475818ac262b389e5b2", "format": 1 }, { @@ -1828,2345 +2290,3304 @@ "format": 1 }, { - "name": "tests/integration/targets/aci_bulk_static_binding_to_epg", + "name": "tests/integration/targets/aci_interface_policy_bfd_multihop", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/aci_bulk_static_binding_to_epg/tasks", + "name": "tests/integration/targets/aci_interface_policy_bfd_multihop/tasks", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/aci_bulk_static_binding_to_epg/tasks/main.yml", + "name": "tests/integration/targets/aci_interface_policy_bfd_multihop/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "84e94677beff76de0840bf516a363281e8d41b2a554137af618f7e8c6263565a", + "chksum_sha256": "13685e99580f38026105872fd095aefaf2ad3072a73d5d07caee1184ff619ab9", "format": 1 }, { - "name": "tests/integration/targets/aci_bulk_static_binding_to_epg/aliases", + "name": "tests/integration/targets/aci_interface_policy_bfd_multihop/aliases", "ftype": "file", "chksum_type": "sha256", "chksum_sha256": "616f27a9a7bb49e561ef3782330e18d1a8cea3840e3166e798796684dd546a69", "format": 1 }, { - "name": "tests/integration/targets/aci_maintenance_group", + "name": "tests/integration/targets/aci_bd_rogue_exception_mac", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/aci_maintenance_group/tasks", + "name": "tests/integration/targets/aci_bd_rogue_exception_mac/tasks", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/aci_maintenance_group/tasks/main.yml", + "name": "tests/integration/targets/aci_bd_rogue_exception_mac/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "b844b65db6cdf1934a6533e89a7591f20bc6dd2304acfe5706fe7dd1e1fb7426", + "chksum_sha256": "55b888d0fe8243a6398c041b0db8b151b6141d1046b5ff8afb6759125c5ec07a", "format": 1 }, { - "name": "tests/integration/targets/aci_maintenance_group/aliases", + "name": "tests/integration/targets/aci_bd_rogue_exception_mac/aliases", "ftype": "file", "chksum_type": "sha256", "chksum_sha256": "616f27a9a7bb49e561ef3782330e18d1a8cea3840e3166e798796684dd546a69", "format": 1 }, { - "name": "tests/integration/targets/aci_tenant_span_src_group_src", + "name": "tests/integration/targets/aci_bulk_static_binding_to_epg", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/aci_tenant_span_src_group_src/tasks", + "name": "tests/integration/targets/aci_bulk_static_binding_to_epg/tasks", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/aci_tenant_span_src_group_src/tasks/main.yml", + "name": "tests/integration/targets/aci_bulk_static_binding_to_epg/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "6c33688aae7482df41385b622a6d728446eabff9a7cb45a9c4a4ca51dc71bba7", + "chksum_sha256": "cf36d796d11e1be1d26ee74dd9c1be0313d9bdbe7a01e43d1c6ea6d52ee1a0c3", "format": 1 }, { - "name": "tests/integration/targets/aci_tenant_span_src_group_src/aliases", + "name": "tests/integration/targets/aci_bulk_static_binding_to_epg/aliases", "ftype": "file", "chksum_type": "sha256", "chksum_sha256": "616f27a9a7bb49e561ef3782330e18d1a8cea3840e3166e798796684dd546a69", "format": 1 }, { - "name": "tests/integration/targets/aci_interface_policy_leaf_fc_policy_group", + "name": "tests/integration/targets/aci_maintenance_group", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/aci_interface_policy_leaf_fc_policy_group/tasks", + "name": "tests/integration/targets/aci_maintenance_group/tasks", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/aci_interface_policy_leaf_fc_policy_group/tasks/main.yml", + "name": "tests/integration/targets/aci_maintenance_group/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "fe1b3e59b230ed7f25bdf7c813f197dfa66e1ed964995b17dff7768416ddbe45", + "chksum_sha256": "6b13d9e01f2962b086bc0b12da836dcc8d519d337576c6891b584f700ae10ec8", "format": 1 }, { - "name": "tests/integration/targets/aci_interface_policy_leaf_fc_policy_group/aliases", + "name": "tests/integration/targets/aci_maintenance_group/aliases", "ftype": "file", "chksum_type": "sha256", "chksum_sha256": "616f27a9a7bb49e561ef3782330e18d1a8cea3840e3166e798796684dd546a69", "format": 1 }, { - "name": "tests/integration/targets/aci_firmware_source", + "name": "tests/integration/targets/aci_tenant_span_src_group_src", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/aci_firmware_source/tasks", + "name": "tests/integration/targets/aci_tenant_span_src_group_src/tasks", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/aci_firmware_source/tasks/main.yml", + "name": "tests/integration/targets/aci_tenant_span_src_group_src/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "ef4e251bc843d4ceafc9ea063dc76b6c03e8db36b2287a197f58aa80bcc768f7", + "chksum_sha256": "7139efd1e06fd2c557e9a85d95dc8651ca591abb6c4fbeb2aee894f32e659318", "format": 1 }, { - "name": "tests/integration/targets/aci_firmware_source/aliases", + "name": "tests/integration/targets/aci_tenant_span_src_group_src/aliases", "ftype": "file", "chksum_type": "sha256", "chksum_sha256": "616f27a9a7bb49e561ef3782330e18d1a8cea3840e3166e798796684dd546a69", "format": 1 }, { - "name": "tests/integration/targets/aci_access_port_block_to_access_port", + "name": "tests/integration/targets/aci_interface_policy_hsrp", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/aci_access_port_block_to_access_port/tasks", + "name": "tests/integration/targets/aci_interface_policy_hsrp/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", + "name": "tests/integration/targets/aci_interface_policy_hsrp/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "1828323aa38b65382a6861d3940dd3e18c5811e8884a0c9a498b1c20474fd17d", + "chksum_sha256": "724f468049beb27adba5873b65d3a200a257d150e56cb97853a347dcbf7a5ead", "format": 1 }, { - "name": "tests/integration/targets/aci_access_port_block_to_access_port/aliases", + "name": "tests/integration/targets/aci_interface_policy_hsrp/aliases", "ftype": "file", "chksum_type": "sha256", "chksum_sha256": "616f27a9a7bb49e561ef3782330e18d1a8cea3840e3166e798796684dd546a69", "format": 1 }, { - "name": "tests/integration/targets/aci_interface_selector_to_switch_policy_leaf_profile", + "name": "tests/integration/targets/aci_interface_policy_leaf_fc_policy_group", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/aci_interface_selector_to_switch_policy_leaf_profile/tasks", + "name": "tests/integration/targets/aci_interface_policy_leaf_fc_policy_group/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", + "name": "tests/integration/targets/aci_interface_policy_leaf_fc_policy_group/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "b55c642e8532b93e41194dc38d6cc027358149c993e391ec8f4cb2f648609900", + "chksum_sha256": "620c371219707b5ba9ffb3c48b07c390a2f4af7c54b534e3a9102af89e670a9d", "format": 1 }, { - "name": "tests/integration/targets/aci_interface_selector_to_switch_policy_leaf_profile/aliases", + "name": "tests/integration/targets/aci_interface_policy_leaf_fc_policy_group/aliases", "ftype": "file", "chksum_type": "sha256", "chksum_sha256": "616f27a9a7bb49e561ef3782330e18d1a8cea3840e3166e798796684dd546a69", "format": 1 }, { - "name": "tests/integration/targets/aci_filter_entry", + "name": "tests/integration/targets/aci_firmware_source", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/aci_filter_entry/tasks", + "name": "tests/integration/targets/aci_firmware_source/tasks", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/aci_filter_entry/tasks/main.yml", + "name": "tests/integration/targets/aci_firmware_source/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "e61460bafe4da68c7fde6ba4f048add6429fe9019de9ed587a21cf24c5f1272f", + "chksum_sha256": "0520dbc50b4c79c2d60b38da8781dcfdc287f22c3db3e262257c5533e605e669", "format": 1 }, { - "name": "tests/integration/targets/aci_filter_entry/aliases", + "name": "tests/integration/targets/aci_firmware_source/aliases", "ftype": "file", "chksum_type": "sha256", "chksum_sha256": "616f27a9a7bb49e561ef3782330e18d1a8cea3840e3166e798796684dd546a69", "format": 1 }, { - "name": "tests/integration/targets/aci_interface_config", + "name": "tests/integration/targets/aci_fabric_pod", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/aci_interface_config/tasks", + "name": "tests/integration/targets/aci_fabric_pod/tasks", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/aci_interface_config/tasks/main.yml", + "name": "tests/integration/targets/aci_fabric_pod/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "949614da80caa4cd9533e7063e8a4d6dfc08e3ae6da70672209b7df2d1b60346", + "chksum_sha256": "fc1722266ff691d548e29d744fd1c9d37751b754ae88cdd66fcaa86442ba7c57", "format": 1 }, { - "name": "tests/integration/targets/aci_interface_config/aliases", + "name": "tests/integration/targets/aci_fabric_pod/aliases", "ftype": "file", "chksum_type": "sha256", "chksum_sha256": "616f27a9a7bb49e561ef3782330e18d1a8cea3840e3166e798796684dd546a69", "format": 1 }, { - "name": "tests/integration/targets/aci_vlan_pool_encap_block", + "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_vlan_pool_encap_block/tasks", + "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_vlan_pool_encap_block/tasks/main.yml", + "name": "tests/integration/targets/aci_access_port_block_to_access_port/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "c27de4117ad90e8466f98e511ff516843648ee8da6fe25645a9f8ae87b25768d", + "chksum_sha256": "2ea0d9197777664d16d11dae2a33cfea35346472a092eda6748ceb0eb445d1d1", "format": 1 }, { - "name": "tests/integration/targets/aci_vlan_pool_encap_block/aliases", + "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_vmm_uplink_container", + "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_vmm_uplink_container/tasks", + "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_vmm_uplink_container/tasks/main.yml", + "name": "tests/integration/targets/aci_interface_selector_to_switch_policy_leaf_profile/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "16a798f367b375064bf56f5113576979bd3e867d689d1696301dcd1c5b4fb283", + "chksum_sha256": "78d89115835ad9d3ef9534e0a1d408b71c1a3207fb20f0a5250f14aafb72283a", "format": 1 }, { - "name": "tests/integration/targets/aci_vmm_uplink_container/aliases", + "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_vlan_pool", + "name": "tests/integration/targets/aci_filter_entry", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/aci_vlan_pool/tasks", + "name": "tests/integration/targets/aci_filter_entry/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": "cb73f26a0209ab1499cd932c8b01114d50ea77426c3405114e1d7c57e8edafa3", - "format": 1 - }, - { - "name": "tests/integration/targets/aci_vlan_pool/tasks/static.yml", - "ftype": "file", - "chksum_type": "sha256", - "chksum_sha256": "391806200ff6ffcf6ecfda748cff3a28825c1092401cad52f1e6afcfeeb83237", - "format": 1 - }, - { - "name": "tests/integration/targets/aci_vlan_pool/tasks/main.yml", + "name": "tests/integration/targets/aci_filter_entry/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "f16539e51468e18e77f6105b1a4ba847f1e6a28a08d652e17fa40144606db4f4", + "chksum_sha256": "3f32421512afce6c2ed052d4af39f0baa18c51356e9095cb4916b848a63a389e", "format": 1 }, { - "name": "tests/integration/targets/aci_vlan_pool/aliases", + "name": "tests/integration/targets/aci_filter_entry/aliases", "ftype": "file", "chksum_type": "sha256", "chksum_sha256": "616f27a9a7bb49e561ef3782330e18d1a8cea3840e3166e798796684dd546a69", "format": 1 }, { - "name": "tests/integration/targets/aci_cloud_epg", + "name": "tests/integration/targets/aci_l3out_hsrp_group", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/aci_cloud_epg/tasks", + "name": "tests/integration/targets/aci_l3out_hsrp_group/tasks", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/aci_cloud_epg/tasks/main.yml", + "name": "tests/integration/targets/aci_l3out_hsrp_group/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "082ad8f9777a3cb4cf019ed7b3a750e0eaa4ecea0e67d63c17230ab77a184b79", + "chksum_sha256": "0fbdf79f543ac0ae48c297878fcdc6aa3dc752afa61fc7be1997a39cb6f3067b", "format": 1 }, { - "name": "tests/integration/targets/aci_cloud_epg/aliases", + "name": "tests/integration/targets/aci_l3out_hsrp_group/aliases", "ftype": "file", "chksum_type": "sha256", "chksum_sha256": "616f27a9a7bb49e561ef3782330e18d1a8cea3840e3166e798796684dd546a69", "format": 1 }, { - "name": "tests/integration/targets/aci_cloud_external_epg_selector", + "name": "tests/integration/targets/aci_interface_config", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/aci_cloud_external_epg_selector/tasks", + "name": "tests/integration/targets/aci_interface_config/tasks", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/aci_cloud_external_epg_selector/tasks/main.yml", + "name": "tests/integration/targets/aci_interface_config/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "cba2fe77659c826449cd65ed0443e521f7b9179ee1fe78d2b4e67cc3c8785e86", + "chksum_sha256": "bdd483a3e9175b7e37640176f4e41bd2cfe3cde64ca27da979e28ac8b6468bcb", "format": 1 }, { - "name": "tests/integration/targets/aci_cloud_external_epg_selector/aliases", + "name": "tests/integration/targets/aci_interface_config/aliases", "ftype": "file", "chksum_type": "sha256", "chksum_sha256": "616f27a9a7bb49e561ef3782330e18d1a8cea3840e3166e798796684dd546a69", "format": 1 }, { - "name": "tests/integration/targets/aci_cloud_aws_provider", + "name": "tests/integration/targets/aci_vlan_pool_encap_block", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/aci_cloud_aws_provider/tasks", + "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_cloud_aws_provider/tasks/main.yml", + "name": "tests/integration/targets/aci_vlan_pool_encap_block/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "30e2c31b5ad7f73e6b909478f13fa19357504a1e3bd9c27f27869f29df0bf874", + "chksum_sha256": "d03d3b2b81b15d6fa8735ef96833fdbecde52f5eadfd84df553832dd2447da9c", "format": 1 }, { - "name": "tests/integration/targets/aci_domain_to_encap_pool", + "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_dhcp_option_policy", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/aci_domain_to_encap_pool/tasks", + "name": "tests/integration/targets/aci_dhcp_option_policy/tasks", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/aci_domain_to_encap_pool/tasks/main.yml", + "name": "tests/integration/targets/aci_dhcp_option_policy/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "e1408a04b604992172d9ee514d16d3b1c83f089191656bd4e20516d1c39e16fd", + "chksum_sha256": "7d51eff57f9862977b125ef675a893b9cb4c8c067c808a84f965927c92b4a244", "format": 1 }, { - "name": "tests/integration/targets/aci_domain_to_encap_pool/aliases", + "name": "tests/integration/targets/aci_dhcp_option_policy/aliases", "ftype": "file", "chksum_type": "sha256", "chksum_sha256": "616f27a9a7bb49e561ef3782330e18d1a8cea3840e3166e798796684dd546a69", "format": 1 }, { - "name": "tests/integration/targets/aci_interface_policy_mcp", + "name": "tests/integration/targets/aci_l3out_floating_svi_path_secondary_ip", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/aci_interface_policy_mcp/tasks", + "name": "tests/integration/targets/aci_l3out_floating_svi_path_secondary_ip/tasks", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/aci_interface_policy_mcp/tasks/main.yml", + "name": "tests/integration/targets/aci_l3out_floating_svi_path_secondary_ip/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "deef48fee05f5fb8bc48390e26b4cff4871bcdcfb06d94fba77a01bcdae94bb6", + "chksum_sha256": "6c15f6cf851cd65ac515fbe2681160fd34b056634ae78e1ac1b28d5793417f2e", "format": 1 }, { - "name": "tests/integration/targets/aci_interface_policy_mcp/aliases", + "name": "tests/integration/targets/aci_l3out_floating_svi_path_secondary_ip/aliases", "ftype": "file", "chksum_type": "sha256", "chksum_sha256": "616f27a9a7bb49e561ef3782330e18d1a8cea3840e3166e798796684dd546a69", "format": 1 }, { - "name": "tests/integration/targets/aci_match_rule", + "name": "tests/integration/targets/aci_vmm_uplink_container", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/aci_match_rule/tasks", + "name": "tests/integration/targets/aci_vmm_uplink_container/tasks", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/aci_match_rule/tasks/main.yml", + "name": "tests/integration/targets/aci_vmm_uplink_container/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "e5084a752a4704a990bb9d8ca629d47d0447209e5cbc8dac92439a9048f96758", + "chksum_sha256": "cda2b2dcf9fc277d187ddc01c25fb43bb6685e248ec5eb65098d34b6a84853f1", "format": 1 }, { - "name": "tests/integration/targets/aci_match_rule/aliases", + "name": "tests/integration/targets/aci_vmm_uplink_container/aliases", "ftype": "file", "chksum_type": "sha256", "chksum_sha256": "616f27a9a7bb49e561ef3782330e18d1a8cea3840e3166e798796684dd546a69", "format": 1 }, { - "name": "tests/integration/targets/aci_ntp_server", + "name": "tests/integration/targets/aci_vlan_pool", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/aci_ntp_server/tasks", + "name": "tests/integration/targets/aci_vlan_pool/tasks", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/aci_ntp_server/tasks/main.yml", + "name": "tests/integration/targets/aci_vlan_pool/tasks/dynamic.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "5e745be684046cdde7cd23c7da4d4a96be89ee0b538f65f0047178393194c1c0", + "chksum_sha256": "91bc67bd296c556bf94eebf42fc939c98eb5adfbe92e87191beff06f7168f6e5", "format": 1 }, { - "name": "tests/integration/targets/aci_ntp_server/aliases", + "name": "tests/integration/targets/aci_vlan_pool/tasks/static.yml", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "2dd127083ff68df0a3dbf696db8d8a40a79d047f4a293c3c403699627c6e60e2", + "format": 1 + }, + { + "name": "tests/integration/targets/aci_vlan_pool/tasks/main.yml", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "4433286af63fcd50848bc5106316ba8688e2225d955a458bc98def951922b3c1", + "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_l3out_logical_interface_vpc_member", + "name": "tests/integration/targets/aci_cloud_epg", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/aci_l3out_logical_interface_vpc_member/tasks", + "name": "tests/integration/targets/aci_cloud_epg/tasks", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/aci_l3out_logical_interface_vpc_member/tasks/main.yml", + "name": "tests/integration/targets/aci_cloud_epg/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "e76de28c039ecd85e495e2077a838631707c5d7b1547ec8e0cc892a0637cb62a", + "chksum_sha256": "ed75fbb318aef76412f7528ffa101f5a74a831bf17e1291b14069f42d0171a76", "format": 1 }, { - "name": "tests/integration/targets/aci_l3out_logical_interface_vpc_member/aliases", + "name": "tests/integration/targets/aci_cloud_epg/aliases", "ftype": "file", "chksum_type": "sha256", "chksum_sha256": "616f27a9a7bb49e561ef3782330e18d1a8cea3840e3166e798796684dd546a69", "format": 1 }, { - "name": "tests/integration/targets/aci_snmp_client_group", + "name": "tests/integration/targets/aci_netflow_monitor_to_exporter", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/aci_snmp_client_group/tasks", + "name": "tests/integration/targets/aci_netflow_monitor_to_exporter/tasks", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/aci_snmp_client_group/tasks/main.yml", + "name": "tests/integration/targets/aci_netflow_monitor_to_exporter/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "fcca2775acfaa05479b5b5e430c68be81f2c3aa7e6bd7494c820ee2d19c23eed", + "chksum_sha256": "ada8730c4ef724c2092ded8a260928e5640f2c4808b87629eb881e6b25c5301d", "format": 1 }, { - "name": "tests/integration/targets/aci_snmp_client_group/aliases", + "name": "tests/integration/targets/aci_netflow_monitor_to_exporter/aliases", "ftype": "file", "chksum_type": "sha256", "chksum_sha256": "616f27a9a7bb49e561ef3782330e18d1a8cea3840e3166e798796684dd546a69", "format": 1 }, { - "name": "tests/integration/targets/aci_interface_description", + "name": "tests/integration/targets/aci_cloud_external_epg_selector", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/aci_interface_description/tasks", + "name": "tests/integration/targets/aci_cloud_external_epg_selector/tasks", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/aci_interface_description/tasks/main.yml", + "name": "tests/integration/targets/aci_cloud_external_epg_selector/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "dab564ccaffb75fb23e7ebe92e423733dd8db80e0907f2cbb2c7ab63ef9b53f7", + "chksum_sha256": "2b0932f5ada60334771a611b14a4a5816f740aad0da9ab6b831056fe4c359bce", "format": 1 }, { - "name": "tests/integration/targets/aci_interface_description/aliases", + "name": "tests/integration/targets/aci_cloud_external_epg_selector/aliases", "ftype": "file", "chksum_type": "sha256", "chksum_sha256": "616f27a9a7bb49e561ef3782330e18d1a8cea3840e3166e798796684dd546a69", "format": 1 }, { - "name": "tests/integration/targets/aci_dns_provider", + "name": "tests/integration/targets/aci_cloud_aws_provider", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/aci_dns_provider/tasks", + "name": "tests/integration/targets/aci_cloud_aws_provider/tasks", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/aci_dns_provider/tasks/main.yml", + "name": "tests/integration/targets/aci_cloud_aws_provider/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "8deb0048459357964c22ea4ceeddc9581317b58e9bb61d833430069f67d63368", + "chksum_sha256": "6efafcee986c6011fa8411217eba7a81d6a026421ec055cbe2cf92c731c7a098", "format": 1 }, { - "name": "tests/integration/targets/aci_dns_provider/aliases", - "ftype": "file", - "chksum_type": "sha256", - "chksum_sha256": "616f27a9a7bb49e561ef3782330e18d1a8cea3840e3166e798796684dd546a69", - "format": 1 - }, - { - "name": "tests/integration/targets/aci_fabric_wide_settings", + "name": "tests/integration/targets/aci_domain_to_encap_pool", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/aci_fabric_wide_settings/tasks", + "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_fabric_wide_settings/tasks/main.yml", + "name": "tests/integration/targets/aci_domain_to_encap_pool/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "148d337c86ab59cfab9434d4d23959de9a7fc4f2cac867d7af9f9e4e52d02e9b", + "chksum_sha256": "63db0c5f71279ef78cce75034fc4561bdcf605172cff877d7d8a2a3fec12e98c", "format": 1 }, { - "name": "tests/integration/targets/aci_fabric_wide_settings/aliases", + "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_esg_contract_master", + "name": "tests/integration/targets/aci_interface_policy_mcp", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/aci_esg_contract_master/tasks", + "name": "tests/integration/targets/aci_interface_policy_mcp/tasks", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/aci_esg_contract_master/tasks/main.yml", + "name": "tests/integration/targets/aci_interface_policy_mcp/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "510fa4b0b76ac202ef3b090ae4fc78e5f3b8875e58ceeada92412884b53be1a1", + "chksum_sha256": "329f5419253eab113bd4faa25f4a99af32251af723460d8e707c4d8db32f2aca", "format": 1 }, { - "name": "tests/integration/targets/aci_esg_contract_master/aliases", + "name": "tests/integration/targets/aci_interface_policy_mcp/aliases", "ftype": "file", "chksum_type": "sha256", "chksum_sha256": "616f27a9a7bb49e561ef3782330e18d1a8cea3840e3166e798796684dd546a69", "format": 1 }, { - "name": "tests/integration/targets/aci_access_port_to_interface_policy_leaf_profile", + "name": "tests/integration/targets/aci_match_rule", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/aci_access_port_to_interface_policy_leaf_profile/tasks", + "name": "tests/integration/targets/aci_match_rule/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", + "name": "tests/integration/targets/aci_match_rule/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "d3ed26b1f2e6331c513718899de4606dadb3f837d724946a54b2347e2bea6684", + "chksum_sha256": "ea173a9f9c9f72d041027ffffbfb2112baf709dbf032674b3cc258489d4f8cbc", "format": 1 }, { - "name": "tests/integration/targets/aci_access_port_to_interface_policy_leaf_profile/aliases", + "name": "tests/integration/targets/aci_match_rule/aliases", "ftype": "file", "chksum_type": "sha256", "chksum_sha256": "616f27a9a7bb49e561ef3782330e18d1a8cea3840e3166e798796684dd546a69", "format": 1 }, { - "name": "tests/integration/targets/aci_cloud_vpn_gateway", + "name": "tests/integration/targets/aci_ntp_server", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/aci_cloud_vpn_gateway/tasks", + "name": "tests/integration/targets/aci_ntp_server/tasks", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/aci_cloud_vpn_gateway/tasks/main.yml", + "name": "tests/integration/targets/aci_ntp_server/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "bbd695fc212060f340e99ae563176ae49654bbefa01bb6e093789633e899e090", + "chksum_sha256": "951b435ff39db19906bbaf323b9bee3b807a2d581e8665dc0361e719f6478ac7", "format": 1 }, { - "name": "tests/integration/targets/aci_cloud_vpn_gateway/aliases", + "name": "tests/integration/targets/aci_ntp_server/aliases", "ftype": "file", "chksum_type": "sha256", "chksum_sha256": "616f27a9a7bb49e561ef3782330e18d1a8cea3840e3166e798796684dd546a69", "format": 1 }, { - "name": "tests/integration/targets/aci_interface_policy_fc", + "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_interface_policy_fc/tasks", + "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_interface_policy_fc/tasks/main.yml", + "name": "tests/integration/targets/aci_l3out_logical_interface_vpc_member/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "b2d68e0c3e83127354a824682dc77c62a7a8f7aff69dae9f125c6b068265358f", + "chksum_sha256": "315a59b0363d15adf5c69ed52b58f1ff42f2b1d07e298c6cf841f1fab4bd17cf", "format": 1 }, { - "name": "tests/integration/targets/aci_interface_policy_fc/aliases", + "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_bd", + "name": "tests/integration/targets/aci_snmp_client_group", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/aci_bd/tasks", + "name": "tests/integration/targets/aci_snmp_client_group/tasks", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/aci_bd/tasks/main.yml", + "name": "tests/integration/targets/aci_snmp_client_group/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "348510483344aa212bc086073b923408e66d0487d42869dab01039ef52dddc0f", + "chksum_sha256": "26b1f825dfd08e37204f64729e2abbcb7c0e300e2cfaa45cba0ded048db4db34", "format": 1 }, { - "name": "tests/integration/targets/aci_bd/aliases", + "name": "tests/integration/targets/aci_snmp_client_group/aliases", "ftype": "file", "chksum_type": "sha256", "chksum_sha256": "616f27a9a7bb49e561ef3782330e18d1a8cea3840e3166e798796684dd546a69", "format": 1 }, { - "name": "tests/integration/targets/aci_snmp_community_policy", + "name": "tests/integration/targets/aci_interface_description", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/aci_snmp_community_policy/tasks", + "name": "tests/integration/targets/aci_interface_description/tasks", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/aci_snmp_community_policy/tasks/main.yml", + "name": "tests/integration/targets/aci_interface_description/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "1f55bd655ca008656898bca31cb24e3c3fb8c4c9857ac5e4344a9cfcbc173f5b", + "chksum_sha256": "541b55bf33113e77644761cde93b2d85dd0fcfa7312d3cc79c4e9f647fd579c1", "format": 1 }, { - "name": "tests/integration/targets/aci_snmp_community_policy/aliases", + "name": "tests/integration/targets/aci_interface_description/aliases", "ftype": "file", "chksum_type": "sha256", "chksum_sha256": "616f27a9a7bb49e561ef3782330e18d1a8cea3840e3166e798796684dd546a69", "format": 1 }, { - "name": "tests/integration/targets/aci_access_span_dst_group", + "name": "tests/integration/targets/aci_bgp_route_summarization_policy", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/aci_access_span_dst_group/tasks", + "name": "tests/integration/targets/aci_bgp_route_summarization_policy/tasks", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/aci_access_span_dst_group/tasks/main.yml", + "name": "tests/integration/targets/aci_bgp_route_summarization_policy/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "de5e15422dbac4ba028abd5422c3f9fe32fb5bf2cbdbd11658a3be4f44b3160e", + "chksum_sha256": "5942305ac9e0bb1d890ef8526e12637256e9f4ddffb2f9594d745d1e9273cd4f", "format": 1 }, { - "name": "tests/integration/targets/aci_access_span_dst_group/aliases", + "name": "tests/integration/targets/aci_bgp_route_summarization_policy/aliases", "ftype": "file", "chksum_type": "sha256", "chksum_sha256": "616f27a9a7bb49e561ef3782330e18d1a8cea3840e3166e798796684dd546a69", "format": 1 }, { - "name": "tests/integration/targets/aci_config_snapshot", + "name": "tests/integration/targets/aci_l3out_dhcp_relay_label", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/aci_config_snapshot/tasks", + "name": "tests/integration/targets/aci_l3out_dhcp_relay_label/tasks", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/aci_config_snapshot/tasks/main.yml", + "name": "tests/integration/targets/aci_l3out_dhcp_relay_label/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "0a799646b1dbd9af66d8df8679820cf8605a7cb64de234e8c88d3d4eaf7f0502", + "chksum_sha256": "2c58052c4366f9fc07db66e74f2e1a3f40a591029c9667fe8a6f7c3ed3885892", "format": 1 }, { - "name": "tests/integration/targets/aci_config_snapshot/aliases", + "name": "tests/integration/targets/aci_l3out_dhcp_relay_label/aliases", "ftype": "file", "chksum_type": "sha256", "chksum_sha256": "616f27a9a7bb49e561ef3782330e18d1a8cea3840e3166e798796684dd546a69", "format": 1 }, { - "name": "tests/integration/targets/aci_config_snapshot/pki", - "ftype": "dir", - "chksum_type": null, - "chksum_sha256": null, - "format": 1 - }, - { - "name": "tests/integration/targets/aci_config_snapshot/pki/admin.crt", - "ftype": "file", - "chksum_type": "sha256", - "chksum_sha256": "f97928b2cd1ce43cfe9ae9bbf47a40b858a749c4c3f25a7ec02898611f4fee90", - "format": 1 - }, - { - "name": "tests/integration/targets/aci_config_snapshot/pki/admin.key", - "ftype": "file", - "chksum_type": "sha256", - "chksum_sha256": "947c1b5a6c419641d4b2c8492b91f2d71588958666aeceeffb1f878460b1d256", - "format": 1 - }, - { - "name": "tests/integration/targets/aci_access_span_src_group", + "name": "tests/integration/targets/aci_dns_provider", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/aci_access_span_src_group/tasks", + "name": "tests/integration/targets/aci_dns_provider/tasks", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/aci_access_span_src_group/tasks/main.yml", + "name": "tests/integration/targets/aci_dns_provider/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "bb9a24d78c38d7e0bff38cdcf51520f0deb18fa0679bc58856121caa71564413", + "chksum_sha256": "75a48c8e2feb076b93f0ce76fcee1bf7029b7189021cb88262a734a1a013606f", "format": 1 }, { - "name": "tests/integration/targets/aci_access_span_src_group/aliases", + "name": "tests/integration/targets/aci_dns_provider/aliases", "ftype": "file", "chksum_type": "sha256", "chksum_sha256": "616f27a9a7bb49e561ef3782330e18d1a8cea3840e3166e798796684dd546a69", "format": 1 }, { - "name": "tests/integration/targets/aci_interface_policy_leaf_breakout_port_group", + "name": "tests/integration/targets/aci_fabric_wide_settings", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/aci_interface_policy_leaf_breakout_port_group/tasks", + "name": "tests/integration/targets/aci_fabric_wide_settings/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", + "name": "tests/integration/targets/aci_fabric_wide_settings/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "2a419d08da733f8a710fcce36d358c3a792435145c4da5ea9f359ec3126c9509", + "chksum_sha256": "647a1cc95af3bbe86822436a1dc0db0cb0e3093ab4f80fb21cb0da08906144f4", "format": 1 }, { - "name": "tests/integration/targets/aci_interface_policy_leaf_breakout_port_group/aliases", + "name": "tests/integration/targets/aci_fabric_wide_settings/aliases", "ftype": "file", "chksum_type": "sha256", "chksum_sha256": "616f27a9a7bb49e561ef3782330e18d1a8cea3840e3166e798796684dd546a69", "format": 1 }, { - "name": "tests/integration/targets/aci_fabric_switch_policy_group", + "name": "tests/integration/targets/aci_esg_contract_master", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/aci_fabric_switch_policy_group/tasks", + "name": "tests/integration/targets/aci_esg_contract_master/tasks", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/aci_fabric_switch_policy_group/tasks/main.yml", + "name": "tests/integration/targets/aci_esg_contract_master/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "9c2e6fd65a9f000cb521b0321fef521255c8b9374f987213d23836db32ae3b7b", + "chksum_sha256": "a67a0f25727f1bd1d90a50924b7767d9a26b3b4d06df8d099a039c5e5b5d2dd8", "format": 1 }, { - "name": "tests/integration/targets/aci_fabric_switch_policy_group/aliases", + "name": "tests/integration/targets/aci_esg_contract_master/aliases", "ftype": "file", "chksum_type": "sha256", "chksum_sha256": "616f27a9a7bb49e561ef3782330e18d1a8cea3840e3166e798796684dd546a69", "format": 1 }, { - "name": "tests/integration/targets/aci_ap", + "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_ap/tasks", + "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_ap/tasks/main.yml", + "name": "tests/integration/targets/aci_access_port_to_interface_policy_leaf_profile/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "180f2222d7fab150d26b1f94088d5edb070178d1bdf4bc198c0d24588d32b331", + "chksum_sha256": "b4a134d633ad0572114d5e0184929adb9b33612c543b99899c7fc9d88f13d3e1", "format": 1 }, { - "name": "tests/integration/targets/aci_ap/aliases", + "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_interface_policy_lldp", + "name": "tests/integration/targets/aci_cloud_vpn_gateway", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/aci_interface_policy_lldp/tasks", + "name": "tests/integration/targets/aci_cloud_vpn_gateway/tasks", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/aci_interface_policy_lldp/tasks/main.yml", + "name": "tests/integration/targets/aci_cloud_vpn_gateway/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "3c2094fbab84d87ce85c8e69e2b7c5b37f906d95eb36578b4c39ade77eb46e35", + "chksum_sha256": "10acde1e59189c19db818fa973107ba1dcb5723f327a224441e701eb52415c45", "format": 1 }, { - "name": "tests/integration/targets/aci_interface_policy_lldp/aliases", + "name": "tests/integration/targets/aci_cloud_vpn_gateway/aliases", "ftype": "file", "chksum_type": "sha256", "chksum_sha256": "616f27a9a7bb49e561ef3782330e18d1a8cea3840e3166e798796684dd546a69", "format": 1 }, { - "name": "tests/integration/targets/aci_access_span_src_group_src_path", + "name": "tests/integration/targets/aci_aaa_security_default_settings", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/aci_access_span_src_group_src_path/tasks", + "name": "tests/integration/targets/aci_aaa_security_default_settings/tasks", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/aci_access_span_src_group_src_path/tasks/main.yml", + "name": "tests/integration/targets/aci_aaa_security_default_settings/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "a01cd09447143359ef684d14444f762e33d2c56d9afb6cad3263989678be66bd", + "chksum_sha256": "7c8afd97006fcf68327261fb0f59141dce9ee8f24b9865b7c5fbd1d4004490e0", "format": 1 }, { - "name": "tests/integration/targets/aci_access_span_src_group_src_path/aliases", + "name": "tests/integration/targets/aci_aaa_security_default_settings/aliases", "ftype": "file", "chksum_type": "sha256", "chksum_sha256": "616f27a9a7bb49e561ef3782330e18d1a8cea3840e3166e798796684dd546a69", "format": 1 }, { - "name": "tests/integration/targets/aci_interface_policy_l2", + "name": "tests/integration/targets/aci_access_spine_interface_profile", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/aci_interface_policy_l2/tasks", + "name": "tests/integration/targets/aci_access_spine_interface_profile/tasks", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/aci_interface_policy_l2/tasks/main.yml", + "name": "tests/integration/targets/aci_access_spine_interface_profile/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "9ca36be150a08cbb8940d974c1a6ee059739fd0728b539ffcee805426964bfe8", + "chksum_sha256": "d5789ff7ae5e73b5e920cd7c0ff63889a6865dae9d5c5d52b39080a268a0e1cf", "format": 1 }, { - "name": "tests/integration/targets/aci_interface_policy_l2/aliases", + "name": "tests/integration/targets/aci_access_spine_interface_profile/aliases", "ftype": "file", "chksum_type": "sha256", "chksum_sha256": "616f27a9a7bb49e561ef3782330e18d1a8cea3840e3166e798796684dd546a69", "format": 1 }, { - "name": "tests/integration/targets/aci_l3out_route_tag_policy", + "name": "tests/integration/targets/aci_interface_policy_fc", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/aci_l3out_route_tag_policy/tasks", + "name": "tests/integration/targets/aci_interface_policy_fc/tasks", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/aci_l3out_route_tag_policy/tasks/main.yml", + "name": "tests/integration/targets/aci_interface_policy_fc/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "2c1e76ca9add4ba716db7e406f1d4cfca1487881d5264dbc4a0057c9a3a26502", + "chksum_sha256": "2a0710b51cc7591636bcfbcf98523e8c90c7d6471d2d4a34614bca90df7dc9b5", "format": 1 }, { - "name": "tests/integration/targets/aci_l3out_route_tag_policy/aliases", + "name": "tests/integration/targets/aci_interface_policy_fc/aliases", "ftype": "file", "chksum_type": "sha256", "chksum_sha256": "616f27a9a7bb49e561ef3782330e18d1a8cea3840e3166e798796684dd546a69", "format": 1 }, { - "name": "tests/integration/targets/aci_esg_ip_subnet_selector", + "name": "tests/integration/targets/aci_bd", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/aci_esg_ip_subnet_selector/tasks", + "name": "tests/integration/targets/aci_bd/tasks", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/aci_esg_ip_subnet_selector/tasks/main.yml", + "name": "tests/integration/targets/aci_bd/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "d1cf6174d2cf27cf9488644f407736c4139424cf52efdbf951713b7b511ca3ad", + "chksum_sha256": "b688f78a537ecbe5c93b7137442c2648250bb083e35ff3200ad74e8805bed8f1", "format": 1 }, { - "name": "tests/integration/targets/aci_esg_ip_subnet_selector/aliases", + "name": "tests/integration/targets/aci_bd/aliases", "ftype": "file", "chksum_type": "sha256", "chksum_sha256": "616f27a9a7bb49e561ef3782330e18d1a8cea3840e3166e798796684dd546a69", "format": 1 }, { - "name": "tests/integration/targets/aci_fabric_span_src_group_src_node", + "name": "tests/integration/targets/aci_snmp_community_policy", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/aci_fabric_span_src_group_src_node/tasks", + "name": "tests/integration/targets/aci_snmp_community_policy/tasks", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/aci_fabric_span_src_group_src_node/tasks/main.yml", + "name": "tests/integration/targets/aci_snmp_community_policy/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "8ef543f2ea69f83824459c15f967cee7dc2d8b553a613d42ba58c794cbc71f9c", + "chksum_sha256": "b0a52e2028b3b6a122141571a294359f4ae704805d26c68e2810a6c2e28d25c8", "format": 1 }, { - "name": "tests/integration/targets/aci_fabric_span_src_group_src_node/aliases", + "name": "tests/integration/targets/aci_snmp_community_policy/aliases", "ftype": "file", "chksum_type": "sha256", "chksum_sha256": "616f27a9a7bb49e561ef3782330e18d1a8cea3840e3166e798796684dd546a69", "format": 1 }, { - "name": "tests/integration/targets/aci_fabric_pod_selector", + "name": "tests/integration/targets/aci_access_span_dst_group", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/aci_fabric_pod_selector/tasks", + "name": "tests/integration/targets/aci_access_span_dst_group/tasks", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/aci_fabric_pod_selector/tasks/main.yml", + "name": "tests/integration/targets/aci_access_span_dst_group/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "142a54f5ea8d61ca6a19bd8caf6a851799de963b6d41d427acb6205bf00fe0ab", + "chksum_sha256": "ba4a2a1bc6f8b8fcd6fb658c770e22a84302cf1128d04d0e7a4bd3eaf48b4a09", "format": 1 }, { - "name": "tests/integration/targets/aci_fabric_pod_selector/aliases", + "name": "tests/integration/targets/aci_access_span_dst_group/aliases", "ftype": "file", "chksum_type": "sha256", "chksum_sha256": "616f27a9a7bb49e561ef3782330e18d1a8cea3840e3166e798796684dd546a69", "format": 1 }, { - "name": "tests/integration/targets/aci_bd_subnet", + "name": "tests/integration/targets/aci_node_block", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/aci_bd_subnet/tasks", + "name": "tests/integration/targets/aci_node_block/tasks", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/aci_bd_subnet/tasks/main.yml", + "name": "tests/integration/targets/aci_node_block/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "860384656ad549aa29df90bc8684d04ba250a9bdcbd50625c4db12a8da6c5b7a", + "chksum_sha256": "9b674a47283e025b415b1517afa141a7a2cb47989f8dc4428801a9dcfceee21e", "format": 1 }, { - "name": "tests/integration/targets/aci_bd_subnet/aliases", + "name": "tests/integration/targets/aci_node_block/aliases", "ftype": "file", "chksum_type": "sha256", "chksum_sha256": "616f27a9a7bb49e561ef3782330e18d1a8cea3840e3166e798796684dd546a69", "format": 1 }, { - "name": "tests/integration/targets/aci_access_span_src_group_src", + "name": "tests/integration/targets/aci_fabric_external_connection_profile", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/aci_access_span_src_group_src/tasks", + "name": "tests/integration/targets/aci_fabric_external_connection_profile/tasks", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/aci_access_span_src_group_src/tasks/main.yml", + "name": "tests/integration/targets/aci_fabric_external_connection_profile/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "9dc18d120ffb94f5d068e0d153497a8cf5be32366a8b698b62f0d59bfa40fa6c", + "chksum_sha256": "75f507b1660e5210c8087024f86683df8970405cac3e9588881761cc35bd4b2e", "format": 1 }, { - "name": "tests/integration/targets/aci_access_span_src_group_src/aliases", + "name": "tests/integration/targets/aci_fabric_external_connection_profile/aliases", "ftype": "file", "chksum_type": "sha256", "chksum_sha256": "616f27a9a7bb49e561ef3782330e18d1a8cea3840e3166e798796684dd546a69", "format": 1 }, { - "name": "tests/integration/targets/aci_aaa_ssh_auth", + "name": "tests/integration/targets/aci_config_snapshot", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/aci_aaa_ssh_auth/tasks", + "name": "tests/integration/targets/aci_config_snapshot/tasks", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/aci_aaa_ssh_auth/tasks/main.yml", + "name": "tests/integration/targets/aci_config_snapshot/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "68ea72c2bead2faabb228d2fb91146165c519371bc46ad550c6a5fcb573588cf", + "chksum_sha256": "ffaf6e7f0074f0cc2c13d5de9c6ba0694d99bb7b99be2ca416cc479c4fd41ce3", "format": 1 }, { - "name": "tests/integration/targets/aci_aaa_ssh_auth/aliases", + "name": "tests/integration/targets/aci_config_snapshot/aliases", "ftype": "file", "chksum_type": "sha256", "chksum_sha256": "616f27a9a7bb49e561ef3782330e18d1a8cea3840e3166e798796684dd546a69", "format": 1 }, { - "name": "tests/integration/targets/aci_aaa_ssh_auth/pki", + "name": "tests/integration/targets/aci_config_snapshot/pki", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/aci_aaa_ssh_auth/pki/sshkey.pub", + "name": "tests/integration/targets/aci_config_snapshot/pki/admin.crt", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "7959b2340762581d9379a1fb67ac0664bbf4ba323e8100997ca81237505827f4", + "chksum_sha256": "f97928b2cd1ce43cfe9ae9bbf47a40b858a749c4c3f25a7ec02898611f4fee90", "format": 1 }, { - "name": "tests/integration/targets/aci_system_banner", + "name": "tests/integration/targets/aci_config_snapshot/pki/admin.key", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "947c1b5a6c419641d4b2c8492b91f2d71588958666aeceeffb1f878460b1d256", + "format": 1 + }, + { + "name": "tests/integration/targets/aci_access_span_src_group", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/aci_system_banner/tasks", + "name": "tests/integration/targets/aci_access_span_src_group/tasks", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/aci_system_banner/tasks/main.yml", + "name": "tests/integration/targets/aci_access_span_src_group/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "6055791dda8f2b3c4fa18573d3b704229cda2a6b817f3b8984fd46475d97652f", + "chksum_sha256": "44d4f6f7286395d4b69df747e208f1d70a52a04b68572920c740fdf92faf8d81", "format": 1 }, { - "name": "tests/integration/targets/aci_system_banner/aliases", + "name": "tests/integration/targets/aci_access_span_src_group/aliases", "ftype": "file", "chksum_type": "sha256", "chksum_sha256": "616f27a9a7bb49e561ef3782330e18d1a8cea3840e3166e798796684dd546a69", "format": 1 }, { - "name": "tests/integration/targets/aci_interface_blacklist", + "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_blacklist/tasks", + "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_blacklist/tasks/main.yml", + "name": "tests/integration/targets/aci_interface_policy_leaf_breakout_port_group/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "4d3c6bde54b9a5c3b7c01058b41a3cb7e055425062699463733b0d2bbd0efca4", + "chksum_sha256": "ab95d13dd9a4034c23cbafb5a903a342482cce5002617efc9bae7d96676cb7a0", "format": 1 }, { - "name": "tests/integration/targets/aci_interface_blacklist/aliases", + "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_interface_policy_leaf_profile_fex_policy_group", + "name": "tests/integration/targets/aci_fabric_switch_policy_group", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/aci_interface_policy_leaf_profile_fex_policy_group/tasks", + "name": "tests/integration/targets/aci_fabric_switch_policy_group/tasks", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/aci_interface_policy_leaf_profile_fex_policy_group/tasks/main.yml", + "name": "tests/integration/targets/aci_fabric_switch_policy_group/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "e9f5cff01edb38af15d9db2e2b6a19fb889e6a911dd1c079ddbd2355eea58784", + "chksum_sha256": "0563dc17cad8b553217c1a11c55df9d481539c9f7c76b0a012d21f9e45508320", "format": 1 }, { - "name": "tests/integration/targets/aci_interface_policy_leaf_profile_fex_policy_group/aliases", + "name": "tests/integration/targets/aci_fabric_switch_policy_group/aliases", "ftype": "file", "chksum_type": "sha256", "chksum_sha256": "616f27a9a7bb49e561ef3782330e18d1a8cea3840e3166e798796684dd546a69", "format": 1 }, { - "name": "tests/integration/targets/aci_syslog_remote_dest", + "name": "tests/integration/targets/aci_action_rule_additional_communities", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/aci_syslog_remote_dest/tasks", + "name": "tests/integration/targets/aci_action_rule_additional_communities/tasks", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/aci_syslog_remote_dest/tasks/main.yml", + "name": "tests/integration/targets/aci_action_rule_additional_communities/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "8cdde3499fe651dad5bd9afc73a318d9b2ccbe1ba1bed3d7e3e2829268484373", + "chksum_sha256": "50dc2f6089cf26d9dae4ae3858760d006dee474d8772e3aa8b99c6f005a293bd", "format": 1 }, { - "name": "tests/integration/targets/aci_syslog_remote_dest/aliases", + "name": "tests/integration/targets/aci_action_rule_additional_communities/aliases", "ftype": "file", "chksum_type": "sha256", "chksum_sha256": "616f27a9a7bb49e561ef3782330e18d1a8cea3840e3166e798796684dd546a69", "format": 1 }, { - "name": "tests/integration/targets/aci_vzany_to_contract", + "name": "tests/integration/targets/aci_access_spine_interface_selector", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/aci_vzany_to_contract/tasks", + "name": "tests/integration/targets/aci_access_spine_interface_selector/tasks", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/aci_vzany_to_contract/tasks/main.yml", + "name": "tests/integration/targets/aci_access_spine_interface_selector/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "184e773934f91f4af9a47fe4cc619c0db3f569e95c2b4af41f50e0712c4f056c", + "chksum_sha256": "b0bcd1f6790dbbfc417b4d06bc77bdecd380b2278065e2bac73a115ec8c92d17", "format": 1 }, { - "name": "tests/integration/targets/aci_vzany_to_contract/aliases", + "name": "tests/integration/targets/aci_access_spine_interface_selector/aliases", "ftype": "file", "chksum_type": "sha256", "chksum_sha256": "616f27a9a7bb49e561ef3782330e18d1a8cea3840e3166e798796684dd546a69", "format": 1 }, { - "name": "tests/integration/targets/aci_fabric_leaf_switch_assoc", + "name": "tests/integration/targets/aci_ap", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/aci_fabric_leaf_switch_assoc/tasks", + "name": "tests/integration/targets/aci_ap/tasks", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/aci_fabric_leaf_switch_assoc/tasks/main.yml", + "name": "tests/integration/targets/aci_ap/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "52a606163c2d5b8fde2b7e6024867432468613edb00589d077468cffd51582c2", + "chksum_sha256": "075ea0bef5ce28a4ba9132f3faca6f08d54c4d519820e8acdb7eb29078f4e9ef", "format": 1 }, { - "name": "tests/integration/targets/aci_fabric_leaf_switch_assoc/aliases", + "name": "tests/integration/targets/aci_ap/aliases", "ftype": "file", "chksum_type": "sha256", "chksum_sha256": "616f27a9a7bb49e561ef3782330e18d1a8cea3840e3166e798796684dd546a69", "format": 1 }, { - "name": "tests/integration/targets/aci_contract", + "name": "tests/integration/targets/aci_interface_policy_lldp", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/aci_contract/tasks", + "name": "tests/integration/targets/aci_interface_policy_lldp/tasks", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/aci_contract/tasks/main.yml", + "name": "tests/integration/targets/aci_interface_policy_lldp/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "1d8de08f6d94f24732d428571352d0729799c4060c1ec71ffb98dddafc30ee7e", + "chksum_sha256": "4fc7ace04cc0c032fe5d143344bbd1efe79e4383dae59962e0fe265a28ecd04d", "format": 1 }, { - "name": "tests/integration/targets/aci_contract/aliases", + "name": "tests/integration/targets/aci_interface_policy_lldp/aliases", "ftype": "file", "chksum_type": "sha256", "chksum_sha256": "616f27a9a7bb49e561ef3782330e18d1a8cea3840e3166e798796684dd546a69", "format": 1 }, { - "name": "tests/integration/targets/aci_node_mgmt_epg", + "name": "tests/integration/targets/aci_access_span_src_group_src_path", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/aci_node_mgmt_epg/tasks", + "name": "tests/integration/targets/aci_access_span_src_group_src_path/tasks", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/aci_node_mgmt_epg/tasks/main.yml", + "name": "tests/integration/targets/aci_access_span_src_group_src_path/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "6cc139d0048870bfc25135df76cc9e9489214e42af5ff369491469ecedc7d1ac", + "chksum_sha256": "65adaca0033acf98b08766fdc5743e33aa947639f324dcf7ac2bad8ef4f6c6b0", "format": 1 }, { - "name": "tests/integration/targets/aci_node_mgmt_epg/aliases", + "name": "tests/integration/targets/aci_access_span_src_group_src_path/aliases", "ftype": "file", "chksum_type": "sha256", "chksum_sha256": "616f27a9a7bb49e561ef3782330e18d1a8cea3840e3166e798796684dd546a69", "format": 1 }, { - "name": "tests/integration/targets/aci_l3out_logical_node_profile", + "name": "tests/integration/targets/aci_netflow_monitor_policy", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/aci_l3out_logical_node_profile/tasks", + "name": "tests/integration/targets/aci_netflow_monitor_policy/tasks", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/aci_l3out_logical_node_profile/tasks/main.yml", + "name": "tests/integration/targets/aci_netflow_monitor_policy/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "5ec5e65d1465e02637d52d5bb09fdbe4fda23bd1531dd1c7bcf63a3e6daf69d2", + "chksum_sha256": "812cecdf3a9c2d60c7f12e79df107e590d0be6ad4900c932dd2d3bd8bd1b5bf7", "format": 1 }, { - "name": "tests/integration/targets/aci_l3out_logical_node_profile/aliases", + "name": "tests/integration/targets/aci_netflow_monitor_policy/aliases", "ftype": "file", "chksum_type": "sha256", "chksum_sha256": "616f27a9a7bb49e561ef3782330e18d1a8cea3840e3166e798796684dd546a69", "format": 1 }, { - "name": "tests/integration/targets/aci_l3out", + "name": "tests/integration/targets/aci_interface_policy_l2", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/aci_l3out/tasks", + "name": "tests/integration/targets/aci_interface_policy_l2/tasks", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/aci_l3out/tasks/main.yml", + "name": "tests/integration/targets/aci_interface_policy_l2/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "c085a58785b7e4539654e0254479dd8585f5ed9d94005772e2cff7b02db13e50", + "chksum_sha256": "1b93975510336d9fe01777e4d386dda4f9e2a5e65d812fde144039577ed6d030", "format": 1 }, { - "name": "tests/integration/targets/aci_l3out/aliases", + "name": "tests/integration/targets/aci_interface_policy_l2/aliases", "ftype": "file", "chksum_type": "sha256", "chksum_sha256": "616f27a9a7bb49e561ef3782330e18d1a8cea3840e3166e798796684dd546a69", "format": 1 }, { - "name": "tests/integration/targets/aci_epg_monitoring_policy", + "name": "tests/integration/targets/aci_l3out_route_tag_policy", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/aci_epg_monitoring_policy/tasks", + "name": "tests/integration/targets/aci_l3out_route_tag_policy/tasks", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/aci_epg_monitoring_policy/tasks/main.yml", + "name": "tests/integration/targets/aci_l3out_route_tag_policy/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "cd7cb391b571c4b8294030393cd288334b14eee8c1f88bf678776f8cc60e7440", + "chksum_sha256": "6e154f6c8fb59f20af72b610e90d2c4b624c3ec72b0c5db14b31850325abaa70", "format": 1 }, { - "name": "tests/integration/targets/aci_epg_monitoring_policy/aliases", + "name": "tests/integration/targets/aci_l3out_route_tag_policy/aliases", "ftype": "file", "chksum_type": "sha256", "chksum_sha256": "616f27a9a7bb49e561ef3782330e18d1a8cea3840e3166e798796684dd546a69", "format": 1 }, { - "name": "tests/integration/targets/aci_interface_policy_leaf_policy_group", + "name": "tests/integration/targets/aci_esg_ip_subnet_selector", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/aci_interface_policy_leaf_policy_group/tasks", + "name": "tests/integration/targets/aci_esg_ip_subnet_selector/tasks", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/aci_interface_policy_leaf_policy_group/tasks/main.yml", + "name": "tests/integration/targets/aci_esg_ip_subnet_selector/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "8821f0cf43e9a9d1f5d8965fc4b38f78a75d62d1b599a74a4dff8546e9866919", + "chksum_sha256": "784db6c69ed7752334eeba70e235637730f04f76649d8dee8802dc2265a68036", "format": 1 }, { - "name": "tests/integration/targets/aci_interface_policy_leaf_policy_group/aliases", + "name": "tests/integration/targets/aci_esg_ip_subnet_selector/aliases", "ftype": "file", "chksum_type": "sha256", "chksum_sha256": "616f27a9a7bb49e561ef3782330e18d1a8cea3840e3166e798796684dd546a69", "format": 1 }, { - "name": "tests/integration/targets/aci_match_route_destination", + "name": "tests/integration/targets/aci_access_switch_policy_group", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/aci_match_route_destination/tasks", + "name": "tests/integration/targets/aci_access_switch_policy_group/tasks", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/aci_match_route_destination/tasks/main.yml", + "name": "tests/integration/targets/aci_access_switch_policy_group/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "85f354ddd29b16e87aaa87111e966a120a6c6003d9a20426900be897c2920a87", + "chksum_sha256": "a96c613da3cfcb8d4877a515c47a85c5611941611aa6f6d5b5b8acd383bd1048", "format": 1 }, { - "name": "tests/integration/targets/aci_match_route_destination/aliases", + "name": "tests/integration/targets/aci_access_switch_policy_group/aliases", "ftype": "file", "chksum_type": "sha256", "chksum_sha256": "616f27a9a7bb49e561ef3782330e18d1a8cea3840e3166e798796684dd546a69", "format": 1 }, { - "name": "tests/integration/targets/aci_lookup_interface_range", + "name": "tests/integration/targets/aci_interface_policy_eigrp", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/aci_lookup_interface_range/tasks", + "name": "tests/integration/targets/aci_interface_policy_eigrp/tasks", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/aci_lookup_interface_range/tasks/main.yml", + "name": "tests/integration/targets/aci_interface_policy_eigrp/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "2dcf9c4f3ee3490c49c1231b11d66fc565c936109235e174d452d072b4b02dcc", + "chksum_sha256": "21ef50711ac13abe3fe324cb574e510d8552751d4745af7dc4704a5e740f56bb", "format": 1 }, { - "name": "tests/integration/targets/aci_lookup_interface_range/aliases", + "name": "tests/integration/targets/aci_interface_policy_eigrp/aliases", "ftype": "file", "chksum_type": "sha256", "chksum_sha256": "616f27a9a7bb49e561ef3782330e18d1a8cea3840e3166e798796684dd546a69", "format": 1 }, { - "name": "tests/integration/targets/aci_vmm_controller", + "name": "tests/integration/targets/aci_fabric_span_src_group_src_node", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/aci_vmm_controller/tasks", + "name": "tests/integration/targets/aci_fabric_span_src_group_src_node/tasks", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/aci_vmm_controller/tasks/main.yml", + "name": "tests/integration/targets/aci_fabric_span_src_group_src_node/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "3b4854c79b639f404cb9aa8636019081e6bb5c8084848e5d81757537d28f3c5f", + "chksum_sha256": "740872eb37c6af94636ad16b317b0ff68d99c18975f41c2cf09b83ac4999cdb7", "format": 1 }, { - "name": "tests/integration/targets/aci_vmm_controller/aliases", + "name": "tests/integration/targets/aci_fabric_span_src_group_src_node/aliases", "ftype": "file", "chksum_type": "sha256", "chksum_sha256": "616f27a9a7bb49e561ef3782330e18d1a8cea3840e3166e798796684dd546a69", "format": 1 }, { - "name": "tests/integration/targets/aci_match_community_factor", + "name": "tests/integration/targets/aci_fabric_pod_selector", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/aci_match_community_factor/tasks", + "name": "tests/integration/targets/aci_fabric_pod_selector/tasks", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/aci_match_community_factor/tasks/main.yml", + "name": "tests/integration/targets/aci_fabric_pod_selector/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "85b19ffcc7f1722664426544bc85648f722f8cda85876e702b651174a6d6c251", + "chksum_sha256": "acf9ceb102cdf9dd068fe5fb2d251b723c1800d1878f9a9232a49a25e1533b08", "format": 1 }, { - "name": "tests/integration/targets/aci_match_community_factor/aliases", + "name": "tests/integration/targets/aci_fabric_pod_selector/aliases", "ftype": "file", "chksum_type": "sha256", "chksum_sha256": "616f27a9a7bb49e561ef3782330e18d1a8cea3840e3166e798796684dd546a69", "format": 1 }, { - "name": "tests/integration/targets/aci_interface_policy_spine_policy_group", + "name": "tests/integration/targets/aci_bd_subnet", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/aci_interface_policy_spine_policy_group/tasks", + "name": "tests/integration/targets/aci_bd_subnet/tasks", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/aci_interface_policy_spine_policy_group/tasks/main.yml", + "name": "tests/integration/targets/aci_bd_subnet/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "70e00aa9a7355ec778b136a583b71ac3211f5cd0a37e4574b5b9f421f99ab6ea", + "chksum_sha256": "c85f1df14defc8594e85dab41d012f478841a580c2b4bbd63584d0fc52517897", "format": 1 }, { - "name": "tests/integration/targets/aci_interface_policy_spine_policy_group/aliases", + "name": "tests/integration/targets/aci_bd_subnet/aliases", "ftype": "file", "chksum_type": "sha256", "chksum_sha256": "616f27a9a7bb49e561ef3782330e18d1a8cea3840e3166e798796684dd546a69", "format": 1 }, { - "name": "tests/integration/targets/aci_contract_subject_to_service_graph", + "name": "tests/integration/targets/aci_access_span_src_group_src", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/aci_contract_subject_to_service_graph/tasks", + "name": "tests/integration/targets/aci_access_span_src_group_src/tasks", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/aci_contract_subject_to_service_graph/tasks/main.yml", + "name": "tests/integration/targets/aci_access_span_src_group_src/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "715f1489683ba74fed4c3301e483f8ceeec58119bcbf765eab406b134d7954c6", + "chksum_sha256": "5cafc8dd677930fd24fe7c90eaa2506bf9e169b3c5642d708ebe9ab6b3833197", "format": 1 }, { - "name": "tests/integration/targets/aci_contract_subject_to_service_graph/aliases", + "name": "tests/integration/targets/aci_access_span_src_group_src/aliases", "ftype": "file", "chksum_type": "sha256", "chksum_sha256": "616f27a9a7bb49e561ef3782330e18d1a8cea3840e3166e798796684dd546a69", "format": 1 }, { - "name": "tests/integration/targets/aci_l3out_extepg_to_contract", + "name": "tests/integration/targets/aci_aaa_ssh_auth", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/aci_l3out_extepg_to_contract/tasks", + "name": "tests/integration/targets/aci_aaa_ssh_auth/tasks", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/aci_l3out_extepg_to_contract/tasks/main.yml", + "name": "tests/integration/targets/aci_aaa_ssh_auth/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "89289a10d688f0af43ab79066c1bf433d8117b54cc8d3cf02bda857edd507699", + "chksum_sha256": "272463007e5206c3bb50044a00296247d115f393bdd411ca8486a7f2b58d8cec", "format": 1 }, { - "name": "tests/integration/targets/aci_l3out_extepg_to_contract/aliases", + "name": "tests/integration/targets/aci_aaa_ssh_auth/aliases", "ftype": "file", "chksum_type": "sha256", "chksum_sha256": "616f27a9a7bb49e561ef3782330e18d1a8cea3840e3166e798796684dd546a69", "format": 1 }, { - "name": "tests/integration/targets/aci_esg_tag_selector", + "name": "tests/integration/targets/aci_aaa_ssh_auth/pki", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/aci_esg_tag_selector/tasks", + "name": "tests/integration/targets/aci_aaa_ssh_auth/pki/sshkey.pub", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "7959b2340762581d9379a1fb67ac0664bbf4ba323e8100997ca81237505827f4", + "format": 1 + }, + { + "name": "tests/integration/targets/aci_epg_useg_attribute_simple_statement", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/aci_esg_tag_selector/tasks/main.yml", + "name": "tests/integration/targets/aci_epg_useg_attribute_simple_statement/tasks", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, + "format": 1 + }, + { + "name": "tests/integration/targets/aci_epg_useg_attribute_simple_statement/tasks/simple_block_levels.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "19d6518c1375739ee95c6016e97bfa1aab3da1e6db19429ce9d89006c5236d63", + "chksum_sha256": "edf2582d6c826c327514d6dc3ca831527542282cc6558396cf9dad006d930508", "format": 1 }, { - "name": "tests/integration/targets/aci_esg_tag_selector/aliases", + "name": "tests/integration/targets/aci_epg_useg_attribute_simple_statement/tasks/main.yml", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "854587afcd7496318201bffe566e135734afe00993dbe3800f5b86935ef9a428", + "format": 1 + }, + { + "name": "tests/integration/targets/aci_epg_useg_attribute_simple_statement/aliases", "ftype": "file", "chksum_type": "sha256", "chksum_sha256": "616f27a9a7bb49e561ef3782330e18d1a8cea3840e3166e798796684dd546a69", "format": 1 }, { - "name": "tests/integration/targets/aci_taboo_contract", + "name": "tests/integration/targets/aci_system_banner", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/aci_taboo_contract/tasks", + "name": "tests/integration/targets/aci_system_banner/tasks", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/aci_taboo_contract/tasks/main.yml", + "name": "tests/integration/targets/aci_system_banner/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "8108b12b09f191cd13cbf4c5fc15132979a8a64fc070ccdd1f3053b4fcc05180", + "chksum_sha256": "c3dfe182aa2cc04090da103aec29a93790275b8cbd966453c688f70adf95887e", "format": 1 }, { - "name": "tests/integration/targets/aci_taboo_contract/aliases", + "name": "tests/integration/targets/aci_system_banner/aliases", "ftype": "file", "chksum_type": "sha256", "chksum_sha256": "616f27a9a7bb49e561ef3782330e18d1a8cea3840e3166e798796684dd546a69", "format": 1 }, { - "name": "tests/integration/targets/aci_domain_to_vlan_pool", + "name": "tests/integration/targets/aci_interface_blacklist", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/aci_domain_to_vlan_pool/tasks", + "name": "tests/integration/targets/aci_interface_blacklist/tasks", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/aci_domain_to_vlan_pool/tasks/main.yml", + "name": "tests/integration/targets/aci_interface_blacklist/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "7f14fc189439710b1e57a89af9ba53d34850b8b289c59207b9239d73cd0edabd", + "chksum_sha256": "7e86f9f41542e3e6c9a14533ee6eaad79e234ecb97450ed72c8af934930ec2b9", "format": 1 }, { - "name": "tests/integration/targets/aci_domain_to_vlan_pool/aliases", + "name": "tests/integration/targets/aci_interface_blacklist/aliases", "ftype": "file", "chksum_type": "sha256", "chksum_sha256": "616f27a9a7bb49e561ef3782330e18d1a8cea3840e3166e798796684dd546a69", "format": 1 }, { - "name": "tests/integration/targets/aci_epg_to_domain", + "name": "tests/integration/targets/aci_interface_policy_leaf_profile_fex_policy_group", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/aci_epg_to_domain/tasks", + "name": "tests/integration/targets/aci_interface_policy_leaf_profile_fex_policy_group/tasks", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/aci_epg_to_domain/tasks/main.yml", + "name": "tests/integration/targets/aci_interface_policy_leaf_profile_fex_policy_group/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "2aa9a7c427ad9d6d2aeb1c9454537ec1df404ca85a1c0a2da43412816fe0d2ff", + "chksum_sha256": "14bd6dbb8fbe95f5005695ef99617f07f339fb400d4cb0c58a3f95b406b24980", "format": 1 }, { - "name": "tests/integration/targets/aci_epg_to_domain/aliases", + "name": "tests/integration/targets/aci_interface_policy_leaf_profile_fex_policy_group/aliases", "ftype": "file", "chksum_type": "sha256", "chksum_sha256": "616f27a9a7bb49e561ef3782330e18d1a8cea3840e3166e798796684dd546a69", "format": 1 }, { - "name": "tests/integration/targets/aci_dhcp_relay_provider", + "name": "tests/integration/targets/aci_syslog_remote_dest", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/aci_dhcp_relay_provider/tasks", + "name": "tests/integration/targets/aci_syslog_remote_dest/tasks", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/aci_dhcp_relay_provider/tasks/main.yml", + "name": "tests/integration/targets/aci_syslog_remote_dest/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "3bcac5486e000d2c50ae9d748e6ac6870227c67671d6d43603f272f198adb317", + "chksum_sha256": "329bb76f7ef5d3580e95ed6b3b97ac3b9a608b5a6535d8897ea48a6d1ef8f9d4", "format": 1 }, { - "name": "tests/integration/targets/aci_dhcp_relay_provider/aliases", + "name": "tests/integration/targets/aci_syslog_remote_dest/aliases", "ftype": "file", "chksum_type": "sha256", "chksum_sha256": "616f27a9a7bb49e561ef3782330e18d1a8cea3840e3166e798796684dd546a69", "format": 1 }, { - "name": "tests/integration/targets/aci_fabric_node_control", + "name": "tests/integration/targets/aci_vzany_to_contract", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/aci_fabric_node_control/tasks", + "name": "tests/integration/targets/aci_vzany_to_contract/tasks", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/aci_fabric_node_control/tasks/main.yml", + "name": "tests/integration/targets/aci_vzany_to_contract/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "be5b110f64ea6906839446cb0d79b30222fda3a9f4afb9da7cbb10bc75944898", + "chksum_sha256": "393485c2f5a01f6af10d1304437784bcfa89f1b000aa39275bb25b3f137c288e", "format": 1 }, { - "name": "tests/integration/targets/aci_fabric_node_control/aliases", + "name": "tests/integration/targets/aci_vzany_to_contract/aliases", "ftype": "file", "chksum_type": "sha256", "chksum_sha256": "616f27a9a7bb49e561ef3782330e18d1a8cea3840e3166e798796684dd546a69", "format": 1 }, { - "name": "tests/integration/targets/aci_interface_policy_cdp", + "name": "tests/integration/targets/aci_fabric_leaf_switch_assoc", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/aci_interface_policy_cdp/tasks", + "name": "tests/integration/targets/aci_fabric_leaf_switch_assoc/tasks", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/aci_interface_policy_cdp/tasks/main.yml", + "name": "tests/integration/targets/aci_fabric_leaf_switch_assoc/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "4392aea7e298d85716756da20857a58467bbda2b4f92d1d711ed1b6fd368325c", + "chksum_sha256": "6a2fb0ef7a000a6222909878c191e8abfba89b6b049f6ab1fca1765dbdb70435", "format": 1 }, { - "name": "tests/integration/targets/aci_interface_policy_cdp/aliases", + "name": "tests/integration/targets/aci_fabric_leaf_switch_assoc/aliases", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "7e5f1f59656b5c296b78849e4845810f74bbe10151203a6d224474a31f470f3f", + "chksum_sha256": "616f27a9a7bb49e561ef3782330e18d1a8cea3840e3166e798796684dd546a69", "format": 1 }, { - "name": "tests/integration/targets/aci_fabric_switch_block", + "name": "tests/integration/targets/aci_contract", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/aci_fabric_switch_block/tasks", + "name": "tests/integration/targets/aci_contract/tasks", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/aci_fabric_switch_block/tasks/main.yml", + "name": "tests/integration/targets/aci_contract/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "423c915493cf75de78c63b152093ddf0066dfd04327a79384c753ddaf3c99ca6", + "chksum_sha256": "6c3d695d9cc94bfb6edb9c98da462c4129f2ba7a72d57f3ccbb7fc2e993d2cbe", "format": 1 }, { - "name": "tests/integration/targets/aci_fabric_switch_block/aliases", + "name": "tests/integration/targets/aci_contract/aliases", "ftype": "file", "chksum_type": "sha256", "chksum_sha256": "616f27a9a7bb49e561ef3782330e18d1a8cea3840e3166e798796684dd546a69", "format": 1 }, { - "name": "tests/integration/targets/aci_tenant", + "name": "tests/integration/targets/aci_node_mgmt_epg", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/aci_tenant/tasks", + "name": "tests/integration/targets/aci_node_mgmt_epg/tasks", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/aci_tenant/tasks/httpapi_connection.yml", + "name": "tests/integration/targets/aci_node_mgmt_epg/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "af2e683ad88998f1ff8062ded1c66873ce24f38165afca72d36356e435e295b5", + "chksum_sha256": "fc7475fc26e0422513ff3607cc7d961f22351dd5feab56321731796a812341f2", "format": 1 }, { - "name": "tests/integration/targets/aci_tenant/tasks/main.yml", + "name": "tests/integration/targets/aci_node_mgmt_epg/aliases", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "6a0620f26d77dee85bcf88b1bdc61aaadc57fd04daafaa6bd91cc8a0898ac507", + "chksum_sha256": "616f27a9a7bb49e561ef3782330e18d1a8cea3840e3166e798796684dd546a69", "format": 1 }, { - "name": "tests/integration/targets/aci_tenant/filter_plugins", + "name": "tests/integration/targets/aci_l3out_bfd_multihop_interface_profile", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/aci_tenant/filter_plugins/generate_ips.py", + "name": "tests/integration/targets/aci_l3out_bfd_multihop_interface_profile/tasks", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, + "format": 1 + }, + { + "name": "tests/integration/targets/aci_l3out_bfd_multihop_interface_profile/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "334529a31b2760cdccb063474365dcb062a0e7c7f5a643f50a313100ada78a78", + "chksum_sha256": "7478cb13ebcf26986773947a04936f91cb724ad1d780e8061eb8664e7bc9d42c", "format": 1 }, { - "name": "tests/integration/targets/aci_tenant/aliases", + "name": "tests/integration/targets/aci_l3out_bfd_multihop_interface_profile/aliases", "ftype": "file", "chksum_type": "sha256", "chksum_sha256": "616f27a9a7bb49e561ef3782330e18d1a8cea3840e3166e798796684dd546a69", "format": 1 }, { - "name": "tests/integration/targets/aci_tenant/pki", + "name": "tests/integration/targets/aci_pim_route_map_entry", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/aci_tenant/pki/admin_invalid.key", - "ftype": "file", - "chksum_type": "sha256", - "chksum_sha256": "55fb85eae133a7b8649703b1d6e303cdf5b585d381e761f3674d1fcc5beb40cb", + "name": "tests/integration/targets/aci_pim_route_map_entry/tasks", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/aci_tenant/pki/rsa_user.key", + "name": "tests/integration/targets/aci_pim_route_map_entry/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "8a74dffaf7d04e74642988302b185f0e9eda2dd35a5b7f32317696b12a9790c1", + "chksum_sha256": "f5d9d462368cb9b72d836aca6dfda0ba5fa4d4845a74e4475ffe2f2cd6d36eb5", "format": 1 }, { - "name": "tests/integration/targets/aci_tenant/pki/admin.crt", + "name": "tests/integration/targets/aci_pim_route_map_entry/aliases", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "f97928b2cd1ce43cfe9ae9bbf47a40b858a749c4c3f25a7ec02898611f4fee90", + "chksum_sha256": "616f27a9a7bb49e561ef3782330e18d1a8cea3840e3166e798796684dd546a69", "format": 1 }, { - "name": "tests/integration/targets/aci_tenant/pki/openssh_rsa.key", - "ftype": "file", - "chksum_type": "sha256", - "chksum_sha256": "81a6ac3a61f2df64339252db67fea1307e891c41232e2da53a1e5219f677c917", + "name": "tests/integration/targets/aci_l3out_logical_node_profile", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/aci_tenant/pki/admin.key", - "ftype": "file", - "chksum_type": "sha256", - "chksum_sha256": "947c1b5a6c419641d4b2c8492b91f2d71588958666aeceeffb1f878460b1d256", + "name": "tests/integration/targets/aci_l3out_logical_node_profile/tasks", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/aci_tenant/pki/rsa_user.crt", + "name": "tests/integration/targets/aci_l3out_logical_node_profile/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "77629e6b31c8c9fad7052f4696dcead786fecef66e33e81c50ce09fcb39d8b4a", + "chksum_sha256": "e01c83bb926d73f2696b0c80aa32ef57ada9421d70edcfa28fabf2d28c1a88cc", "format": 1 }, { - "name": "tests/integration/targets/aci_tenant/pki/rsa_ansible.key", + "name": "tests/integration/targets/aci_l3out_logical_node_profile/aliases", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "6945fcb844179106a63be7e8ea5b407f31a8a1e95a1eaa0b5e67da1c26802032", + "chksum_sha256": "616f27a9a7bb49e561ef3782330e18d1a8cea3840e3166e798796684dd546a69", "format": 1 }, { - "name": "tests/integration/targets/aci_maintenance_group_node", + "name": "tests/integration/targets/aci_l3out", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/aci_maintenance_group_node/tasks", + "name": "tests/integration/targets/aci_l3out/tasks", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/aci_maintenance_group_node/tasks/main.yml", + "name": "tests/integration/targets/aci_l3out/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "b342a36b963e0b3001e11800be162c1faf958dc1bdfa552f32b928c516a532ed", + "chksum_sha256": "f2f3db1f45a197eb63ee2abf69d3846e003169bc8a005a7f4d8d8f2ceaafb6c8", "format": 1 }, { - "name": "tests/integration/targets/aci_maintenance_group_node/aliases", + "name": "tests/integration/targets/aci_l3out/aliases", "ftype": "file", "chksum_type": "sha256", "chksum_sha256": "616f27a9a7bb49e561ef3782330e18d1a8cea3840e3166e798796684dd546a69", "format": 1 }, { - "name": "tests/integration/targets/aci_syslog_group", + "name": "tests/integration/targets/aci_epg_monitoring_policy", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/aci_syslog_group/tasks", + "name": "tests/integration/targets/aci_epg_monitoring_policy/tasks", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/aci_syslog_group/tasks/main.yml", + "name": "tests/integration/targets/aci_epg_monitoring_policy/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "b19762539379f2b450c6fa4619679431461b7820a2fd498c76164f476241726b", + "chksum_sha256": "24b071e6239b75d757f3e3f4f781d02ac2cb5c8e115c6c1ceda273d0cc1fdd58", "format": 1 }, { - "name": "tests/integration/targets/aci_syslog_group/aliases", + "name": "tests/integration/targets/aci_epg_monitoring_policy/aliases", "ftype": "file", "chksum_type": "sha256", "chksum_sha256": "616f27a9a7bb49e561ef3782330e18d1a8cea3840e3166e798796684dd546a69", "format": 1 }, { - "name": "tests/integration/targets/aci_route_control_profile", + "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_route_control_profile/tasks", + "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_route_control_profile/tasks/main.yml", + "name": "tests/integration/targets/aci_interface_policy_leaf_policy_group/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "f5c0118b53e4cab847d81acd60edfba3e5f58a263aa32f980ccce6c9240a2f09", + "chksum_sha256": "dd96b5ca42b731af07e3ea81b610077b65049ffdb61b0410c595939c626394f8", "format": 1 }, { - "name": "tests/integration/targets/aci_route_control_profile/aliases", + "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_snmp_client", + "name": "tests/integration/targets/aci_fabric_management_access_https_cipher", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/aci_snmp_client/tasks", + "name": "tests/integration/targets/aci_fabric_management_access_https_cipher/tasks", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/aci_snmp_client/tasks/main.yml", + "name": "tests/integration/targets/aci_fabric_management_access_https_cipher/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "b6aeebb21b6c1e350325f298e3cd1d98615dc2a5d12916783b06c259fccd0357", + "chksum_sha256": "354499d076d51762359bc6754bf7a3419a8adcf808c5a531e7a3ed5d3bdb8576", "format": 1 }, { - "name": "tests/integration/targets/aci_snmp_client/aliases", + "name": "tests/integration/targets/aci_fabric_management_access_https_cipher/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", + "name": "tests/integration/targets/aci_fabric_management_access_https_cipher/pki", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/aci_aep/tasks/main.yml", + "name": "tests/integration/targets/aci_fabric_management_access_https_cipher/pki/admin.crt", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "e77d10440880f6638ea10d90eb11baf49ad2c213760740ae224fb7582ce5410f", + "chksum_sha256": "f97928b2cd1ce43cfe9ae9bbf47a40b858a749c4c3f25a7ec02898611f4fee90", "format": 1 }, { - "name": "tests/integration/targets/aci_aep/aliases", + "name": "tests/integration/targets/aci_fabric_management_access_https_cipher/pki/admin.key", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "616f27a9a7bb49e561ef3782330e18d1a8cea3840e3166e798796684dd546a69", + "chksum_sha256": "947c1b5a6c419641d4b2c8492b91f2d71588958666aeceeffb1f878460b1d256", "format": 1 }, { - "name": "tests/integration/targets/aci_l3out_logical_interface_profile", + "name": "tests/integration/targets/aci_match_route_destination", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/aci_l3out_logical_interface_profile/tasks", + "name": "tests/integration/targets/aci_match_route_destination/tasks", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, + "format": 1 + }, + { + "name": "tests/integration/targets/aci_match_route_destination/tasks/main.yml", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "2f4b74df3f41c9c953b17a5507582414ef917228a975b2cdfea50f9f1bfe0a60", + "format": 1 + }, + { + "name": "tests/integration/targets/aci_match_route_destination/aliases", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "616f27a9a7bb49e561ef3782330e18d1a8cea3840e3166e798796684dd546a69", + "format": 1 + }, + { + "name": "tests/integration/targets/aci_access_spine_interface_profile_to_spine_switch_profile", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, + "format": 1 + }, + { + "name": "tests/integration/targets/aci_access_spine_interface_profile_to_spine_switch_profile/tasks", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, + "format": 1 + }, + { + "name": "tests/integration/targets/aci_access_spine_interface_profile_to_spine_switch_profile/tasks/main.yml", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "b3df535e49bc0be8388c197c5b0bf033531b251ed9d006b54680657fb9b44617", + "format": 1 + }, + { + "name": "tests/integration/targets/aci_access_spine_interface_profile_to_spine_switch_profile/aliases", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "616f27a9a7bb49e561ef3782330e18d1a8cea3840e3166e798796684dd546a69", + "format": 1 + }, + { + "name": "tests/integration/targets/aci_subject_label", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, + "format": 1 + }, + { + "name": "tests/integration/targets/aci_subject_label/tasks", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, + "format": 1 + }, + { + "name": "tests/integration/targets/aci_subject_label/tasks/subject_label.yml", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "b0142be114c5b41e92d0606b6773f88956d6364426921d61a9d8c3917593e95c", + "format": 1 + }, + { + "name": "tests/integration/targets/aci_subject_label/tasks/main.yml", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "b6766924ad4faf3897216406eebf0db680a19b16eacabd23b54aec4e1930c7b9", + "format": 1 + }, + { + "name": "tests/integration/targets/aci_subject_label/aliases", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "616f27a9a7bb49e561ef3782330e18d1a8cea3840e3166e798796684dd546a69", + "format": 1 + }, + { + "name": "tests/integration/targets/aci_lookup_interface_range", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, + "format": 1 + }, + { + "name": "tests/integration/targets/aci_lookup_interface_range/tasks", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, + "format": 1 + }, + { + "name": "tests/integration/targets/aci_lookup_interface_range/tasks/main.yml", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "221de56e6663fa2dceb813ad609f945c98710d6fbcadcae7c5a33e4a7b6e9051", + "format": 1 + }, + { + "name": "tests/integration/targets/aci_lookup_interface_range/aliases", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "616f27a9a7bb49e561ef3782330e18d1a8cea3840e3166e798796684dd546a69", + "format": 1 + }, + { + "name": "tests/integration/targets/aci_action_rule_set_as_path", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, + "format": 1 + }, + { + "name": "tests/integration/targets/aci_action_rule_set_as_path/tasks", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, + "format": 1 + }, + { + "name": "tests/integration/targets/aci_action_rule_set_as_path/tasks/main.yml", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "68ce66ae1b1a1475fbbc7f7ec356c4d869ae309edd1ef84d29db395d95c4b8cb", + "format": 1 + }, + { + "name": "tests/integration/targets/aci_action_rule_set_as_path/aliases", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "616f27a9a7bb49e561ef3782330e18d1a8cea3840e3166e798796684dd546a69", + "format": 1 + }, + { + "name": "tests/integration/targets/aci_l3out_hsrp_interface_profile", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, + "format": 1 + }, + { + "name": "tests/integration/targets/aci_l3out_hsrp_interface_profile/tasks", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, + "format": 1 + }, + { + "name": "tests/integration/targets/aci_l3out_hsrp_interface_profile/tasks/main.yml", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "70a846f11cd8a5d33689ccdb3c4bd8175e71775ea26a44479448bb4dc56fc51f", + "format": 1 + }, + { + "name": "tests/integration/targets/aci_l3out_hsrp_interface_profile/aliases", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "616f27a9a7bb49e561ef3782330e18d1a8cea3840e3166e798796684dd546a69", + "format": 1 + }, + { + "name": "tests/integration/targets/aci_vmm_controller", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, + "format": 1 + }, + { + "name": "tests/integration/targets/aci_vmm_controller/tasks", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, + "format": 1 + }, + { + "name": "tests/integration/targets/aci_vmm_controller/tasks/main.yml", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "5a3cd55149d7f96da70469e19735ab3c66f1035b7c16c408e012d9abf0e8585c", + "format": 1 + }, + { + "name": "tests/integration/targets/aci_vmm_controller/aliases", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "616f27a9a7bb49e561ef3782330e18d1a8cea3840e3166e798796684dd546a69", + "format": 1 + }, + { + "name": "tests/integration/targets/aci_match_community_factor", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, + "format": 1 + }, + { + "name": "tests/integration/targets/aci_match_community_factor/tasks", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, + "format": 1 + }, + { + "name": "tests/integration/targets/aci_match_community_factor/tasks/main.yml", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "88bfb2ad054c03baaa0deb48b1ca92378c2861e268f405f01eeb24367ea803ba", + "format": 1 + }, + { + "name": "tests/integration/targets/aci_match_community_factor/aliases", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "616f27a9a7bb49e561ef3782330e18d1a8cea3840e3166e798796684dd546a69", + "format": 1 + }, + { + "name": "tests/integration/targets/aci_netflow_exporter_policy", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, + "format": 1 + }, + { + "name": "tests/integration/targets/aci_netflow_exporter_policy/tasks", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, + "format": 1 + }, + { + "name": "tests/integration/targets/aci_netflow_exporter_policy/tasks/main.yml", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "d5db92b4f7d533301c0d74cd6e43168f20f9e958fbb1df411243429fe31b14bb", + "format": 1 + }, + { + "name": "tests/integration/targets/aci_netflow_exporter_policy/aliases", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "616f27a9a7bb49e561ef3782330e18d1a8cea3840e3166e798796684dd546a69", + "format": 1 + }, + { + "name": "tests/integration/targets/aci_interface_policy_spine_policy_group", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, + "format": 1 + }, + { + "name": "tests/integration/targets/aci_interface_policy_spine_policy_group/tasks", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, + "format": 1 + }, + { + "name": "tests/integration/targets/aci_interface_policy_spine_policy_group/tasks/main.yml", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "f549bb6df8c4bb50f2b90e7396eb1821f6bcdc1b73692e7086e84918fd4a71fd", + "format": 1 + }, + { + "name": "tests/integration/targets/aci_interface_policy_spine_policy_group/aliases", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "616f27a9a7bb49e561ef3782330e18d1a8cea3840e3166e798796684dd546a69", + "format": 1 + }, + { + "name": "tests/integration/targets/aci_contract_subject_to_service_graph", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, + "format": 1 + }, + { + "name": "tests/integration/targets/aci_contract_subject_to_service_graph/tasks", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, + "format": 1 + }, + { + "name": "tests/integration/targets/aci_contract_subject_to_service_graph/tasks/main.yml", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "adc631affae75b956ad1706c342768534435020288b484e5b9206e15f577723a", + "format": 1 + }, + { + "name": "tests/integration/targets/aci_contract_subject_to_service_graph/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": "c4235e10fba80f4cfa51414d789fc641b110a586ce680758fc473008c16679d4", + "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_esg_tag_selector", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, + "format": 1 + }, + { + "name": "tests/integration/targets/aci_esg_tag_selector/tasks", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, + "format": 1 + }, + { + "name": "tests/integration/targets/aci_esg_tag_selector/tasks/main.yml", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "e8737e49c607fc4ea8d3e1be17786d980145bac3a8a47b37e342852dbd35b19e", + "format": 1 + }, + { + "name": "tests/integration/targets/aci_esg_tag_selector/aliases", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "616f27a9a7bb49e561ef3782330e18d1a8cea3840e3166e798796684dd546a69", + "format": 1 + }, + { + "name": "tests/integration/targets/aci_fabric_pod_remote_pool", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, + "format": 1 + }, + { + "name": "tests/integration/targets/aci_fabric_pod_remote_pool/tasks", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, + "format": 1 + }, + { + "name": "tests/integration/targets/aci_fabric_pod_remote_pool/tasks/main.yml", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "211d91283dcb13d28868f7b3b688878b26bfa80f28b6b5fdc34219908a7d457b", + "format": 1 + }, + { + "name": "tests/integration/targets/aci_fabric_pod_remote_pool/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": "cccae803763b432f0e46dd690c1246c7890f0c15d43afb738aed1f5e7aec2f4f", + "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": "1be874b2846aa8cc3262e2fd72f54e4be879ed8cf182f3455dbdfb821ea3fd52", + "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_interface_policy_bfd", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, + "format": 1 + }, + { + "name": "tests/integration/targets/aci_interface_policy_bfd/tasks", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, + "format": 1 + }, + { + "name": "tests/integration/targets/aci_interface_policy_bfd/tasks/main.yml", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "d8e3ac7fb7082101ca2357634854a1ff6d4c55985a2b0678e41255c2a616518c", + "format": 1 + }, + { + "name": "tests/integration/targets/aci_interface_policy_bfd/aliases", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "616f27a9a7bb49e561ef3782330e18d1a8cea3840e3166e798796684dd546a69", + "format": 1 + }, + { + "name": "tests/integration/targets/aci_l3out_hsrp_secondary_vip", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, + "format": 1 + }, + { + "name": "tests/integration/targets/aci_l3out_hsrp_secondary_vip/tasks", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, + "format": 1 + }, + { + "name": "tests/integration/targets/aci_l3out_hsrp_secondary_vip/tasks/main.yml", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "315756f685e0511637fe2aa9059d2ead8bfecfd8757d44118e1df482552fd54d", + "format": 1 + }, + { + "name": "tests/integration/targets/aci_l3out_hsrp_secondary_vip/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": "e532d3cb3ba4bfd61a9743796bee3e77a7f8dba5432ca556eee75acd28e7d259", + "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_dhcp_relay_provider", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, + "format": 1 + }, + { + "name": "tests/integration/targets/aci_dhcp_relay_provider/tasks", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, + "format": 1 + }, + { + "name": "tests/integration/targets/aci_dhcp_relay_provider/tasks/main.yml", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "8ce53bdb5cb776c76480212771310300dfc3914a788b5f4e5dce7c1422c6be0b", + "format": 1 + }, + { + "name": "tests/integration/targets/aci_dhcp_relay_provider/aliases", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "616f27a9a7bb49e561ef3782330e18d1a8cea3840e3166e798796684dd546a69", + "format": 1 + }, + { + "name": "tests/integration/targets/aci_fabric_node_control", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, + "format": 1 + }, + { + "name": "tests/integration/targets/aci_fabric_node_control/tasks", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, + "format": 1 + }, + { + "name": "tests/integration/targets/aci_fabric_node_control/tasks/main.yml", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "c59e43442f0f1a1ee20a22249c7719a051efb76b4cf8475aa6038021089d613d", + "format": 1 + }, + { + "name": "tests/integration/targets/aci_fabric_node_control/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": "151d65b7a851eecaa7b3d3e57a8b3cb04900087f5104825a83d63a104d775a6a", + "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_fabric_switch_block", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, + "format": 1 + }, + { + "name": "tests/integration/targets/aci_fabric_switch_block/tasks", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, + "format": 1 + }, + { + "name": "tests/integration/targets/aci_fabric_switch_block/tasks/main.yml", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "875c4f67b25a7e8f915926dd63b1ffc62c8b60e6a68245e9e3b4a44a4115854f", + "format": 1 + }, + { + "name": "tests/integration/targets/aci_fabric_switch_block/aliases", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "616f27a9a7bb49e561ef3782330e18d1a8cea3840e3166e798796684dd546a69", + "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/httpapi_connection.yml", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "374084c2e47bb24fb55ccd963f962ca99de7504897e53b6cfeb68ba75710f5b1", + "format": 1 + }, + { + "name": "tests/integration/targets/aci_tenant/tasks/main.yml", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "768148a4cfb5ac46096dae214c9301edbd62409cb29273417f1d7de9e4a9e79a", + "format": 1 + }, + { + "name": "tests/integration/targets/aci_tenant/filter_plugins", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, + "format": 1 + }, + { + "name": "tests/integration/targets/aci_tenant/filter_plugins/generate_ips.py", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "334529a31b2760cdccb063474365dcb062a0e7c7f5a643f50a313100ada78a78", + "format": 1 + }, + { + "name": "tests/integration/targets/aci_tenant/aliases", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "616f27a9a7bb49e561ef3782330e18d1a8cea3840e3166e798796684dd546a69", + "format": 1 + }, + { + "name": "tests/integration/targets/aci_tenant/pki", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, + "format": 1 + }, + { + "name": "tests/integration/targets/aci_tenant/pki/admin_invalid.key", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "55fb85eae133a7b8649703b1d6e303cdf5b585d381e761f3674d1fcc5beb40cb", + "format": 1 + }, + { + "name": "tests/integration/targets/aci_tenant/pki/rsa_user.key", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "8a74dffaf7d04e74642988302b185f0e9eda2dd35a5b7f32317696b12a9790c1", + "format": 1 + }, + { + "name": "tests/integration/targets/aci_tenant/pki/admin.crt", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "f97928b2cd1ce43cfe9ae9bbf47a40b858a749c4c3f25a7ec02898611f4fee90", + "format": 1 + }, + { + "name": "tests/integration/targets/aci_tenant/pki/openssh_rsa.key", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "81a6ac3a61f2df64339252db67fea1307e891c41232e2da53a1e5219f677c917", + "format": 1 + }, + { + "name": "tests/integration/targets/aci_tenant/pki/admin.key", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "947c1b5a6c419641d4b2c8492b91f2d71588958666aeceeffb1f878460b1d256", + "format": 1 + }, + { + "name": "tests/integration/targets/aci_tenant/pki/rsa_user.crt", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "77629e6b31c8c9fad7052f4696dcead786fecef66e33e81c50ce09fcb39d8b4a", + "format": 1 + }, + { + "name": "tests/integration/targets/aci_tenant/pki/rsa_ansible.key", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "6945fcb844179106a63be7e8ea5b407f31a8a1e95a1eaa0b5e67da1c26802032", + "format": 1 + }, + { + "name": "tests/integration/targets/aci_maintenance_group_node", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, + "format": 1 + }, + { + "name": "tests/integration/targets/aci_maintenance_group_node/tasks", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, + "format": 1 + }, + { + "name": "tests/integration/targets/aci_maintenance_group_node/tasks/main.yml", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "6c2130d1314c7e5258b0c06ae27a187d652eb0aa01a363ed46bb88180ce981d0", + "format": 1 + }, + { + "name": "tests/integration/targets/aci_maintenance_group_node/aliases", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "616f27a9a7bb49e561ef3782330e18d1a8cea3840e3166e798796684dd546a69", + "format": 1 + }, + { + "name": "tests/integration/targets/aci_l3out_floating_svi_secondary_ip", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, + "format": 1 + }, + { + "name": "tests/integration/targets/aci_l3out_floating_svi_secondary_ip/tasks", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, + "format": 1 + }, + { + "name": "tests/integration/targets/aci_l3out_floating_svi_secondary_ip/tasks/main.yml", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "073b1706685542287c18a0c471677deaf3b9e3dfccfec7904e09dfdce33fafe2", + "format": 1 + }, + { + "name": "tests/integration/targets/aci_l3out_floating_svi_secondary_ip/aliases", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "616f27a9a7bb49e561ef3782330e18d1a8cea3840e3166e798796684dd546a69", + "format": 1 + }, + { + "name": "tests/integration/targets/aci_syslog_group", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, + "format": 1 + }, + { + "name": "tests/integration/targets/aci_syslog_group/tasks", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, + "format": 1 + }, + { + "name": "tests/integration/targets/aci_syslog_group/tasks/main.yml", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "6c8d18b7d1b934e886e32960bab072793cb8c9fb411a974b322940bdb47ec526", + "format": 1 + }, + { + "name": "tests/integration/targets/aci_syslog_group/aliases", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "616f27a9a7bb49e561ef3782330e18d1a8cea3840e3166e798796684dd546a69", + "format": 1 + }, + { + "name": "tests/integration/targets/aci_vrf_multicast", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, + "format": 1 + }, + { + "name": "tests/integration/targets/aci_vrf_multicast/tasks", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, + "format": 1 + }, + { + "name": "tests/integration/targets/aci_vrf_multicast/tasks/main.yml", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "c258a4ad5bac870a51363670ef44d922f17e3bc8f88571356799581a4b449bd6", + "format": 1 + }, + { + "name": "tests/integration/targets/aci_vrf_multicast/aliases", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "616f27a9a7bb49e561ef3782330e18d1a8cea3840e3166e798796684dd546a69", + "format": 1 + }, + { + "name": "tests/integration/targets/aci_route_control_profile", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, + "format": 1 + }, + { + "name": "tests/integration/targets/aci_route_control_profile/tasks", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, + "format": 1 + }, + { + "name": "tests/integration/targets/aci_route_control_profile/tasks/main.yml", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "4a9deefee3a9c978912c3fed74ab40f13a922f5b409c7ffc5c8cdca6468a488f", + "format": 1 + }, + { + "name": "tests/integration/targets/aci_route_control_profile/aliases", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "616f27a9a7bb49e561ef3782330e18d1a8cea3840e3166e798796684dd546a69", + "format": 1 + }, + { + "name": "tests/integration/targets/aci_snmp_client", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, + "format": 1 + }, + { + "name": "tests/integration/targets/aci_snmp_client/tasks", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, + "format": 1 + }, + { + "name": "tests/integration/targets/aci_snmp_client/tasks/main.yml", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "8319763fc884a440954ec4ccebe9ee9250e6273ea234f8fb664d8886cc2b74e7", + "format": 1 + }, + { + "name": "tests/integration/targets/aci_snmp_client/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": "2b7837cc64a41aee8dc2ec18b18dee00bca0a01508cc459c420554f4351744a6", + "format": 1 + }, + { + "name": "tests/integration/targets/aci_aep/aliases", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "616f27a9a7bb49e561ef3782330e18d1a8cea3840e3166e798796684dd546a69", + "format": 1 + }, + { + "name": "tests/integration/targets/aci_l3out_logical_interface_profile", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, + "format": 1 + }, + { + "name": "tests/integration/targets/aci_l3out_logical_interface_profile/tasks", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, @@ -4176,2916 +5597,3812 @@ "name": "tests/integration/targets/aci_l3out_logical_interface_profile/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "5a87867498dd6a864410a35eb31e8d8db264675bf15a3935f583efa16f563b56", + "chksum_sha256": "2a25546b4e0f4e0d6fd51a29e2f410c19503f531263681cfcd2e00f72bedca4a", + "format": 1 + }, + { + "name": "tests/integration/targets/aci_l3out_logical_interface_profile/aliases", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "616f27a9a7bb49e561ef3782330e18d1a8cea3840e3166e798796684dd546a69", + "format": 1 + }, + { + "name": "tests/integration/targets/aci_qos_dscp_class", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, + "format": 1 + }, + { + "name": "tests/integration/targets/aci_qos_dscp_class/tasks", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, + "format": 1 + }, + { + "name": "tests/integration/targets/aci_qos_dscp_class/tasks/main.yml", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "3cfe7421f7078e9e86be3cddeb6208d86143879fac9600252cfd2046ab643df3", + "format": 1 + }, + { + "name": "tests/integration/targets/aci_qos_dscp_class/aliases", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "616f27a9a7bb49e561ef3782330e18d1a8cea3840e3166e798796684dd546a69", + "format": 1 + }, + { + "name": "tests/integration/targets/aci_key_policy", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, + "format": 1 + }, + { + "name": "tests/integration/targets/aci_key_policy/tasks", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, + "format": 1 + }, + { + "name": "tests/integration/targets/aci_key_policy/tasks/main.yml", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "c33960701dd547ddb2b87f3e29c441eb080f99cbf1b4594a8631c06b24f0cab5", + "format": 1 + }, + { + "name": "tests/integration/targets/aci_key_policy/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": "2e4dfc8c97a7056dd048fe03ac4f32e085b6660d1cfe5a6d8c02a72742824a84", + "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_interface_policy_storm_control", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, + "format": 1 + }, + { + "name": "tests/integration/targets/aci_interface_policy_storm_control/tasks", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, + "format": 1 + }, + { + "name": "tests/integration/targets/aci_interface_policy_storm_control/tasks/main.yml", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "d8ba82d7c2ebfc91a4d467faf3e26e54f15bea00a562fe91216b0cea1b12804f", + "format": 1 + }, + { + "name": "tests/integration/targets/aci_interface_policy_storm_control/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": "23e36fefcac51193152a60816eef04e25f51414c89ee8e0a777e5021b8811295", + "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": "a5b42d2c95354d21b03b1c93d0ca9ae8420ab88925e83fa5e41de036bdc42360", + "format": 1 + }, + { + "name": "tests/integration/targets/aci_l2out/aliases", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "616f27a9a7bb49e561ef3782330e18d1a8cea3840e3166e798796684dd546a69", + "format": 1 + }, + { + "name": "tests/integration/targets/aci_access_spine_switch_profile", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, + "format": 1 + }, + { + "name": "tests/integration/targets/aci_access_spine_switch_profile/tasks", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, + "format": 1 + }, + { + "name": "tests/integration/targets/aci_access_spine_switch_profile/tasks/main.yml", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "190c8a814cf28931d1fa51f1a522a54ff25768311f41e344ff9fee69594f1261", + "format": 1 + }, + { + "name": "tests/integration/targets/aci_access_spine_switch_profile/aliases", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "616f27a9a7bb49e561ef3782330e18d1a8cea3840e3166e798796684dd546a69", + "format": 1 + }, + { + "name": "tests/integration/targets/aci_fabric_management_access", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, + "format": 1 + }, + { + "name": "tests/integration/targets/aci_fabric_management_access/tasks", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, + "format": 1 + }, + { + "name": "tests/integration/targets/aci_fabric_management_access/tasks/main.yml", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "c6c6776f7831d40b5522ac88a481d61c38c7f5a323d9f80f762847f0601c729e", + "format": 1 + }, + { + "name": "tests/integration/targets/aci_fabric_management_access/aliases", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "616f27a9a7bb49e561ef3782330e18d1a8cea3840e3166e798796684dd546a69", + "format": 1 + }, + { + "name": "tests/integration/targets/aci_fabric_management_access/pki", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, + "format": 1 + }, + { + "name": "tests/integration/targets/aci_fabric_management_access/pki/admin.crt", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "f97928b2cd1ce43cfe9ae9bbf47a40b858a749c4c3f25a7ec02898611f4fee90", + "format": 1 + }, + { + "name": "tests/integration/targets/aci_fabric_management_access/pki/admin.key", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "947c1b5a6c419641d4b2c8492b91f2d71588958666aeceeffb1f878460b1d256", + "format": 1 + }, + { + "name": "tests/integration/targets/aci_interface_policy_port_channel", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, + "format": 1 + }, + { + "name": "tests/integration/targets/aci_interface_policy_port_channel/tasks", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, + "format": 1 + }, + { + "name": "tests/integration/targets/aci_interface_policy_port_channel/tasks/main.yml", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "5d15555a235b9bce54b5a236b904fd2abc03d7c77a5676a78b133701747294a3", + "format": 1 + }, + { + "name": "tests/integration/targets/aci_interface_policy_port_channel/aliases", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "616f27a9a7bb49e561ef3782330e18d1a8cea3840e3166e798796684dd546a69", + "format": 1 + }, + { + "name": "tests/integration/targets/aci_match_community_regex_term", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, + "format": 1 + }, + { + "name": "tests/integration/targets/aci_match_community_regex_term/tasks", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, + "format": 1 + }, + { + "name": "tests/integration/targets/aci_match_community_regex_term/tasks/main.yml", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "816f883819fca9605b5d08fbec656564a659d6dae12519f744a1f38e1733ab1f", + "format": 1 + }, + { + "name": "tests/integration/targets/aci_match_community_regex_term/aliases", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "616f27a9a7bb49e561ef3782330e18d1a8cea3840e3166e798796684dd546a69", + "format": 1 + }, + { + "name": "tests/integration/targets/aci_snmp_policy", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, + "format": 1 + }, + { + "name": "tests/integration/targets/aci_snmp_policy/tasks", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, + "format": 1 + }, + { + "name": "tests/integration/targets/aci_snmp_policy/tasks/main.yml", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "924e49b0662472fe0e67ab72404819c5e00523f51b37715f28a805cce6b2a850", + "format": 1 + }, + { + "name": "tests/integration/targets/aci_snmp_policy/aliases", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "616f27a9a7bb49e561ef3782330e18d1a8cea3840e3166e798796684dd546a69", + "format": 1 + }, + { + "name": "tests/integration/targets/aci_fabric_pod_policy_group", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, + "format": 1 + }, + { + "name": "tests/integration/targets/aci_fabric_pod_policy_group/tasks", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, + "format": 1 + }, + { + "name": "tests/integration/targets/aci_fabric_pod_policy_group/tasks/main.yml", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "a34f5d541f3fa84f488c3fae897cffd7e1352728a4807fa86557cd326e4d8a7f", + "format": 1 + }, + { + "name": "tests/integration/targets/aci_fabric_pod_policy_group/aliases", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "616f27a9a7bb49e561ef3782330e18d1a8cea3840e3166e798796684dd546a69", + "format": 1 + }, + { + "name": "tests/integration/targets/aci_ntp_policy", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, + "format": 1 + }, + { + "name": "tests/integration/targets/aci_ntp_policy/tasks", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, + "format": 1 + }, + { + "name": "tests/integration/targets/aci_ntp_policy/tasks/main.yml", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "f120f96885c5c81468280e9eb51a4d2b03ece33638eb1f42519861aba2218383", + "format": 1 + }, + { + "name": "tests/integration/targets/aci_ntp_policy/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": "6aabcd7a0fa4ef86f4b4c5c68364d8a30e707f34a42e97ead2a2de68d10beb45", + "format": 1 + }, + { + "name": "tests/integration/targets/aci_domain/tasks/l2dom.yml", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "29ec89ad1eba9d7ffafe36e5488d2a4533ad529cfa813093416fedd3826dd06a", + "format": 1 + }, + { + "name": "tests/integration/targets/aci_domain/tasks/fc.yml", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "e8c8bc20d452d9b3209ac08186558f5dece49357afe9a609734aebae7f2e1fe7", + "format": 1 + }, + { + "name": "tests/integration/targets/aci_domain/tasks/phys.yml", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "adf84c74f9c21856cf21f498b7c905652911b00c7016733b2b49f4a13ff93a15", + "format": 1 + }, + { + "name": "tests/integration/targets/aci_domain/tasks/main.yml", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "38a72f6c96f2b5bd47da5764a219da47054b0814d0944001539679311a9d3758", + "format": 1 + }, + { + "name": "tests/integration/targets/aci_domain/tasks/l3dom.yml", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "567c158639220dfb536539f8f2175fd0c2af80036285c5e9bd31a9c6ad2530e9", + "format": 1 + }, + { + "name": "tests/integration/targets/aci_domain/aliases", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "616f27a9a7bb49e561ef3782330e18d1a8cea3840e3166e798796684dd546a69", + "format": 1 + }, + { + "name": "tests/integration/targets/aci_l3out_to_sr_mpls_infra_l3out", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, + "format": 1 + }, + { + "name": "tests/integration/targets/aci_l3out_to_sr_mpls_infra_l3out/tasks", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, + "format": 1 + }, + { + "name": "tests/integration/targets/aci_l3out_to_sr_mpls_infra_l3out/tasks/main.yml", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "5b0ae646f216ff9c163d4fad30f2c4fef221738b8f9b12946dda962ae7b8d44f", + "format": 1 + }, + { + "name": "tests/integration/targets/aci_l3out_to_sr_mpls_infra_l3out/aliases", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "616f27a9a7bb49e561ef3782330e18d1a8cea3840e3166e798796684dd546a69", + "format": 1 + }, + { + "name": "tests/integration/targets/aci_l2out_logical_interface_path", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, + "format": 1 + }, + { + "name": "tests/integration/targets/aci_l2out_logical_interface_path/tasks", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, + "format": 1 + }, + { + "name": "tests/integration/targets/aci_l2out_logical_interface_path/tasks/main.yml", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "d6c73e292a940421447e8428d9f80684516667ea75a511d3f1556487cd266fb6", + "format": 1 + }, + { + "name": "tests/integration/targets/aci_l2out_logical_interface_path/aliases", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "616f27a9a7bb49e561ef3782330e18d1a8cea3840e3166e798796684dd546a69", + "format": 1 + }, + { + "name": "tests/integration/targets/aci_l2out_logical_interface_profile", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, + "format": 1 + }, + { + "name": "tests/integration/targets/aci_l2out_logical_interface_profile/tasks", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, + "format": 1 + }, + { + "name": "tests/integration/targets/aci_l2out_logical_interface_profile/tasks/main.yml", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "2cc00f299f8ea22792ca39143101fd8e7bed11cb289d6fc0efdd352100872b8b", + "format": 1 + }, + { + "name": "tests/integration/targets/aci_l2out_logical_interface_profile/aliases", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "616f27a9a7bb49e561ef3782330e18d1a8cea3840e3166e798796684dd546a69", + "format": 1 + }, + { + "name": "tests/integration/targets/aci_l3out_extepg", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, + "format": 1 + }, + { + "name": "tests/integration/targets/aci_l3out_extepg/tasks", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, + "format": 1 + }, + { + "name": "tests/integration/targets/aci_l3out_extepg/tasks/main.yml", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "c836365750e7a249888a36db8674bb739727dc37aec16cdfd25f55d0a90e916e", + "format": 1 + }, + { + "name": "tests/integration/targets/aci_l3out_extepg/aliases", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "616f27a9a7bb49e561ef3782330e18d1a8cea3840e3166e798796684dd546a69", + "format": 1 + }, + { + "name": "tests/integration/targets/aci_aaa_custom_privilege", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, + "format": 1 + }, + { + "name": "tests/integration/targets/aci_aaa_custom_privilege/tasks", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, + "format": 1 + }, + { + "name": "tests/integration/targets/aci_aaa_custom_privilege/tasks/main.yml", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "9baf4665c6e36079e351b72403afb38fd7cd55b82d6a8d421be615bfbcede9e1", + "format": 1 + }, + { + "name": "tests/integration/targets/aci_aaa_custom_privilege/aliases", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "616f27a9a7bb49e561ef3782330e18d1a8cea3840e3166e798796684dd546a69", + "format": 1 + }, + { + "name": "tests/integration/targets/aci_fabric_scheduler", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, + "format": 1 + }, + { + "name": "tests/integration/targets/aci_fabric_scheduler/tasks", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, + "format": 1 + }, + { + "name": "tests/integration/targets/aci_fabric_scheduler/tasks/main.yml", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "dbb8e5f043a9f5dee464af5ac5dabab28801bf0b87845d2923b988925dbea1fd", + "format": 1 + }, + { + "name": "tests/integration/targets/aci_fabric_scheduler/aliases", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "616f27a9a7bb49e561ef3782330e18d1a8cea3840e3166e798796684dd546a69", + "format": 1 + }, + { + "name": "tests/integration/targets/aci_fabric_span_src_group", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, + "format": 1 + }, + { + "name": "tests/integration/targets/aci_fabric_span_src_group/tasks", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, + "format": 1 + }, + { + "name": "tests/integration/targets/aci_fabric_span_src_group/tasks/main.yml", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "1349d691b2fe6da11dd0a944676e957265253af30d5c87af537934ed86b5a770", + "format": 1 + }, + { + "name": "tests/integration/targets/aci_fabric_span_src_group/aliases", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "616f27a9a7bb49e561ef3782330e18d1a8cea3840e3166e798796684dd546a69", + "format": 1 + }, + { + "name": "tests/integration/targets/aci_firmware_group", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, + "format": 1 + }, + { + "name": "tests/integration/targets/aci_firmware_group/tasks", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, + "format": 1 + }, + { + "name": "tests/integration/targets/aci_firmware_group/tasks/main.yml", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "baff773fe422ff7682c90ffc9464dcab4d4cbd96fc264934a9b9fac31efaa425", + "format": 1 + }, + { + "name": "tests/integration/targets/aci_firmware_group/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": "b4c20198391e11c0ea0b8bdea508d71f9f947ed99bb6c920b29aa8eb1e99a07d", + "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": "fffdbacbdff26e734a2a5e76421e7190bc469d5d30e4fa5faacf788dd51647f7", + "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_bd_to_l3out", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, + "format": 1 + }, + { + "name": "tests/integration/targets/aci_bd_to_l3out/tasks", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, + "format": 1 + }, + { + "name": "tests/integration/targets/aci_bd_to_l3out/tasks/main.yml", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "5ec695e014db0f6c557988a54ce858da4e8bf30cbce5b8bafe3888ff3046fe4f", "format": 1 }, { - "name": "tests/integration/targets/aci_l3out_logical_interface_profile/aliases", + "name": "tests/integration/targets/aci_bd_to_l3out/aliases", "ftype": "file", "chksum_type": "sha256", "chksum_sha256": "616f27a9a7bb49e561ef3782330e18d1a8cea3840e3166e798796684dd546a69", "format": 1 }, { - "name": "tests/integration/targets/aci_interface_policy_link_level", + "name": "tests/integration/targets/aci_aaa_key_ring", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/aci_interface_policy_link_level/tasks", + "name": "tests/integration/targets/aci_aaa_key_ring/tasks", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/aci_interface_policy_link_level/tasks/main.yml", + "name": "tests/integration/targets/aci_aaa_key_ring/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "760f5c21dc389db02d3e809c5761fa869934dfd6867fbbcdf11fcbe511a9c931", + "chksum_sha256": "96483c17928f4da918cea3324f23ecb083eaf820af2d4c0748e334ed42340c93", "format": 1 }, { - "name": "tests/integration/targets/aci_interface_policy_link_level/aliases", + "name": "tests/integration/targets/aci_aaa_key_ring/aliases", "ftype": "file", "chksum_type": "sha256", "chksum_sha256": "616f27a9a7bb49e561ef3782330e18d1a8cea3840e3166e798796684dd546a69", "format": 1 }, { - "name": "tests/integration/targets/aci_l3out_extsubnet", + "name": "tests/integration/targets/aci_aaa_key_ring/pki", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/aci_l3out_extsubnet/tasks", + "name": "tests/integration/targets/aci_aaa_key_ring/pki/admin.crt", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "f97928b2cd1ce43cfe9ae9bbf47a40b858a749c4c3f25a7ec02898611f4fee90", + "format": 1 + }, + { + "name": "tests/integration/targets/aci_aaa_key_ring/pki/admin.key", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "947c1b5a6c419641d4b2c8492b91f2d71588958666aeceeffb1f878460b1d256", + "format": 1 + }, + { + "name": "tests/integration/targets/aci_fabric_span_dst_group", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/aci_l3out_extsubnet/tasks/main.yml", + "name": "tests/integration/targets/aci_fabric_span_dst_group/tasks", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, + "format": 1 + }, + { + "name": "tests/integration/targets/aci_fabric_span_dst_group/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "ff51702c2b61e04d0852925417f2632ca2ad77476c87fbc3e3bf26e841fb9b40", + "chksum_sha256": "01015ad80e8bffebdc43dbbe5c3d7dea2a8d3e72a443f1b40b322048d1640608", "format": 1 }, { - "name": "tests/integration/targets/aci_l3out_extsubnet/aliases", + "name": "tests/integration/targets/aci_fabric_span_dst_group/aliases", "ftype": "file", "chksum_type": "sha256", "chksum_sha256": "616f27a9a7bb49e561ef3782330e18d1a8cea3840e3166e798796684dd546a69", "format": 1 }, { - "name": "tests/integration/targets/aci_l2out", + "name": "tests/integration/targets/aci_bgp_best_path_policy", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/aci_l2out/tasks", + "name": "tests/integration/targets/aci_bgp_best_path_policy/tasks", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/aci_l2out/tasks/main.yml", + "name": "tests/integration/targets/aci_bgp_best_path_policy/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "ac1d2a1e71906e0bcf422d680dd720508431daae4c1717c57834105e79a3aef4", + "chksum_sha256": "4869d34c6a9ec2f31b1a9e2992fd0c7ff2db1b05fe820e47be8a7f51bb3e574c", "format": 1 }, { - "name": "tests/integration/targets/aci_l2out/aliases", + "name": "tests/integration/targets/aci_bgp_best_path_policy/aliases", "ftype": "file", "chksum_type": "sha256", "chksum_sha256": "616f27a9a7bb49e561ef3782330e18d1a8cea3840e3166e798796684dd546a69", "format": 1 }, { - "name": "tests/integration/targets/aci_interface_policy_port_channel", + "name": "tests/integration/targets/aci_fabric_node", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/aci_interface_policy_port_channel/tasks", + "name": "tests/integration/targets/aci_fabric_node/tasks", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/aci_interface_policy_port_channel/tasks/main.yml", + "name": "tests/integration/targets/aci_fabric_node/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "dd6ca5c9bc1c622ad186c3081434eb5d82f61d82e756e9a7731fbe39a85a1c26", + "chksum_sha256": "312722a6556b1633da341e02bb311cda8fdd4774085b2bb886dc7ed892cd80fc", "format": 1 }, { - "name": "tests/integration/targets/aci_interface_policy_port_channel/aliases", + "name": "tests/integration/targets/aci_fabric_node/aliases", "ftype": "file", "chksum_type": "sha256", "chksum_sha256": "616f27a9a7bb49e561ef3782330e18d1a8cea3840e3166e798796684dd546a69", "format": 1 }, { - "name": "tests/integration/targets/aci_match_community_regex_term", + "name": "tests/integration/targets/aci_epg_useg_attribute_block_statement", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/aci_match_community_regex_term/tasks", + "name": "tests/integration/targets/aci_epg_useg_attribute_block_statement/tasks", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/aci_match_community_regex_term/tasks/main.yml", + "name": "tests/integration/targets/aci_epg_useg_attribute_block_statement/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "a317a7798696e01a0bbcea910360a73b59f03c9fcf0946a8f0e1566daaa222cb", + "chksum_sha256": "1b3e8a671dda2ec261dbc4084d65ff05654f61c79970a944fdf2f4760a312860", "format": 1 }, { - "name": "tests/integration/targets/aci_match_community_regex_term/aliases", + "name": "tests/integration/targets/aci_epg_useg_attribute_block_statement/aliases", "ftype": "file", "chksum_type": "sha256", "chksum_sha256": "616f27a9a7bb49e561ef3782330e18d1a8cea3840e3166e798796684dd546a69", "format": 1 }, { - "name": "tests/integration/targets/aci_snmp_policy", + "name": "tests/integration/targets/aci_aep_to_domain", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/aci_snmp_policy/tasks", + "name": "tests/integration/targets/aci_aep_to_domain/tasks", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/aci_snmp_policy/tasks/main.yml", + "name": "tests/integration/targets/aci_aep_to_domain/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "14124ae8544f77657abd5db831e7226aaf9b752363d4751ba05943ca8fc9c1ec", + "chksum_sha256": "ef617648cf3b092fa334cb5b9a1cab0ed9b086b86598304306e33ec576ac0664", "format": 1 }, { - "name": "tests/integration/targets/aci_snmp_policy/aliases", + "name": "tests/integration/targets/aci_aep_to_domain/aliases", "ftype": "file", "chksum_type": "sha256", "chksum_sha256": "616f27a9a7bb49e561ef3782330e18d1a8cea3840e3166e798796684dd546a69", "format": 1 }, { - "name": "tests/integration/targets/aci_fabric_pod_policy_group", + "name": "tests/integration/targets/aci_dns_domain", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/aci_fabric_pod_policy_group/tasks", + "name": "tests/integration/targets/aci_dns_domain/tasks", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/aci_fabric_pod_policy_group/tasks/main.yml", + "name": "tests/integration/targets/aci_dns_domain/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "bb70c203bf4447030ac385ca1f63408f7cb2bba098a457badaa46ad73907101d", + "chksum_sha256": "d7d7eab519cd4192a61605b934bb4c813872671117802804effd3732fd11531a", "format": 1 }, { - "name": "tests/integration/targets/aci_fabric_pod_policy_group/aliases", + "name": "tests/integration/targets/aci_dns_domain/aliases", "ftype": "file", "chksum_type": "sha256", "chksum_sha256": "616f27a9a7bb49e561ef3782330e18d1a8cea3840e3166e798796684dd546a69", "format": 1 }, { - "name": "tests/integration/targets/aci_ntp_policy", + "name": "tests/integration/targets/aci_encap_pool_range", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/aci_ntp_policy/tasks", + "name": "tests/integration/targets/aci_encap_pool_range/tasks", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/aci_ntp_policy/tasks/main.yml", + "name": "tests/integration/targets/aci_encap_pool_range/tasks/vsan.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "b7c1c21fd27b102bebe4468763f63901b5c66ba04ebbd3dd1fc4f030ab2a46d8", + "chksum_sha256": "33a77d78e48ca5615f806248beefe920ac99a7c43ed1f19e96c0660381a23b9d", "format": 1 }, { - "name": "tests/integration/targets/aci_ntp_policy/aliases", + "name": "tests/integration/targets/aci_encap_pool_range/tasks/vlan.yml", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "194dffc2cabbf408c5039de01f0f01f0b5419538e6fde4b3d3e564d42ec8e5dd", + "format": 1 + }, + { + "name": "tests/integration/targets/aci_encap_pool_range/tasks/vxlan.yml", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "13773b8b2e1ae5d22eb4c2919c3b14bc2192b0876e4bc2dca286b40b8486b88a", + "format": 1 + }, + { + "name": "tests/integration/targets/aci_encap_pool_range/tasks/main.yml", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "0018ba019fdc1fbff1df694d0a1e190b58b73682a8c63c93ac5143d0e2018f48", + "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_domain", + "name": "tests/integration/targets/aci_aep_to_epg", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/aci_domain/tasks", + "name": "tests/integration/targets/aci_aep_to_epg/tasks", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/aci_domain/tasks/vmm-vmware.yml", + "name": "tests/integration/targets/aci_aep_to_epg/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "068ef4d1d8671df9f8ba54f51483cb29a08a42adcd5227ae345b0c87bce5e5b8", + "chksum_sha256": "da9bc3dc1d400e410025b424cd743b07e0cb4626de5372b2d495ddc702e1631d", "format": 1 }, { - "name": "tests/integration/targets/aci_domain/tasks/l2dom.yml", + "name": "tests/integration/targets/aci_aep_to_epg/aliases", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "04dbec0678323daf3a87d3170ff98a41a8d38a5db26e8772f7d36e406a9d4483", + "chksum_sha256": "616f27a9a7bb49e561ef3782330e18d1a8cea3840e3166e798796684dd546a69", "format": 1 }, { - "name": "tests/integration/targets/aci_domain/tasks/fc.yml", + "name": "tests/integration/targets/aci_contract_export", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, + "format": 1 + }, + { + "name": "tests/integration/targets/aci_contract_export/tasks", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, + "format": 1 + }, + { + "name": "tests/integration/targets/aci_contract_export/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "c04c71cae5fcd512f2e5203c57129582bf1f0b55c74a9dcd4c57dcdc8856fc7a", + "chksum_sha256": "9218e7b208662c098c4ebae5c850aa48872bb16daeed28d1d18895c8df68049f", "format": 1 }, { - "name": "tests/integration/targets/aci_domain/tasks/phys.yml", + "name": "tests/integration/targets/aci_contract_export/aliases", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "36fae3df4197ffba49ff83256a05c2c952247e974a052c94d3882dc693cdc80a", + "chksum_sha256": "616f27a9a7bb49e561ef3782330e18d1a8cea3840e3166e798796684dd546a69", "format": 1 }, { - "name": "tests/integration/targets/aci_domain/tasks/main.yml", + "name": "tests/integration/targets/aci_dhcp_option", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, + "format": 1 + }, + { + "name": "tests/integration/targets/aci_dhcp_option/tasks", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, + "format": 1 + }, + { + "name": "tests/integration/targets/aci_dhcp_option/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "8094a133d927bf97b43ccdc714c7b8b962af676a11e616f205f21e605f27f1e9", + "chksum_sha256": "58c3b602a17925f8950bcda6c8244d12af1a72ddce3dd5f61b83ae32c4093994", "format": 1 }, { - "name": "tests/integration/targets/aci_domain/tasks/l3dom.yml", + "name": "tests/integration/targets/aci_dhcp_option/aliases", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "28068851b310e83f51c3d025c5cddf8fb4acc6466ed5873cfa47279140d655d5", + "chksum_sha256": "616f27a9a7bb49e561ef3782330e18d1a8cea3840e3166e798796684dd546a69", "format": 1 }, { - "name": "tests/integration/targets/aci_domain/aliases", + "name": "tests/integration/targets/aci_tenant_ep_retention_policy", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, + "format": 1 + }, + { + "name": "tests/integration/targets/aci_tenant_ep_retention_policy/tasks", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, + "format": 1 + }, + { + "name": "tests/integration/targets/aci_tenant_ep_retention_policy/tasks/main.yml", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "0e296f21257f52e78b0a77f0b832de6ebf7dadcaadc78c66d7ca322e146b286d", + "format": 1 + }, + { + "name": "tests/integration/targets/aci_tenant_ep_retention_policy/aliases", "ftype": "file", "chksum_type": "sha256", "chksum_sha256": "616f27a9a7bb49e561ef3782330e18d1a8cea3840e3166e798796684dd546a69", "format": 1 }, { - "name": "tests/integration/targets/aci_l2out_logical_interface_path", + "name": "tests/integration/targets/aci_interface_policy_ospf", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/aci_l2out_logical_interface_path/tasks", + "name": "tests/integration/targets/aci_interface_policy_ospf/tasks", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/aci_l2out_logical_interface_path/tasks/main.yml", + "name": "tests/integration/targets/aci_interface_policy_ospf/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "1165e2174890eb8cb16b1404bb45f4e8f5d8ef28cf70e482ef1ff2406644a38c", + "chksum_sha256": "27505847c69378b6d211c17fdee3a50f1057277c4eff07938949b3a264eadac3", "format": 1 }, { - "name": "tests/integration/targets/aci_l2out_logical_interface_path/aliases", + "name": "tests/integration/targets/aci_interface_policy_ospf/aliases", "ftype": "file", "chksum_type": "sha256", "chksum_sha256": "616f27a9a7bb49e561ef3782330e18d1a8cea3840e3166e798796684dd546a69", "format": 1 }, { - "name": "tests/integration/targets/aci_l2out_logical_interface_profile", + "name": "tests/integration/targets/aci_fabric_pod_profile", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/aci_l2out_logical_interface_profile/tasks", + "name": "tests/integration/targets/aci_fabric_pod_profile/tasks", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/aci_l2out_logical_interface_profile/tasks/main.yml", + "name": "tests/integration/targets/aci_fabric_pod_profile/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "b14eacd51921ac498aaff06bce4e881310cbcdbd8498f3b89a493ce4c9a198e1", + "chksum_sha256": "23809735df7d7fe9bba12a715c73f150afca71eb6ed0f0eb7de21d90734eef1f", "format": 1 }, { - "name": "tests/integration/targets/aci_l2out_logical_interface_profile/aliases", + "name": "tests/integration/targets/aci_fabric_pod_profile/aliases", "ftype": "file", "chksum_type": "sha256", "chksum_sha256": "616f27a9a7bb49e561ef3782330e18d1a8cea3840e3166e798796684dd546a69", "format": 1 }, { - "name": "tests/integration/targets/aci_l3out_extepg", + "name": "tests/integration/targets/aci_tenant_span_src_group_to_dst_group", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/aci_l3out_extepg/tasks", + "name": "tests/integration/targets/aci_tenant_span_src_group_to_dst_group/tasks", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/aci_l3out_extepg/tasks/main.yml", + "name": "tests/integration/targets/aci_tenant_span_src_group_to_dst_group/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "e3cc46789ecac2e9636478d437fac86b9006cc9f2ed504961fe2f0e110e1c69d", + "chksum_sha256": "0f3e66721b1b44eec6526d09c3b4eac25012d866b3b91876d96c8bdf17314e38", "format": 1 }, { - "name": "tests/integration/targets/aci_l3out_extepg/aliases", + "name": "tests/integration/targets/aci_tenant_span_src_group_to_dst_group/aliases", "ftype": "file", "chksum_type": "sha256", "chksum_sha256": "616f27a9a7bb49e561ef3782330e18d1a8cea3840e3166e798796684dd546a69", "format": 1 }, { - "name": "tests/integration/targets/aci_aaa_custom_privilege", + "name": "tests/integration/targets/aci_qos_dot1p_class", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/aci_aaa_custom_privilege/tasks", + "name": "tests/integration/targets/aci_qos_dot1p_class/tasks", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/aci_aaa_custom_privilege/tasks/main.yml", + "name": "tests/integration/targets/aci_qos_dot1p_class/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "87e9446b4626d0ef82702c19eae28f33bac7ec595b4bea916317b7938ef1964f", + "chksum_sha256": "d0c72b681c2d1e8907202f51dab724b455d84cf449fe3ddf8a06b12668650c9f", "format": 1 }, { - "name": "tests/integration/targets/aci_aaa_custom_privilege/aliases", + "name": "tests/integration/targets/aci_qos_dot1p_class/aliases", "ftype": "file", "chksum_type": "sha256", "chksum_sha256": "616f27a9a7bb49e561ef3782330e18d1a8cea3840e3166e798796684dd546a69", "format": 1 }, { - "name": "tests/integration/targets/aci_fabric_scheduler", + "name": "tests/integration/targets/aci_fabric_leaf_profile", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/aci_fabric_scheduler/tasks", + "name": "tests/integration/targets/aci_fabric_leaf_profile/tasks", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/aci_fabric_scheduler/tasks/main.yml", + "name": "tests/integration/targets/aci_fabric_leaf_profile/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "704b7c6e84833030f155e856359f86d7166319df9f4595a463c2662ad048218d", + "chksum_sha256": "0f6034365b07c13b284182fc8630c472055da2610e1d2b45959f4da55315acd0", "format": 1 }, { - "name": "tests/integration/targets/aci_fabric_scheduler/aliases", + "name": "tests/integration/targets/aci_fabric_leaf_profile/aliases", "ftype": "file", "chksum_type": "sha256", "chksum_sha256": "616f27a9a7bb49e561ef3782330e18d1a8cea3840e3166e798796684dd546a69", "format": 1 }, { - "name": "tests/integration/targets/aci_fabric_span_src_group", + "name": "tests/integration/targets/aci_dhcp_relay", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/aci_fabric_span_src_group/tasks", + "name": "tests/integration/targets/aci_dhcp_relay/tasks", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/aci_fabric_span_src_group/tasks/main.yml", + "name": "tests/integration/targets/aci_dhcp_relay/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "8b252a0ada511e83d47a0b183a5aa1bb06a30296081f84cb99af94e26077d70e", + "chksum_sha256": "ef953d743a99f4d89d3f095aa890c946aabc18555658b6c58dc29ebe19e8598a", "format": 1 }, { - "name": "tests/integration/targets/aci_fabric_span_src_group/aliases", + "name": "tests/integration/targets/aci_dhcp_relay/aliases", "ftype": "file", "chksum_type": "sha256", "chksum_sha256": "616f27a9a7bb49e561ef3782330e18d1a8cea3840e3166e798796684dd546a69", "format": 1 }, { - "name": "tests/integration/targets/aci_firmware_group", + "name": "tests/integration/targets/aci_esg_epg_selector", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/aci_firmware_group/tasks", + "name": "tests/integration/targets/aci_esg_epg_selector/tasks", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/aci_firmware_group/tasks/main.yml", + "name": "tests/integration/targets/aci_esg_epg_selector/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "f2fd0c9c021e33ae4d4fec5ce9ffce4128b16c2d8ca1b67595954a50f59694db", + "chksum_sha256": "e983ab11ab93391be56423cb95cc3dd5a5f15af14d643c2f5444b63d8c038a61", "format": 1 }, { - "name": "tests/integration/targets/aci_firmware_group/aliases", + "name": "tests/integration/targets/aci_esg_epg_selector/aliases", "ftype": "file", "chksum_type": "sha256", "chksum_sha256": "616f27a9a7bb49e561ef3782330e18d1a8cea3840e3166e798796684dd546a69", "format": 1 }, { - "name": "tests/integration/targets/aci_epg_to_contract", + "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": "2f68d8433cc59f8a13c5d3ac288654986ee1f988b7266667aa9d1e5166cd462b", + "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_l3out_bgp_peer", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/aci_epg_to_contract/tasks", + "name": "tests/integration/targets/aci_l3out_bgp_peer/tasks", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/aci_epg_to_contract/tasks/main.yml", + "name": "tests/integration/targets/aci_l3out_bgp_peer/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "6938a58d3e50e6dd47797f38b2d79024e680245d4fd40872b9732813c123b7d6", + "chksum_sha256": "59fe840ce233545a7a3565066949c258e4bab20372ccf9d6ccf0afc6a859c5fd", "format": 1 }, { - "name": "tests/integration/targets/aci_epg_to_contract/aliases", + "name": "tests/integration/targets/aci_l3out_bgp_peer/aliases", "ftype": "file", "chksum_type": "sha256", "chksum_sha256": "616f27a9a7bb49e561ef3782330e18d1a8cea3840e3166e798796684dd546a69", "format": 1 }, { - "name": "tests/integration/targets/aci_interface_policy_leaf_profile", + "name": "tests/integration/targets/aci_esg", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/aci_interface_policy_leaf_profile/tasks", + "name": "tests/integration/targets/aci_esg/tasks", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/aci_interface_policy_leaf_profile/tasks/main.yml", + "name": "tests/integration/targets/aci_esg/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "9b6457997e6b2e8e018cfa0bebfe2028134acfd44522c7e222a3ffb7910219e3", + "chksum_sha256": "fe8d3096f7c246f57362d15eca011da984636a020c2078c2f11e78233797fdf2", "format": 1 }, { - "name": "tests/integration/targets/aci_interface_policy_leaf_profile/aliases", + "name": "tests/integration/targets/aci_esg/aliases", "ftype": "file", "chksum_type": "sha256", "chksum_sha256": "616f27a9a7bb49e561ef3782330e18d1a8cea3840e3166e798796684dd546a69", "format": 1 }, { - "name": "tests/integration/targets/aci_bd_to_l3out", + "name": "tests/integration/targets/aci_bgp_rr_node", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/aci_bd_to_l3out/tasks", + "name": "tests/integration/targets/aci_bgp_rr_node/tasks", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/aci_bd_to_l3out/tasks/main.yml", + "name": "tests/integration/targets/aci_bgp_rr_node/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "ae0c2f1524cebfd9d304242f67006adfcf029fe89ba8376ad1f27e53305d37de", + "chksum_sha256": "67668eb013645c8804596c2e49b7da0475b0ef8387afe3fc3892b42d3694c947", "format": 1 }, { - "name": "tests/integration/targets/aci_bd_to_l3out/aliases", + "name": "tests/integration/targets/aci_bgp_rr_node/aliases", "ftype": "file", "chksum_type": "sha256", "chksum_sha256": "616f27a9a7bb49e561ef3782330e18d1a8cea3840e3166e798796684dd546a69", "format": 1 }, { - "name": "tests/integration/targets/aci_fabric_span_dst_group", + "name": "tests/integration/targets/aci_aaa_domain", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/aci_fabric_span_dst_group/tasks", + "name": "tests/integration/targets/aci_aaa_domain/tasks", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/aci_fabric_span_dst_group/tasks/main.yml", + "name": "tests/integration/targets/aci_aaa_domain/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "89f09f54b34b4070853e81358c3bfc5afcac772fec7c242cb6f4712960118340", + "chksum_sha256": "6957a06dbf27ff890df7e769895f53ab731eabe43b4d70f59d299db3be09391b", "format": 1 }, { - "name": "tests/integration/targets/aci_fabric_span_dst_group/aliases", + "name": "tests/integration/targets/aci_aaa_domain/aliases", "ftype": "file", "chksum_type": "sha256", "chksum_sha256": "616f27a9a7bb49e561ef3782330e18d1a8cea3840e3166e798796684dd546a69", "format": 1 }, { - "name": "tests/integration/targets/aci_bgp_best_path_policy", + "name": "tests/integration/targets/aci_l3out_eigrp_interface_profile", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/aci_bgp_best_path_policy/tasks", + "name": "tests/integration/targets/aci_l3out_eigrp_interface_profile/tasks", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/aci_bgp_best_path_policy/tasks/main.yml", + "name": "tests/integration/targets/aci_l3out_eigrp_interface_profile/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "bd01f327bd89e5f470bd0b9fc80e2a0246c42a9fd91de72285f6bca6aee14b85", + "chksum_sha256": "cfa446df78e06fa818f43f0e123b395d90c91dfca4b5d2953a98273ce21a9954", "format": 1 }, { - "name": "tests/integration/targets/aci_bgp_best_path_policy/aliases", + "name": "tests/integration/targets/aci_l3out_eigrp_interface_profile/aliases", "ftype": "file", "chksum_type": "sha256", "chksum_sha256": "616f27a9a7bb49e561ef3782330e18d1a8cea3840e3166e798796684dd546a69", "format": 1 }, { - "name": "tests/integration/targets/aci_fabric_node", + "name": "tests/integration/targets/aci_file_remote_path", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/aci_fabric_node/tasks", + "name": "tests/integration/targets/aci_file_remote_path/tasks", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/aci_fabric_node/tasks/main.yml", + "name": "tests/integration/targets/aci_file_remote_path/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "11155626d26d8df736b01f6b694e7724cfb3edf8a1690474e77deda7bdbc0c1f", + "chksum_sha256": "fd5329b2fe47a12cd6b500a0275628e0fa48efacddf8a7fe0b61b4ef9bf58efc", "format": 1 }, { - "name": "tests/integration/targets/aci_fabric_node/aliases", + "name": "tests/integration/targets/aci_file_remote_path/aliases", "ftype": "file", "chksum_type": "sha256", "chksum_sha256": "616f27a9a7bb49e561ef3782330e18d1a8cea3840e3166e798796684dd546a69", "format": 1 }, { - "name": "tests/integration/targets/aci_aep_to_domain", + "name": "tests/integration/targets/aci_file_remote_path/pki", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/aci_aep_to_domain/tasks", + "name": "tests/integration/targets/aci_file_remote_path/pki/rsa_ansible.key", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "6945fcb844179106a63be7e8ea5b407f31a8a1e95a1eaa0b5e67da1c26802032", + "format": 1 + }, + { + "name": "tests/integration/targets/aci_aaa_user", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/aci_aep_to_domain/tasks/main.yml", + "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": "52a218b485aa23a4981d67fbbf2c7e7dd9c344f16e5fc19904f839f1f2d22dc2", + "chksum_sha256": "e5e0db5d28a70fb4d52e137fe34fa991f737c2c12c575591544c4ecdbfb4dc04", "format": 1 }, { - "name": "tests/integration/targets/aci_aep_to_domain/aliases", + "name": "tests/integration/targets/aci_aaa_user/aliases", "ftype": "file", "chksum_type": "sha256", "chksum_sha256": "616f27a9a7bb49e561ef3782330e18d1a8cea3840e3166e798796684dd546a69", "format": 1 }, { - "name": "tests/integration/targets/aci_dns_domain", + "name": "tests/integration/targets/aci_epg_to_contract_master", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/aci_dns_domain/tasks", + "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_dns_domain/tasks/main.yml", + "name": "tests/integration/targets/aci_epg_to_contract_master/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "5942d788bbbef1eacb07ff15c38c50de8c3f2f7dc6e80edd5efebcc193c1e1c4", + "chksum_sha256": "08fb777a7d079af0d1c0eb643663d7665c95306d1446e6d78363707ac3a91113", "format": 1 }, { - "name": "tests/integration/targets/aci_dns_domain/aliases", + "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_encap_pool_range", + "name": "tests/integration/targets/aci_cloud_external_epg", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/aci_encap_pool_range/tasks", + "name": "tests/integration/targets/aci_cloud_external_epg/tasks", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/aci_encap_pool_range/tasks/vsan.yml", + "name": "tests/integration/targets/aci_cloud_external_epg/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "33a77d78e48ca5615f806248beefe920ac99a7c43ed1f19e96c0660381a23b9d", + "chksum_sha256": "da9bd98cd5fea7a9d6a76f97d9ae25672e99b41ce724772f1416c76e9d4dab82", "format": 1 }, { - "name": "tests/integration/targets/aci_encap_pool_range/tasks/vlan.yml", + "name": "tests/integration/targets/aci_cloud_external_epg/aliases", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "345dbde8c63f84017b7eb34c35f034e9743ca0f185eddd3f7949671295488150", + "chksum_sha256": "616f27a9a7bb49e561ef3782330e18d1a8cea3840e3166e798796684dd546a69", "format": 1 }, { - "name": "tests/integration/targets/aci_encap_pool_range/tasks/vxlan.yml", - "ftype": "file", - "chksum_type": "sha256", - "chksum_sha256": "13773b8b2e1ae5d22eb4c2919c3b14bc2192b0876e4bc2dca286b40b8486b88a", + "name": "tests/integration/targets/aci_keychain_policy", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/aci_encap_pool_range/tasks/main.yml", + "name": "tests/integration/targets/aci_keychain_policy/tasks", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, + "format": 1 + }, + { + "name": "tests/integration/targets/aci_keychain_policy/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "cade19307a5a902a3c840480d82e00ffd71173f3ca0ba5ba59d5c74cd8864085", + "chksum_sha256": "1b29eb0c2070e1985696d8d10e54ca601f191c9bd13e4a11f78763adf88307fb", "format": 1 }, { - "name": "tests/integration/targets/aci_encap_pool_range/aliases", + "name": "tests/integration/targets/aci_keychain_policy/aliases", "ftype": "file", "chksum_type": "sha256", "chksum_sha256": "616f27a9a7bb49e561ef3782330e18d1a8cea3840e3166e798796684dd546a69", "format": 1 }, { - "name": "tests/integration/targets/aci_aep_to_epg", + "name": "tests/integration/targets/aci_firmware_policy", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/aci_aep_to_epg/tasks", + "name": "tests/integration/targets/aci_firmware_policy/tasks", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/aci_aep_to_epg/tasks/main.yml", + "name": "tests/integration/targets/aci_firmware_policy/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "a1e627a67befe9cc0f6faa1de4d1379e5ebde380bc124e285d153a7b5e7cae74", + "chksum_sha256": "97ffa299416e48106e1431b8a80ebbea3eeed0686cd575325904e166968ca291", "format": 1 }, { - "name": "tests/integration/targets/aci_aep_to_epg/aliases", + "name": "tests/integration/targets/aci_firmware_policy/aliases", "ftype": "file", "chksum_type": "sha256", "chksum_sha256": "616f27a9a7bb49e561ef3782330e18d1a8cea3840e3166e798796684dd546a69", "format": 1 }, { - "name": "tests/integration/targets/aci_contract_export", + "name": "tests/integration/targets/aci_cloud_subnet", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/aci_contract_export/tasks", + "name": "tests/integration/targets/aci_cloud_subnet/tasks", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/aci_contract_export/tasks/main.yml", + "name": "tests/integration/targets/aci_cloud_subnet/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "194beab695bfb110bce199c3815786ae800384b41469a8dcb64bb724a5d34596", + "chksum_sha256": "f6533302e08342b9dad6391562828ecc98b02e63ee29d65b1f0e3481a74db713", "format": 1 }, { - "name": "tests/integration/targets/aci_contract_export/aliases", + "name": "tests/integration/targets/aci_cloud_subnet/aliases", "ftype": "file", "chksum_type": "sha256", "chksum_sha256": "616f27a9a7bb49e561ef3782330e18d1a8cea3840e3166e798796684dd546a69", "format": 1 }, { - "name": "tests/integration/targets/aci_tenant_ep_retention_policy", + "name": "tests/integration/targets/aci_vrf", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/aci_tenant_ep_retention_policy/tasks", + "name": "tests/integration/targets/aci_vrf/tasks", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/aci_tenant_ep_retention_policy/tasks/main.yml", + "name": "tests/integration/targets/aci_vrf/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "843240370cdf77e385f381e5046df7655f88a4eb9843237c37b1d2b7339fd25e", + "chksum_sha256": "440e5baec2b38bc0940223c14b5e9fe8d42d391263f235b2e7df366c7ad0cac2", "format": 1 }, { - "name": "tests/integration/targets/aci_tenant_ep_retention_policy/aliases", + "name": "tests/integration/targets/aci_vrf/aliases", "ftype": "file", "chksum_type": "sha256", "chksum_sha256": "616f27a9a7bb49e561ef3782330e18d1a8cea3840e3166e798796684dd546a69", "format": 1 }, { - "name": "tests/integration/targets/aci_interface_policy_ospf", + "name": "tests/integration/targets/aci_filter", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/aci_interface_policy_ospf/tasks", + "name": "tests/integration/targets/aci_filter/tasks", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/aci_interface_policy_ospf/tasks/main.yml", + "name": "tests/integration/targets/aci_filter/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "9b9ba9779d76f78bb5e11c9486b65c3153fecae854844ff74734ffff8233002b", + "chksum_sha256": "b1325b621500ac3780cc4932d57525ad50ebdabd8021eb82b2bc794a009f5fe8", "format": 1 }, { - "name": "tests/integration/targets/aci_interface_policy_ospf/aliases", + "name": "tests/integration/targets/aci_filter/aliases", "ftype": "file", "chksum_type": "sha256", "chksum_sha256": "616f27a9a7bb49e561ef3782330e18d1a8cea3840e3166e798796684dd546a69", "format": 1 }, { - "name": "tests/integration/targets/aci_tenant_span_src_group_to_dst_group", + "name": "tests/integration/targets/aci_l3out_interface", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/aci_tenant_span_src_group_to_dst_group/tasks", + "name": "tests/integration/targets/aci_l3out_interface/tasks", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/aci_tenant_span_src_group_to_dst_group/tasks/main.yml", + "name": "tests/integration/targets/aci_l3out_interface/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "74533cc1bb596adff756c3a691a9445e1f5c96655e6544426cd0e02e524207ac", + "chksum_sha256": "a1f06a4e765dd38a0c5200098f40dc8822e1017ec9522674be2cae300a4ce746", "format": 1 }, { - "name": "tests/integration/targets/aci_tenant_span_src_group_to_dst_group/aliases", + "name": "tests/integration/targets/aci_l3out_interface/aliases", "ftype": "file", "chksum_type": "sha256", "chksum_sha256": "616f27a9a7bb49e561ef3782330e18d1a8cea3840e3166e798796684dd546a69", "format": 1 }, { - "name": "tests/integration/targets/aci_fabric_leaf_profile", + "name": "tests/integration/targets/aci_tenant_span_dst_group", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/aci_fabric_leaf_profile/tasks", + "name": "tests/integration/targets/aci_tenant_span_dst_group/tasks", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/aci_fabric_leaf_profile/tasks/main.yml", + "name": "tests/integration/targets/aci_tenant_span_dst_group/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "f41af177548f2ec1a66e496a62bc8fbe1e48098e48a20efd6f4fd27572722298", + "chksum_sha256": "813febdbdf77a5cf80cae3cd76dc7ffd52b549a94870d439398c002a61d5c98e", "format": 1 }, { - "name": "tests/integration/targets/aci_fabric_leaf_profile/aliases", + "name": "tests/integration/targets/aci_tenant_span_dst_group/aliases", "ftype": "file", "chksum_type": "sha256", "chksum_sha256": "616f27a9a7bb49e561ef3782330e18d1a8cea3840e3166e798796684dd546a69", "format": 1 }, { - "name": "tests/integration/targets/aci_dhcp_relay", + "name": "tests/integration/targets/aci_l3out_logical_interface_profile_ospf_policy", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/aci_dhcp_relay/tasks", + "name": "tests/integration/targets/aci_l3out_logical_interface_profile_ospf_policy/tasks", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/aci_dhcp_relay/tasks/main.yml", + "name": "tests/integration/targets/aci_l3out_logical_interface_profile_ospf_policy/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "773df8a3cfbfbaf68a2c5de6619e9bf1ce6026d7f45b2e45c0025c4dd9ad6d1f", + "chksum_sha256": "9ed24f55a9eab4d00c8ac950a45c0fe36425fcaa041f346087f91565c787b7d4", "format": 1 }, { - "name": "tests/integration/targets/aci_dhcp_relay/aliases", + "name": "tests/integration/targets/aci_l3out_logical_interface_profile_ospf_policy/aliases", "ftype": "file", "chksum_type": "sha256", "chksum_sha256": "616f27a9a7bb49e561ef3782330e18d1a8cea3840e3166e798796684dd546a69", "format": 1 }, { - "name": "tests/integration/targets/aci_esg_epg_selector", + "name": "tests/integration/targets/aci_epg", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/aci_esg_epg_selector/tasks", + "name": "tests/integration/targets/aci_epg/tasks", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/aci_esg_epg_selector/tasks/main.yml", + "name": "tests/integration/targets/aci_epg/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "37aaf2c1c23852f9bcf49957b45617ba513ed8218a3a7be31ee5f425bfd4cec6", + "chksum_sha256": "7090d0c8c60de535e912349131843b0b242409ea8ddf02306e9ada7517bbd190", "format": 1 }, { - "name": "tests/integration/targets/aci_esg_epg_selector/aliases", + "name": "tests/integration/targets/aci_epg/aliases", "ftype": "file", "chksum_type": "sha256", "chksum_sha256": "616f27a9a7bb49e561ef3782330e18d1a8cea3840e3166e798796684dd546a69", "format": 1 }, { - "name": "tests/integration/targets/aci_cloud_provider", + "name": "tests/integration/targets/aci_cloud_bgp_asn", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/aci_cloud_provider/tasks", + "name": "tests/integration/targets/aci_cloud_bgp_asn/tasks", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/aci_cloud_provider/tasks/main.yml", + "name": "tests/integration/targets/aci_cloud_bgp_asn/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "d1b78c7fd6417e2c36752f6971e733888d0ac8386a10333ea1070bae55695fd2", + "chksum_sha256": "ef83e2ea2fc6e2f8b16098634b11aaa0f6584ffe2e580e51063eafabf767b792", "format": 1 }, { - "name": "tests/integration/targets/aci_cloud_provider/aliases", + "name": "tests/integration/targets/aci_cloud_bgp_asn/aliases", "ftype": "file", "chksum_type": "sha256", "chksum_sha256": "616f27a9a7bb49e561ef3782330e18d1a8cea3840e3166e798796684dd546a69", "format": 1 }, { - "name": "tests/integration/targets/aci_l3out_bgp_peer", + "name": "tests/integration/targets/aci_fabric_external_routing_profile", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/aci_l3out_bgp_peer/tasks", + "name": "tests/integration/targets/aci_fabric_external_routing_profile/tasks", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/aci_l3out_bgp_peer/tasks/main.yml", + "name": "tests/integration/targets/aci_fabric_external_routing_profile/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "b58713b299f63cbc303b82df604713e8c1cf2702ed61b5b178461fad4c36e190", + "chksum_sha256": "773ccf7db7e09cbaf3c76e92ae057c969ecb48e332510c4f7e6d169c970b27d7", "format": 1 }, { - "name": "tests/integration/targets/aci_l3out_bgp_peer/aliases", + "name": "tests/integration/targets/aci_fabric_external_routing_profile/aliases", "ftype": "file", "chksum_type": "sha256", "chksum_sha256": "616f27a9a7bb49e561ef3782330e18d1a8cea3840e3166e798796684dd546a69", "format": 1 }, { - "name": "tests/integration/targets/aci_esg", + "name": "tests/integration/targets/aci_fabric_span_src_group_src_path", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/aci_esg/tasks", + "name": "tests/integration/targets/aci_fabric_span_src_group_src_path/tasks", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/aci_esg/tasks/main.yml", + "name": "tests/integration/targets/aci_fabric_span_src_group_src_path/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "1caf56ec2b7f2e62fe63f79d6e2d0245b7013c18435a4614e88755423a16567e", + "chksum_sha256": "c45de6f0f5ba988c452296375b81d51d2b2afc549b3af9fd8fe201e984d204bd", "format": 1 }, { - "name": "tests/integration/targets/aci_esg/aliases", + "name": "tests/integration/targets/aci_fabric_span_src_group_src_path/aliases", "ftype": "file", "chksum_type": "sha256", "chksum_sha256": "616f27a9a7bb49e561ef3782330e18d1a8cea3840e3166e798796684dd546a69", "format": 1 }, { - "name": "tests/integration/targets/aci_bgp_rr_node", + "name": "tests/integration/targets/aci_fabric_span_src_group_src", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/aci_bgp_rr_node/tasks", + "name": "tests/integration/targets/aci_fabric_span_src_group_src/tasks", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/aci_bgp_rr_node/tasks/main.yml", + "name": "tests/integration/targets/aci_fabric_span_src_group_src/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "ca6e2261d1df22ddd407932d30f07f324d995264a5f5b198a11a4f5dff9b9c63", + "chksum_sha256": "11d0d775fa82a716293db5881ef1a37c57f6e2a964dfeb687af2679560e4bade", "format": 1 }, { - "name": "tests/integration/targets/aci_bgp_rr_node/aliases", + "name": "tests/integration/targets/aci_fabric_span_src_group_src/aliases", "ftype": "file", "chksum_type": "sha256", "chksum_sha256": "616f27a9a7bb49e561ef3782330e18d1a8cea3840e3166e798796684dd546a69", "format": 1 }, { - "name": "tests/integration/targets/aci_aaa_domain", + "name": "tests/integration/targets/aci_tenant_span_src_group", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/aci_aaa_domain/tasks", + "name": "tests/integration/targets/aci_tenant_span_src_group/tasks", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/aci_aaa_domain/tasks/main.yml", + "name": "tests/integration/targets/aci_tenant_span_src_group/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "f70ba67fedbe15cdcd8d967d90ff9a188436898f610fb427a9ef312c5460c0f5", + "chksum_sha256": "7867b37ef567e6e844044a69229948b32007f26f9764787e8e8c5d36db630ce7", "format": 1 }, { - "name": "tests/integration/targets/aci_aaa_domain/aliases", + "name": "tests/integration/targets/aci_tenant_span_src_group/aliases", "ftype": "file", "chksum_type": "sha256", "chksum_sha256": "616f27a9a7bb49e561ef3782330e18d1a8cea3840e3166e798796684dd546a69", "format": 1 }, { - "name": "tests/integration/targets/aci_file_remote_path", + "name": "tests/integration/targets/aci_config_export_policy", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/aci_file_remote_path/tasks", + "name": "tests/integration/targets/aci_config_export_policy/tasks", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/aci_file_remote_path/tasks/main.yml", + "name": "tests/integration/targets/aci_config_export_policy/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "be86a485a2200db58a988ec0095acb483fbc9d7710ff026c96d9ef780cb2fc5b", + "chksum_sha256": "c6d87fc399a3e571a7bf452696d3070b88b7020f08b3bd95e923bfae4009f38b", "format": 1 }, { - "name": "tests/integration/targets/aci_file_remote_path/aliases", + "name": "tests/integration/targets/aci_config_export_policy/aliases", "ftype": "file", "chksum_type": "sha256", "chksum_sha256": "616f27a9a7bb49e561ef3782330e18d1a8cea3840e3166e798796684dd546a69", "format": 1 }, { - "name": "tests/integration/targets/aci_file_remote_path/pki", - "ftype": "dir", - "chksum_type": null, - "chksum_sha256": null, - "format": 1 - }, - { - "name": "tests/integration/targets/aci_file_remote_path/pki/rsa_ansible.key", - "ftype": "file", - "chksum_type": "sha256", - "chksum_sha256": "6945fcb844179106a63be7e8ea5b407f31a8a1e95a1eaa0b5e67da1c26802032", - "format": 1 - }, - { - "name": "tests/integration/targets/aci_aaa_user", + "name": "tests/integration/targets/aci_cloud_epg_selector", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/aci_aaa_user/tasks", + "name": "tests/integration/targets/aci_cloud_epg_selector/tasks", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/aci_aaa_user/tasks/main.yml", + "name": "tests/integration/targets/aci_cloud_epg_selector/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "0a27716e570cda199712f2864aa28f6845cda283992a047be6e435d739c30ce0", + "chksum_sha256": "8d57d82be914fa88e07bc41d7bb244e02734ed6aac76a92bfc10977d5e69c33c", "format": 1 }, { - "name": "tests/integration/targets/aci_aaa_user/aliases", + "name": "tests/integration/targets/aci_cloud_epg_selector/aliases", "ftype": "file", "chksum_type": "sha256", "chksum_sha256": "616f27a9a7bb49e561ef3782330e18d1a8cea3840e3166e798796684dd546a69", "format": 1 }, { - "name": "tests/integration/targets/aci_epg_to_contract_master", + "name": "tests/integration/targets/aci_epg_to_contract_interface", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/aci_epg_to_contract_master/tasks", + "name": "tests/integration/targets/aci_epg_to_contract_interface/tasks", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/aci_epg_to_contract_master/tasks/main.yml", + "name": "tests/integration/targets/aci_epg_to_contract_interface/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "6072b9a2c06b9f3dada60cf3b523afec718985b00c2df0279f4e05d4ecc5432e", + "chksum_sha256": "1c312538c0a8394a8aeb46f742e8d42a78f7e21eb7eb45baac278ea65357dea1", "format": 1 }, { - "name": "tests/integration/targets/aci_epg_to_contract_master/aliases", + "name": "tests/integration/targets/aci_epg_to_contract_interface/aliases", "ftype": "file", "chksum_type": "sha256", "chksum_sha256": "616f27a9a7bb49e561ef3782330e18d1a8cea3840e3166e798796684dd546a69", "format": 1 }, { - "name": "tests/integration/targets/aci_cloud_external_epg", + "name": "tests/integration/targets/aci_system_endpoint_controls", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/aci_cloud_external_epg/tasks", + "name": "tests/integration/targets/aci_system_endpoint_controls/tasks", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/aci_cloud_external_epg/tasks/main.yml", + "name": "tests/integration/targets/aci_system_endpoint_controls/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "bc04416ef5a6af8c60f0aac74936413174b083df60b44b9a0fd9791d687c24e5", + "chksum_sha256": "5607830b2d7127241067d32fde8ad7074d75750f37b8fdd49ace1d8647d791e5", "format": 1 }, { - "name": "tests/integration/targets/aci_cloud_external_epg/aliases", + "name": "tests/integration/targets/aci_system_endpoint_controls/aliases", "ftype": "file", "chksum_type": "sha256", "chksum_sha256": "616f27a9a7bb49e561ef3782330e18d1a8cea3840e3166e798796684dd546a69", "format": 1 }, { - "name": "tests/integration/targets/aci_firmware_policy", + "name": "tests/integration/targets/aci_l3out_interface_secondary_ip", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/aci_firmware_policy/tasks", + "name": "tests/integration/targets/aci_l3out_interface_secondary_ip/tasks", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/aci_firmware_policy/tasks/main.yml", + "name": "tests/integration/targets/aci_l3out_interface_secondary_ip/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "cffeb0a042ff0bba5cceabcf4ddbf8a233ebba5620ae52ed5ea38bb392532cda", + "chksum_sha256": "2afa0e99471843228a5cf1a7459c2fc764b647318621416d6af001e72f31eb20", "format": 1 }, { - "name": "tests/integration/targets/aci_firmware_policy/aliases", + "name": "tests/integration/targets/aci_l3out_interface_secondary_ip/aliases", "ftype": "file", "chksum_type": "sha256", "chksum_sha256": "616f27a9a7bb49e561ef3782330e18d1a8cea3840e3166e798796684dd546a69", "format": 1 }, { - "name": "tests/integration/targets/aci_cloud_subnet", + "name": "tests/integration/targets/aci_static_binding_to_epg", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/aci_cloud_subnet/tasks", + "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_cloud_subnet/tasks/main.yml", + "name": "tests/integration/targets/aci_static_binding_to_epg/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "a8f69aafc42231d6fcbb8e12c3e233c4d5f197b36133a53e8044cb4e80544111", + "chksum_sha256": "48503f32dc4d09af6a416cb2697c5d1e50e86df3ef869cdabd889efb91d80444", "format": 1 }, { - "name": "tests/integration/targets/aci_cloud_subnet/aliases", + "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_vrf", + "name": "tests/integration/targets/aci_l3out_floating_svi_path", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/aci_vrf/tasks", + "name": "tests/integration/targets/aci_l3out_floating_svi_path/tasks", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/aci_vrf/tasks/main.yml", + "name": "tests/integration/targets/aci_l3out_floating_svi_path/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "f8e835d03f2b31ef9aab370d7fca0b89b821069d50d7917aac1ab757d19acb09", + "chksum_sha256": "e939e6263c6afc549ceaba38d1c3885bebd2e13f3fc6e82cc524dcab8848fc72", "format": 1 }, { - "name": "tests/integration/targets/aci_vrf/aliases", + "name": "tests/integration/targets/aci_l3out_floating_svi_path/aliases", "ftype": "file", "chksum_type": "sha256", "chksum_sha256": "616f27a9a7bb49e561ef3782330e18d1a8cea3840e3166e798796684dd546a69", "format": 1 }, { - "name": "tests/integration/targets/aci_filter", + "name": "tests/integration/targets/aci_vmm_uplink", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/aci_filter/tasks", + "name": "tests/integration/targets/aci_vmm_uplink/tasks", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/aci_filter/tasks/main.yml", + "name": "tests/integration/targets/aci_vmm_uplink/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "3b390892db7b692a7a98a480bc46de220a682a0f929ec268d1861a63cc11e870", + "chksum_sha256": "e68d4a1637bd4faec127d03539b84dcf8df2cd4f04f4d2ee54a8e6ee3f79e486", "format": 1 }, { - "name": "tests/integration/targets/aci_filter/aliases", + "name": "tests/integration/targets/aci_vmm_uplink/aliases", "ftype": "file", "chksum_type": "sha256", "chksum_sha256": "616f27a9a7bb49e561ef3782330e18d1a8cea3840e3166e798796684dd546a69", "format": 1 }, { - "name": "tests/integration/targets/aci_l3out_interface", + "name": "tests/integration/targets/aci_firmware_group_node", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/aci_l3out_interface/tasks", + "name": "tests/integration/targets/aci_firmware_group_node/tasks", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/aci_l3out_interface/tasks/main.yml", + "name": "tests/integration/targets/aci_firmware_group_node/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "d4d9c101d09159d2b36a82c35f8fbccbdc87a4f40651964eaa2b38e37696ee05", + "chksum_sha256": "91e40267ec7fcf8abd83cccda6005ac1cd79563ad8294a7a3424ada8cd4d1de7", "format": 1 }, { - "name": "tests/integration/targets/aci_l3out_interface/aliases", + "name": "tests/integration/targets/aci_firmware_group_node/aliases", "ftype": "file", "chksum_type": "sha256", "chksum_sha256": "616f27a9a7bb49e561ef3782330e18d1a8cea3840e3166e798796684dd546a69", "format": 1 }, { - "name": "tests/integration/targets/aci_tenant_span_dst_group", + "name": "tests/integration/targets/aci_bgp_timers_policy", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/aci_tenant_span_dst_group/tasks", + "name": "tests/integration/targets/aci_bgp_timers_policy/tasks", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/aci_tenant_span_dst_group/tasks/main.yml", + "name": "tests/integration/targets/aci_bgp_timers_policy/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "ff4eb055593d4fff6ee7b8a530e750ec83e6bef96f7e30b01debdfc10a45a11b", + "chksum_sha256": "6f414d5bdd980d5bc0683477eccf0068024b2840faa09cd22756ae6ffef09866", "format": 1 }, { - "name": "tests/integration/targets/aci_tenant_span_dst_group/aliases", + "name": "tests/integration/targets/aci_bgp_timers_policy/aliases", "ftype": "file", "chksum_type": "sha256", "chksum_sha256": "616f27a9a7bb49e561ef3782330e18d1a8cea3840e3166e798796684dd546a69", "format": 1 }, { - "name": "tests/integration/targets/aci_l3out_logical_interface_profile_ospf_policy", + "name": "tests/integration/targets/aci_access_span_filter_group", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/aci_l3out_logical_interface_profile_ospf_policy/tasks", + "name": "tests/integration/targets/aci_access_span_filter_group/tasks", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/aci_l3out_logical_interface_profile_ospf_policy/tasks/main.yml", + "name": "tests/integration/targets/aci_access_span_filter_group/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "32b2fb5e9f361fc21865ef39c0ce3e989de8cad67c902bbe9f776e041f743f17", + "chksum_sha256": "6dd4fd944b408971bfdb832ca9ddca613c84215afd429a31fc0f6a3942b67e8c", "format": 1 }, { - "name": "tests/integration/targets/aci_l3out_logical_interface_profile_ospf_policy/aliases", + "name": "tests/integration/targets/aci_access_span_filter_group/aliases", "ftype": "file", "chksum_type": "sha256", "chksum_sha256": "616f27a9a7bb49e561ef3782330e18d1a8cea3840e3166e798796684dd546a69", "format": 1 }, { - "name": "tests/integration/targets/aci_epg", + "name": "tests/integration/targets/aci_l2out_extepg_to_contract", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/aci_epg/tasks", + "name": "tests/integration/targets/aci_l2out_extepg_to_contract/tasks", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/aci_epg/tasks/main.yml", + "name": "tests/integration/targets/aci_l2out_extepg_to_contract/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "67a517482b4a33dcab9d8bd8e4554e267418005c62a16f769382b58322395f25", + "chksum_sha256": "8412f7fab3416a00fde4db461cfef7664d415505f3f5226ba65b6b6b2a0e2830", "format": 1 }, { - "name": "tests/integration/targets/aci_epg/aliases", + "name": "tests/integration/targets/aci_l2out_extepg_to_contract/aliases", "ftype": "file", "chksum_type": "sha256", "chksum_sha256": "616f27a9a7bb49e561ef3782330e18d1a8cea3840e3166e798796684dd546a69", "format": 1 }, { - "name": "tests/integration/targets/aci_cloud_bgp_asn", + "name": "tests/integration/targets/aci_system_global_aes_passphrase_encryption", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/aci_cloud_bgp_asn/tasks", + "name": "tests/integration/targets/aci_system_global_aes_passphrase_encryption/tasks", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/aci_cloud_bgp_asn/tasks/main.yml", + "name": "tests/integration/targets/aci_system_global_aes_passphrase_encryption/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "8cca30820ec8be49ca48b9dc4ce95ed9de8e963abe364b9e5c7a6efa3e1ecc23", + "chksum_sha256": "899d51d6e65dade49ddda996d828b8c246c4aa847400460253c7ee240a912f94", "format": 1 }, { - "name": "tests/integration/targets/aci_cloud_bgp_asn/aliases", + "name": "tests/integration/targets/aci_system_global_aes_passphrase_encryption/aliases", "ftype": "file", "chksum_type": "sha256", "chksum_sha256": "616f27a9a7bb49e561ef3782330e18d1a8cea3840e3166e798796684dd546a69", "format": 1 }, { - "name": "tests/integration/targets/aci_fabric_span_src_group_src_path", + "name": "tests/integration/targets/aci_aaa_user_certificate", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/aci_fabric_span_src_group_src_path/tasks", + "name": "tests/integration/targets/aci_aaa_user_certificate/tasks", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/aci_fabric_span_src_group_src_path/tasks/main.yml", + "name": "tests/integration/targets/aci_aaa_user_certificate/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "36d0fe1f44db748661297e8588d6311dded74f304e8c43e1575ae67e31309031", + "chksum_sha256": "199c9a55602b3f78f352c659379e413b9c4578ee27e82fc8b61bc1f870c2b6d5", "format": 1 }, { - "name": "tests/integration/targets/aci_fabric_span_src_group_src_path/aliases", + "name": "tests/integration/targets/aci_aaa_user_certificate/aliases", "ftype": "file", "chksum_type": "sha256", "chksum_sha256": "616f27a9a7bb49e561ef3782330e18d1a8cea3840e3166e798796684dd546a69", "format": 1 }, { - "name": "tests/integration/targets/aci_fabric_span_src_group_src", + "name": "tests/integration/targets/aci_aaa_user_certificate/pki", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/aci_fabric_span_src_group_src/tasks", - "ftype": "dir", - "chksum_type": null, - "chksum_sha256": null, + "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_fabric_span_src_group_src/tasks/main.yml", + "name": "tests/integration/targets/aci_aaa_user_certificate/pki/rsa_user.key", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "7376aad0adce8582bb048f45bb6999bef5e4c0bd92b879ca9818b3a34af60596", + "chksum_sha256": "8a74dffaf7d04e74642988302b185f0e9eda2dd35a5b7f32317696b12a9790c1", "format": 1 }, { - "name": "tests/integration/targets/aci_fabric_span_src_group_src/aliases", + "name": "tests/integration/targets/aci_aaa_user_certificate/pki/admin.crt", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "616f27a9a7bb49e561ef3782330e18d1a8cea3840e3166e798796684dd546a69", + "chksum_sha256": "f97928b2cd1ce43cfe9ae9bbf47a40b858a749c4c3f25a7ec02898611f4fee90", "format": 1 }, { - "name": "tests/integration/targets/aci_tenant_span_src_group", - "ftype": "dir", - "chksum_type": null, - "chksum_sha256": null, + "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_tenant_span_src_group/tasks", - "ftype": "dir", - "chksum_type": null, - "chksum_sha256": null, + "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_tenant_span_src_group/tasks/main.yml", + "name": "tests/integration/targets/aci_aaa_user_certificate/pki/rsa_user.crt", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "50933aa768540483691d9a20c4c1a15aa1d8af1f46513544d747f73abb84bcca", + "chksum_sha256": "77629e6b31c8c9fad7052f4696dcead786fecef66e33e81c50ce09fcb39d8b4a", "format": 1 }, { - "name": "tests/integration/targets/aci_tenant_span_src_group/aliases", + "name": "tests/integration/targets/aci_aaa_user_certificate/pki/rsa_ansible.key", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "616f27a9a7bb49e561ef3782330e18d1a8cea3840e3166e798796684dd546a69", + "chksum_sha256": "6945fcb844179106a63be7e8ea5b407f31a8a1e95a1eaa0b5e67da1c26802032", "format": 1 }, { - "name": "tests/integration/targets/aci_config_export_policy", + "name": "tests/integration/targets/aci_cloud_ctx_profile", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/aci_config_export_policy/tasks", + "name": "tests/integration/targets/aci_cloud_ctx_profile/tasks", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/aci_config_export_policy/tasks/main.yml", + "name": "tests/integration/targets/aci_cloud_ctx_profile/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "aa4ba50ca5446ff9d640b396c474dde2f5e0feb65eecb9e91db4aeb4d1eadd38", + "chksum_sha256": "30aa6efad91c5732bce45da24f742a50dfc29ed56c7354dcd1dd3eac347c3784", "format": 1 }, { - "name": "tests/integration/targets/aci_config_export_policy/aliases", + "name": "tests/integration/targets/aci_cloud_ctx_profile/aliases", "ftype": "file", "chksum_type": "sha256", "chksum_sha256": "616f27a9a7bb49e561ef3782330e18d1a8cea3840e3166e798796684dd546a69", "format": 1 }, { - "name": "tests/integration/targets/aci_cloud_epg_selector", + "name": "tests/integration/targets/aci_tenant_action_rule_profile", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/aci_cloud_epg_selector/tasks", + "name": "tests/integration/targets/aci_tenant_action_rule_profile/tasks", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/aci_cloud_epg_selector/tasks/main.yml", + "name": "tests/integration/targets/aci_tenant_action_rule_profile/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "f8b04b64f325492a0dd9e7c31568ffe2214b81f289ce9a96557d7ec4272fb592", + "chksum_sha256": "d404d98736d155e056fe35c47c91e155e160324994e69a6f555ec8705f34e2d1", "format": 1 }, { - "name": "tests/integration/targets/aci_cloud_epg_selector/aliases", + "name": "tests/integration/targets/aci_tenant_action_rule_profile/aliases", "ftype": "file", "chksum_type": "sha256", "chksum_sha256": "616f27a9a7bb49e561ef3782330e18d1a8cea3840e3166e798796684dd546a69", "format": 1 }, { - "name": "tests/integration/targets/aci_epg_to_contract_interface", + "name": "tests/integration/targets/aci_aaa_user_role", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/aci_epg_to_contract_interface/tasks", + "name": "tests/integration/targets/aci_aaa_user_role/tasks", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/aci_epg_to_contract_interface/tasks/main.yml", + "name": "tests/integration/targets/aci_aaa_user_role/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "05e64f0bd49cf86a4f884c5816b2061d3bc79734d4c5549c084200777ce08579", + "chksum_sha256": "3a5db07a207f6b1d4dea828953eccffde4a61d9c02064af4db569867b918f553", "format": 1 }, { - "name": "tests/integration/targets/aci_epg_to_contract_interface/aliases", + "name": "tests/integration/targets/aci_aaa_user_role/aliases", "ftype": "file", "chksum_type": "sha256", "chksum_sha256": "616f27a9a7bb49e561ef3782330e18d1a8cea3840e3166e798796684dd546a69", "format": 1 }, { - "name": "tests/integration/targets/aci_system_endpoint_controls", + "name": "tests/integration/targets/aci_bfd_multihop_node_policy", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/aci_system_endpoint_controls/tasks", + "name": "tests/integration/targets/aci_bfd_multihop_node_policy/tasks", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/aci_system_endpoint_controls/tasks/main.yml", + "name": "tests/integration/targets/aci_bfd_multihop_node_policy/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "d38cac5f1adb2065455a24ba14eeb63e9798c2d7beb71ec609b7aa2c24a57ed6", + "chksum_sha256": "d008e5ceb983a17bb32d6788349c2e915a973edd2d4eb87e4cbb9f7da2b13aed", "format": 1 }, { - "name": "tests/integration/targets/aci_system_endpoint_controls/aliases", + "name": "tests/integration/targets/aci_bfd_multihop_node_policy/aliases", "ftype": "file", "chksum_type": "sha256", "chksum_sha256": "616f27a9a7bb49e561ef3782330e18d1a8cea3840e3166e798796684dd546a69", "format": 1 }, { - "name": "tests/integration/targets/aci_l3out_interface_secondary_ip", + "name": "tests/integration/targets/aci_bgp_rr_asn", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/aci_l3out_interface_secondary_ip/tasks", + "name": "tests/integration/targets/aci_bgp_rr_asn/tasks", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/aci_l3out_interface_secondary_ip/tasks/main.yml", + "name": "tests/integration/targets/aci_bgp_rr_asn/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "f0f185cc60c0b1d032084324e53847b3c3dddd21b4a3cb03db5883490a764e0c", + "chksum_sha256": "664c54c3392957c332451d9a1183860fa2e606c9892beb918d65f9e195dbb612", "format": 1 }, { - "name": "tests/integration/targets/aci_l3out_interface_secondary_ip/aliases", + "name": "tests/integration/targets/aci_bgp_rr_asn/aliases", "ftype": "file", "chksum_type": "sha256", "chksum_sha256": "616f27a9a7bb49e561ef3782330e18d1a8cea3840e3166e798796684dd546a69", "format": 1 }, { - "name": "tests/integration/targets/aci_static_binding_to_epg", + "name": "tests/integration/targets/aci_contract_subject", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/aci_static_binding_to_epg/tasks", + "name": "tests/integration/targets/aci_contract_subject/tasks", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/aci_static_binding_to_epg/tasks/main.yml", + "name": "tests/integration/targets/aci_contract_subject/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "3c12648b939c15bfbd8a35c6483db89011dbccd407961c4d41215ca270a71971", + "chksum_sha256": "b2e2ef790915f6b82210707684804b4b87ea0a7231906446fed594e5539763d3", "format": 1 }, { - "name": "tests/integration/targets/aci_static_binding_to_epg/aliases", + "name": "tests/integration/targets/aci_contract_subject/aliases", "ftype": "file", "chksum_type": "sha256", "chksum_sha256": "616f27a9a7bb49e561ef3782330e18d1a8cea3840e3166e798796684dd546a69", "format": 1 }, { - "name": "tests/integration/targets/aci_vmm_uplink", + "name": "tests/integration/targets/aci_l2out_extepg", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/aci_vmm_uplink/tasks", + "name": "tests/integration/targets/aci_l2out_extepg/tasks", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/aci_vmm_uplink/tasks/main.yml", + "name": "tests/integration/targets/aci_l2out_extepg/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "35981a27594dc20c90e735f385654aff3bd3be4a968645356b9edc96a24bfa19", + "chksum_sha256": "9a64487a93a84b5d75b09d109eb24358a1b36ac88ead16a2dd9d083c7ea932a6", "format": 1 }, { - "name": "tests/integration/targets/aci_vmm_uplink/aliases", + "name": "tests/integration/targets/aci_l2out_extepg/aliases", "ftype": "file", "chksum_type": "sha256", "chksum_sha256": "616f27a9a7bb49e561ef3782330e18d1a8cea3840e3166e798796684dd546a69", "format": 1 }, { - "name": "tests/integration/targets/aci_firmware_group_node", + "name": "tests/integration/targets/aci_bgp_address_family_context_policy", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/aci_firmware_group_node/tasks", + "name": "tests/integration/targets/aci_bgp_address_family_context_policy/tasks", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/aci_firmware_group_node/tasks/main.yml", + "name": "tests/integration/targets/aci_bgp_address_family_context_policy/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "c3e4f4978c8f104052bd17ebd014e836998899f4f807661656accefbf40e19fc", + "chksum_sha256": "ec5d52ebe05821de9002324ce8868d780c2d8e67f1a364439113771225d44120", "format": 1 }, { - "name": "tests/integration/targets/aci_firmware_group_node/aliases", + "name": "tests/integration/targets/aci_bgp_address_family_context_policy/aliases", "ftype": "file", "chksum_type": "sha256", "chksum_sha256": "616f27a9a7bb49e561ef3782330e18d1a8cea3840e3166e798796684dd546a69", "format": 1 }, { - "name": "tests/integration/targets/aci_bgp_timers_policy", + "name": "tests/integration/targets/aci_l3out_static_routes", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/aci_bgp_timers_policy/tasks", + "name": "tests/integration/targets/aci_l3out_static_routes/tasks", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/aci_bgp_timers_policy/tasks/main.yml", + "name": "tests/integration/targets/aci_l3out_static_routes/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "e1e28cfb914f228702667f03f8a265f9b869f13e6766c767a90e8edb0166762b", + "chksum_sha256": "cb6d8cf3197e1a320d278c77ee62e6e273a89d3cec7f1c4492dc46bc13952ff0", "format": 1 }, { - "name": "tests/integration/targets/aci_bgp_timers_policy/aliases", + "name": "tests/integration/targets/aci_l3out_static_routes/aliases", "ftype": "file", "chksum_type": "sha256", "chksum_sha256": "616f27a9a7bb49e561ef3782330e18d1a8cea3840e3166e798796684dd546a69", "format": 1 }, { - "name": "tests/integration/targets/aci_access_span_filter_group", + "name": "tests/integration/targets/aci_cloud_zone", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/aci_access_span_filter_group/tasks", + "name": "tests/integration/targets/aci_cloud_zone/tasks", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/aci_access_span_filter_group/tasks/main.yml", + "name": "tests/integration/targets/aci_cloud_zone/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "f670f47ac966f70d906c6b18d446b8e45984dd6e504d3b64bd480b5b28fccda9", + "chksum_sha256": "6c157a960cbb53511ca4b65c8c15c8ba14a9ac55dfe374195e4216ff24a91d44", "format": 1 }, { - "name": "tests/integration/targets/aci_access_span_filter_group/aliases", + "name": "tests/integration/targets/aci_cloud_zone/aliases", "ftype": "file", "chksum_type": "sha256", "chksum_sha256": "616f27a9a7bb49e561ef3782330e18d1a8cea3840e3166e798796684dd546a69", "format": 1 }, { - "name": "tests/integration/targets/aci_l2out_extepg_to_contract", + "name": "tests/integration/targets/aci_switch_leaf_selector", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/aci_l2out_extepg_to_contract/tasks", + "name": "tests/integration/targets/aci_switch_leaf_selector/tasks", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/aci_l2out_extepg_to_contract/tasks/main.yml", + "name": "tests/integration/targets/aci_switch_leaf_selector/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "298360f809920f82f95eee117e53bfb6046d844d36f443e1d4e666cde742fbde", + "chksum_sha256": "2d806125c2e70e3fdd5cb182de4560a4dfb097aacd506d2de6c7337069672ab0", "format": 1 }, { - "name": "tests/integration/targets/aci_l2out_extepg_to_contract/aliases", + "name": "tests/integration/targets/aci_switch_leaf_selector/aliases", "ftype": "file", "chksum_type": "sha256", "chksum_sha256": "616f27a9a7bb49e561ef3782330e18d1a8cea3840e3166e798796684dd546a69", "format": 1 }, { - "name": "tests/integration/targets/aci_system_global_aes_passphrase_encryption", + "name": "tests/integration/targets/aci_aaa_user_domain", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/aci_system_global_aes_passphrase_encryption/tasks", + "name": "tests/integration/targets/aci_aaa_user_domain/tasks", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/aci_system_global_aes_passphrase_encryption/tasks/main.yml", + "name": "tests/integration/targets/aci_aaa_user_domain/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "ae783a7828434afa0de8e616e3e9ecfe84317763a28203beeba2aff1b63bcd55", + "chksum_sha256": "ae53b1118c33169250cd58a3414485bf90bcbce33fd322a93e91a63dd8a36205", "format": 1 }, { - "name": "tests/integration/targets/aci_system_global_aes_passphrase_encryption/aliases", + "name": "tests/integration/targets/aci_aaa_user_domain/aliases", "ftype": "file", "chksum_type": "sha256", "chksum_sha256": "616f27a9a7bb49e561ef3782330e18d1a8cea3840e3166e798796684dd546a69", "format": 1 }, { - "name": "tests/integration/targets/aci_aaa_user_certificate", + "name": "tests/integration/targets/aci_l3out_bfd_interface_profile", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/aci_aaa_user_certificate/tasks", + "name": "tests/integration/targets/aci_l3out_bfd_interface_profile/tasks", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/aci_aaa_user_certificate/tasks/main.yml", + "name": "tests/integration/targets/aci_l3out_bfd_interface_profile/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "de23c78bd0da077a2e5259699d1c861ca6c9ed0b161398c068c74fc95e31d59c", + "chksum_sha256": "fcaba6dbbd06bc810cf1a384017a895c0b4182cf60d20dfde9dc9fcab27859ac", "format": 1 }, { - "name": "tests/integration/targets/aci_aaa_user_certificate/aliases", + "name": "tests/integration/targets/aci_l3out_bfd_interface_profile/aliases", "ftype": "file", "chksum_type": "sha256", "chksum_sha256": "616f27a9a7bb49e561ef3782330e18d1a8cea3840e3166e798796684dd546a69", "format": 1 }, { - "name": "tests/integration/targets/aci_aaa_user_certificate/pki", + "name": "tests/integration/targets/aci_fabric_spine_profile", "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", + "name": "tests/integration/targets/aci_fabric_spine_profile/tasks", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/aci_aaa_user_certificate/pki/rsa_user.key", + "name": "tests/integration/targets/aci_fabric_spine_profile/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "8a74dffaf7d04e74642988302b185f0e9eda2dd35a5b7f32317696b12a9790c1", + "chksum_sha256": "c6f9c12ac6b7d9eb27202617560fa2c7f6de2b246e3e5bf0d2afa3d20af23ff4", "format": 1 }, { - "name": "tests/integration/targets/aci_aaa_user_certificate/pki/admin.crt", + "name": "tests/integration/targets/aci_fabric_spine_profile/aliases", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "f97928b2cd1ce43cfe9ae9bbf47a40b858a749c4c3f25a7ec02898611f4fee90", + "chksum_sha256": "616f27a9a7bb49e561ef3782330e18d1a8cea3840e3166e798796684dd546a69", "format": 1 }, { - "name": "tests/integration/targets/aci_aaa_user_certificate/pki/openssh_rsa.key", - "ftype": "file", - "chksum_type": "sha256", - "chksum_sha256": "81a6ac3a61f2df64339252db67fea1307e891c41232e2da53a1e5219f677c917", + "name": "tests/integration/targets/aci_fabric_pod_connectivity_profile", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/aci_aaa_user_certificate/pki/admin.key", - "ftype": "file", - "chksum_type": "sha256", - "chksum_sha256": "947c1b5a6c419641d4b2c8492b91f2d71588958666aeceeffb1f878460b1d256", + "name": "tests/integration/targets/aci_fabric_pod_connectivity_profile/tasks", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/aci_aaa_user_certificate/pki/rsa_user.crt", + "name": "tests/integration/targets/aci_fabric_pod_connectivity_profile/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "77629e6b31c8c9fad7052f4696dcead786fecef66e33e81c50ce09fcb39d8b4a", + "chksum_sha256": "91495c491ee2f353f10948002561caa645366aa118d0a3c4bd8fed1855287b91", "format": 1 }, { - "name": "tests/integration/targets/aci_aaa_user_certificate/pki/rsa_ansible.key", + "name": "tests/integration/targets/aci_fabric_pod_connectivity_profile/aliases", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "6945fcb844179106a63be7e8ea5b407f31a8a1e95a1eaa0b5e67da1c26802032", + "chksum_sha256": "616f27a9a7bb49e561ef3782330e18d1a8cea3840e3166e798796684dd546a69", "format": 1 }, { - "name": "tests/integration/targets/aci_cloud_ctx_profile", + "name": "tests/integration/targets/aci_l3out_logical_node", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/aci_cloud_ctx_profile/tasks", + "name": "tests/integration/targets/aci_l3out_logical_node/tasks", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/aci_cloud_ctx_profile/tasks/main.yml", + "name": "tests/integration/targets/aci_l3out_logical_node/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "c3244f45def81cbee17c3643e20b46e448c6740ff821bf0d37d2e8877d464c8a", + "chksum_sha256": "914550f2ff9cdabdce76de3706f87f5a13f48b223742d5fbba78728f21d3b1ee", "format": 1 }, { - "name": "tests/integration/targets/aci_cloud_ctx_profile/aliases", + "name": "tests/integration/targets/aci_l3out_logical_node/aliases", "ftype": "file", "chksum_type": "sha256", "chksum_sha256": "616f27a9a7bb49e561ef3782330e18d1a8cea3840e3166e798796684dd546a69", "format": 1 }, { - "name": "tests/integration/targets/aci_tenant_action_rule_profile", + "name": "tests/integration/targets/aci_action_rule_set_as_path_asn", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/aci_tenant_action_rule_profile/tasks", + "name": "tests/integration/targets/aci_action_rule_set_as_path_asn/tasks", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/aci_tenant_action_rule_profile/tasks/main.yml", + "name": "tests/integration/targets/aci_action_rule_set_as_path_asn/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "8a81f5e051113d70e75f90145d1d81cd6444922e3d38b0131d1e6601f7816dbd", + "chksum_sha256": "7ae345cd77046a57a7f8e630459ab04b6252c60104548db9854fd3963fdcbd1d", "format": 1 }, { - "name": "tests/integration/targets/aci_tenant_action_rule_profile/aliases", + "name": "tests/integration/targets/aci_action_rule_set_as_path_asn/aliases", "ftype": "file", "chksum_type": "sha256", "chksum_sha256": "616f27a9a7bb49e561ef3782330e18d1a8cea3840e3166e798796684dd546a69", "format": 1 }, { - "name": "tests/integration/targets/aci_aaa_user_role", + "name": "tests/integration/targets/aci_filter_listify", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/aci_aaa_user_role/tasks", + "name": "tests/integration/targets/aci_filter_listify/tasks", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/aci_aaa_user_role/tasks/main.yml", + "name": "tests/integration/targets/aci_filter_listify/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "56d48ff0dec763a6c52d2d1f7e8c1fbf495e366ca4979d29b9c1178d3d135735", + "chksum_sha256": "4ebd342b364c0bcd4d7458cabd4cbcf98eda3188fedc289375cbee648d18c45e", "format": 1 }, { - "name": "tests/integration/targets/aci_aaa_user_role/aliases", + "name": "tests/integration/targets/aci_filter_listify/aliases", "ftype": "file", "chksum_type": "sha256", "chksum_sha256": "616f27a9a7bb49e561ef3782330e18d1a8cea3840e3166e798796684dd546a69", "format": 1 }, { - "name": "tests/integration/targets/aci_bgp_rr_asn", + "name": "tests/integration/targets/aci_cloud_region", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/aci_bgp_rr_asn/tasks", + "name": "tests/integration/targets/aci_cloud_region/tasks", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/aci_bgp_rr_asn/tasks/main.yml", + "name": "tests/integration/targets/aci_cloud_region/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "d91c2f2511cc599bfec0aad23925038f00045fe03ce492af6ab1b2bec2bed73f", + "chksum_sha256": "d03c2da42e15fc3b0c84a0b1b69bdac0c21fd13d7f640f9b28bd1a10449e5d5b", "format": 1 }, { - "name": "tests/integration/targets/aci_bgp_rr_asn/aliases", + "name": "tests/integration/targets/aci_cloud_region/aliases", "ftype": "file", "chksum_type": "sha256", "chksum_sha256": "616f27a9a7bb49e561ef3782330e18d1a8cea3840e3166e798796684dd546a69", "format": 1 }, { - "name": "tests/integration/targets/aci_contract_subject", + "name": "tests/integration/targets/aci_access_spine_switch_selector", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/aci_contract_subject/tasks", + "name": "tests/integration/targets/aci_access_spine_switch_selector/tasks", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/aci_contract_subject/tasks/main.yml", + "name": "tests/integration/targets/aci_access_spine_switch_selector/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "f545c12b34c65b8f84356ddf1ac88a8038a6b9010d32567eef65976c86001096", + "chksum_sha256": "03c68b11627cec5057b89e00004d3f15f458e014ef267c78626d27f8ca7e6488", "format": 1 }, { - "name": "tests/integration/targets/aci_contract_subject/aliases", + "name": "tests/integration/targets/aci_access_spine_switch_selector/aliases", "ftype": "file", "chksum_type": "sha256", "chksum_sha256": "616f27a9a7bb49e561ef3782330e18d1a8cea3840e3166e798796684dd546a69", "format": 1 }, { - "name": "tests/integration/targets/aci_l2out_extepg", + "name": "tests/integration/targets/aci_route_control_context", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/aci_l2out_extepg/tasks", + "name": "tests/integration/targets/aci_route_control_context/tasks", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/aci_l2out_extepg/tasks/main.yml", + "name": "tests/integration/targets/aci_route_control_context/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "5132135607c61b28d1b345e749441939fc7673970a1fe788692840bedd383a66", + "chksum_sha256": "c06ebb912f21867917c48d6200c05a5a9c193aacd430899bd63c35e5f6685bca", "format": 1 }, { - "name": "tests/integration/targets/aci_l2out_extepg/aliases", + "name": "tests/integration/targets/aci_route_control_context/aliases", "ftype": "file", "chksum_type": "sha256", "chksum_sha256": "616f27a9a7bb49e561ef3782330e18d1a8cea3840e3166e798796684dd546a69", "format": 1 }, { - "name": "tests/integration/targets/aci_l3out_static_routes", + "name": "tests/integration/targets/aci_switch_policy_leaf_profile", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/aci_l3out_static_routes/tasks", + "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_l3out_static_routes/tasks/main.yml", + "name": "tests/integration/targets/aci_switch_policy_leaf_profile/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "4b42b52c3a3a19c551fc82081e676952c8a08e778a9c3fdd3e4dc4a508e458c1", + "chksum_sha256": "6e48f8298d81dadd34c82e6f4909b4e8502eeeabd9e37debe57bb7538d2a8180", "format": 1 }, { - "name": "tests/integration/targets/aci_l3out_static_routes/aliases", + "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_cloud_zone", + "name": "tests/integration/targets/aci_vmm_vswitch_policy", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/aci_cloud_zone/tasks", + "name": "tests/integration/targets/aci_vmm_vswitch_policy/tasks", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/aci_cloud_zone/tasks/main.yml", + "name": "tests/integration/targets/aci_vmm_vswitch_policy/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "b06e53f5f18332fe1f6c2e00cb62c1d78ae10851aea950be32a945e28cad72a4", + "chksum_sha256": "913426c8878960f24280848e6ceda7c2193f6576dbe043b956be207cb23b24aa", "format": 1 }, { - "name": "tests/integration/targets/aci_cloud_zone/aliases", + "name": "tests/integration/targets/aci_vmm_vswitch_policy/aliases", "ftype": "file", "chksum_type": "sha256", "chksum_sha256": "616f27a9a7bb49e561ef3782330e18d1a8cea3840e3166e798796684dd546a69", "format": 1 }, { - "name": "tests/integration/targets/aci_switch_leaf_selector", + "name": "tests/integration/targets/aci_syslog_source", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/aci_switch_leaf_selector/tasks", + "name": "tests/integration/targets/aci_syslog_source/tasks", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/aci_switch_leaf_selector/tasks/main.yml", + "name": "tests/integration/targets/aci_syslog_source/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "522658a23ac16892e9e82fc69f7b4afd930e26dfc02ad82b3e93c95d0181461a", + "chksum_sha256": "1aa926ceea4e53ecff3632cc8251c721993d96bd323dc4160543b24bb7f7671b", "format": 1 }, { - "name": "tests/integration/targets/aci_switch_leaf_selector/aliases", + "name": "tests/integration/targets/aci_syslog_source/aliases", "ftype": "file", "chksum_type": "sha256", "chksum_sha256": "616f27a9a7bb49e561ef3782330e18d1a8cea3840e3166e798796684dd546a69", "format": 1 }, { - "name": "tests/integration/targets/aci_aaa_user_domain", + "name": "tests/integration/targets/aci_vmm_credential", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/aci_aaa_user_domain/tasks", + "name": "tests/integration/targets/aci_vmm_credential/tasks", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/aci_aaa_user_domain/tasks/main.yml", + "name": "tests/integration/targets/aci_vmm_credential/tasks/vmware.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "a2ab7a16b4d545e99c973b926d28fb765c480cd3e21587a129d29ba18a9c1255", + "chksum_sha256": "e4b4bf1a18cb208a79c4e698474729cad83c54ab24130553de53ddd95262080b", "format": 1 }, { - "name": "tests/integration/targets/aci_aaa_user_domain/aliases", + "name": "tests/integration/targets/aci_vmm_credential/tasks/main.yml", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "e56710bf76207c9a80e3fcb62d230acd20b749db044ed8c6080744cd7fdea667", + "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_fabric_spine_profile", + "name": "tests/integration/targets/aci_snmp_user", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/aci_fabric_spine_profile/tasks", + "name": "tests/integration/targets/aci_snmp_user/tasks", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/aci_fabric_spine_profile/tasks/main.yml", + "name": "tests/integration/targets/aci_snmp_user/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "8c7831e91043717924a30d223bdf42efd52198261270595dc1cd0e3b3a4d4d5f", + "chksum_sha256": "efb1388a0c49eb283d44aff2448b64c978ee381bd5c3d47db73b9b1acedc45fb", "format": 1 }, { - "name": "tests/integration/targets/aci_fabric_spine_profile/aliases", + "name": "tests/integration/targets/aci_snmp_user/aliases", "ftype": "file", "chksum_type": "sha256", "chksum_sha256": "616f27a9a7bb49e561ef3782330e18d1a8cea3840e3166e798796684dd546a69", "format": 1 }, { - "name": "tests/integration/targets/aci_l3out_logical_node", + "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_l3out_logical_node/tasks", + "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_l3out_logical_node/tasks/main.yml", + "name": "tests/integration/targets/aci_switch_policy_vpc_protection_group/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "4607bdbef2f2b481fe393e457c18ba02c78af0b6d16f1d53c84e69c0057d30d0", + "chksum_sha256": "d36cb34648ae0539a22d1e5195610d2f2b51a905607af531fbea0309f1513216", "format": 1 }, { - "name": "tests/integration/targets/aci_l3out_logical_node/aliases", + "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_cloud_region", + "name": "tests/integration/targets/aci_netflow_record_policy", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/aci_cloud_region/tasks", + "name": "tests/integration/targets/aci_netflow_record_policy/tasks", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/aci_cloud_region/tasks/main.yml", + "name": "tests/integration/targets/aci_netflow_record_policy/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "07c218a26eba7b984743300e0c8292dc9dbda9000d4cb22a3216a3abb1dc18ed", + "chksum_sha256": "329bae5d9ca559cd2a7a964cb692775a6f9fda68d3ecb1fa9c759ad9c42cc800", "format": 1 }, { - "name": "tests/integration/targets/aci_cloud_region/aliases", + "name": "tests/integration/targets/aci_netflow_record_policy/aliases", "ftype": "file", "chksum_type": "sha256", "chksum_sha256": "616f27a9a7bb49e561ef3782330e18d1a8cea3840e3166e798796684dd546a69", "format": 1 }, { - "name": "tests/integration/targets/aci_route_control_context", + "name": "tests/integration/targets/aci_igmp_interface_policy", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/aci_route_control_context/tasks", + "name": "tests/integration/targets/aci_igmp_interface_policy/tasks", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/aci_route_control_context/tasks/main.yml", + "name": "tests/integration/targets/aci_igmp_interface_policy/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "54fcba37e0a385af9767ffaa2740fd81458fc3cee008e017ec702f8162f18e70", + "chksum_sha256": "427b44e1d879dc625fff8fe46745130443253f461e918f614ebe9c943fdca45d", "format": 1 }, { - "name": "tests/integration/targets/aci_route_control_context/aliases", + "name": "tests/integration/targets/aci_igmp_interface_policy/aliases", "ftype": "file", "chksum_type": "sha256", "chksum_sha256": "616f27a9a7bb49e561ef3782330e18d1a8cea3840e3166e798796684dd546a69", "format": 1 }, { - "name": "tests/integration/targets/aci_switch_policy_leaf_profile", + "name": "tests/integration/targets/aci_aaa_role", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/aci_switch_policy_leaf_profile/tasks", + "name": "tests/integration/targets/aci_aaa_role/tasks", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/aci_switch_policy_leaf_profile/tasks/main.yml", + "name": "tests/integration/targets/aci_aaa_role/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "71c9bc35fe283b8c8ca37f65c12ac529328987b60b799c48c2ded27832452f35", + "chksum_sha256": "f31f4e475199f346f8e3b5ef4da7fc19661e7af0a57701849ed9af132a5cb614", "format": 1 }, { - "name": "tests/integration/targets/aci_switch_policy_leaf_profile/aliases", + "name": "tests/integration/targets/aci_aaa_role/aliases", "ftype": "file", "chksum_type": "sha256", "chksum_sha256": "616f27a9a7bb49e561ef3782330e18d1a8cea3840e3166e798796684dd546a69", "format": 1 }, { - "name": "tests/integration/targets/aci_vmm_vswitch_policy", + "name": "tests/integration/targets/aci_static_node_mgmt_address", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/aci_vmm_vswitch_policy/tasks", + "name": "tests/integration/targets/aci_static_node_mgmt_address/tasks", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/aci_vmm_vswitch_policy/tasks/main.yml", + "name": "tests/integration/targets/aci_static_node_mgmt_address/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "097f845417dd0d363abacdf65fc8915762f05b878e6b628d3be3504f4edef7c6", + "chksum_sha256": "e8a5c433aef22455527758f03430c2e87aad859904f2c804b9f0ae735fc6f4f4", "format": 1 }, { - "name": "tests/integration/targets/aci_vmm_vswitch_policy/aliases", + "name": "tests/integration/targets/aci_static_node_mgmt_address/aliases", "ftype": "file", "chksum_type": "sha256", "chksum_sha256": "616f27a9a7bb49e561ef3782330e18d1a8cea3840e3166e798796684dd546a69", "format": 1 }, { - "name": "tests/integration/targets/aci_syslog_source", + "name": "tests/integration/targets/aci_config_rollback", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/aci_syslog_source/tasks", + "name": "tests/integration/targets/aci_config_rollback/tasks", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/aci_syslog_source/tasks/main.yml", + "name": "tests/integration/targets/aci_config_rollback/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "201852b3cc6e35b2452031b52492754e0824fc6b6beefbf1afa676b7a4c4edb9", + "chksum_sha256": "472c0fb98c3cf9edb626192d2481c896d11d1184503d873353ff8d7e4813223d", "format": 1 }, { - "name": "tests/integration/targets/aci_syslog_source/aliases", + "name": "tests/integration/targets/aci_config_rollback/aliases", "ftype": "file", "chksum_type": "sha256", "chksum_sha256": "616f27a9a7bb49e561ef3782330e18d1a8cea3840e3166e798796684dd546a69", "format": 1 }, { - "name": "tests/integration/targets/aci_vmm_credential", + "name": "tests/integration/targets/aci_interface_policy_port_security", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/aci_vmm_credential/tasks", + "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_vmm_credential/tasks/vmware.yml", - "ftype": "file", - "chksum_type": "sha256", - "chksum_sha256": "68f594ddc8d654e2e02c8283a476b9bd5d66299f56bf71081b741b6f4c38efe4", - "format": 1 - }, - { - "name": "tests/integration/targets/aci_vmm_credential/tasks/main.yml", + "name": "tests/integration/targets/aci_interface_policy_port_security/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "3160edcdbd1b730523e2239ca29b9ce2050d22d65028504573171f59b2a62e82", + "chksum_sha256": "f8c9744d1187e4d9f67cf1215af9f540d6cd1e7be7839a1c437d2a8392cc07e8", "format": 1 }, { - "name": "tests/integration/targets/aci_vmm_credential/aliases", + "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_snmp_user", + "name": "tests/integration/targets/aci_l3out_floating_svi", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/aci_snmp_user/tasks", + "name": "tests/integration/targets/aci_l3out_floating_svi/tasks", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/aci_snmp_user/tasks/main.yml", + "name": "tests/integration/targets/aci_l3out_floating_svi/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "efb1388a0c49eb283d44aff2448b64c978ee381bd5c3d47db73b9b1acedc45fb", + "chksum_sha256": "f03579a734119e7e928a7155c37e13075d716b45b5a4457074bfe1b8012f1e4a", "format": 1 }, { - "name": "tests/integration/targets/aci_snmp_user/aliases", + "name": "tests/integration/targets/aci_l3out_floating_svi/aliases", "ftype": "file", "chksum_type": "sha256", "chksum_sha256": "616f27a9a7bb49e561ef3782330e18d1a8cea3840e3166e798796684dd546a69", "format": 1 }, { - "name": "tests/integration/targets/aci_switch_policy_vpc_protection_group", + "name": "tests/integration/targets/aci_access_span_filter_group_entry", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/aci_switch_policy_vpc_protection_group/tasks", + "name": "tests/integration/targets/aci_access_span_filter_group_entry/tasks", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/aci_switch_policy_vpc_protection_group/tasks/main.yml", + "name": "tests/integration/targets/aci_access_span_filter_group_entry/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "094faa7b08d4d132f470f233ab465a9ee16a6d37d7a5ac76d352cdef966533ea", + "chksum_sha256": "b2f5e1a7ae93be81c9a06807167c50ed2c19388765d2345be14b97ea28ba4c7d", "format": 1 }, { - "name": "tests/integration/targets/aci_switch_policy_vpc_protection_group/aliases", + "name": "tests/integration/targets/aci_access_span_filter_group_entry/aliases", "ftype": "file", "chksum_type": "sha256", "chksum_sha256": "616f27a9a7bb49e561ef3782330e18d1a8cea3840e3166e798796684dd546a69", "format": 1 }, { - "name": "tests/integration/targets/aci_igmp_interface_policy", + "name": "tests/integration/targets/aci_system", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/aci_igmp_interface_policy/tasks", + "name": "tests/integration/targets/aci_system/tasks", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/aci_igmp_interface_policy/tasks/main.yml", + "name": "tests/integration/targets/aci_system/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "4494f102e844ea6ff5c82c65daecef0b968b1e7f1b6109e55b015240e579fd16", + "chksum_sha256": "76e7fd03254cda8d4cadea91be613f9b77ec590c14a09d13e322b4264ff0651e", "format": 1 }, { - "name": "tests/integration/targets/aci_igmp_interface_policy/aliases", + "name": "tests/integration/targets/aci_system/aliases", "ftype": "file", "chksum_type": "sha256", "chksum_sha256": "616f27a9a7bb49e561ef3782330e18d1a8cea3840e3166e798796684dd546a69", "format": 1 }, { - "name": "tests/integration/targets/aci_aaa_role", + "name": "tests/integration/targets/aci_pim_route_map_policy", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/aci_aaa_role/tasks", + "name": "tests/integration/targets/aci_pim_route_map_policy/tasks", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/aci_aaa_role/tasks/main.yml", + "name": "tests/integration/targets/aci_pim_route_map_policy/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "421a7230dbd68e1e8a0ae78052502bcacc51e4873bfe24bd138004b4f340e60b", + "chksum_sha256": "acae8cf67565eb38722387ce99c02bb793670d98086b73830596f6031661379c", "format": 1 }, { - "name": "tests/integration/targets/aci_aaa_role/aliases", + "name": "tests/integration/targets/aci_pim_route_map_policy/aliases", "ftype": "file", "chksum_type": "sha256", "chksum_sha256": "616f27a9a7bb49e561ef3782330e18d1a8cea3840e3166e798796684dd546a69", "format": 1 }, { - "name": "tests/integration/targets/aci_static_node_mgmt_address", + "name": "tests/integration/targets/aci_epg_subnet", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/aci_static_node_mgmt_address/tasks", + "name": "tests/integration/targets/aci_epg_subnet/tasks", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/aci_static_node_mgmt_address/tasks/main.yml", + "name": "tests/integration/targets/aci_epg_subnet/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "76354f4a25f3daeb76b8f8929c15c97d6822ed0c5cda61a2a5b6a4ca9932da52", + "chksum_sha256": "cebd3d119809c5f2ec21749d192c2ada5934a0f1e26d3d5f5ca08e6cae6fe946", "format": 1 }, { - "name": "tests/integration/targets/aci_static_node_mgmt_address/aliases", + "name": "tests/integration/targets/aci_epg_subnet/aliases", "ftype": "file", "chksum_type": "sha256", "chksum_sha256": "616f27a9a7bb49e561ef3782330e18d1a8cea3840e3166e798796684dd546a69", "format": 1 }, { - "name": "tests/integration/targets/aci_config_rollback", + "name": "tests/integration/targets/aci_interface_policy_spanning_tree", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/aci_config_rollback/tasks", + "name": "tests/integration/targets/aci_interface_policy_spanning_tree/tasks", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/aci_config_rollback/tasks/main.yml", + "name": "tests/integration/targets/aci_interface_policy_spanning_tree/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "6d4937bb22c5f4a4a7fe5771ba24fabaa8f0961137cf6811726fb2e07f02f9f5", + "chksum_sha256": "bf5f4904bc4ce5d96a7af20f61d8b3f107cd89aa83ca310c94c4aa2978cf358e", "format": 1 }, { - "name": "tests/integration/targets/aci_config_rollback/aliases", + "name": "tests/integration/targets/aci_interface_policy_spanning_tree/aliases", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "616f27a9a7bb49e561ef3782330e18d1a8cea3840e3166e798796684dd546a69", + "chksum_sha256": "7e5f1f59656b5c296b78849e4845810f74bbe10151203a6d224474a31f470f3f", "format": 1 }, { - "name": "tests/integration/targets/aci_interface_policy_port_security", + "name": "tests/integration/targets/aci_bd_to_netflow_monitor_policy", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/aci_interface_policy_port_security/tasks", + "name": "tests/integration/targets/aci_bd_to_netflow_monitor_policy/tasks", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/aci_interface_policy_port_security/tasks/main.yml", + "name": "tests/integration/targets/aci_bd_to_netflow_monitor_policy/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "5b4022adb62fa72c4942d6104977f94bc734486be02f53ddb5cae1ceffc61371", + "chksum_sha256": "082dfca281ac7354249b0bc7e8695278ca69428044f37989c5a3ea482460372c", "format": 1 }, { - "name": "tests/integration/targets/aci_interface_policy_port_security/aliases", + "name": "tests/integration/targets/aci_bd_to_netflow_monitor_policy/aliases", "ftype": "file", "chksum_type": "sha256", "chksum_sha256": "616f27a9a7bb49e561ef3782330e18d1a8cea3840e3166e798796684dd546a69", "format": 1 }, { - "name": "tests/integration/targets/aci_access_span_filter_group_entry", + "name": "tests/integration/targets/aci_fabric_interface_policy_group", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/aci_access_span_filter_group_entry/tasks", + "name": "tests/integration/targets/aci_fabric_interface_policy_group/tasks", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/aci_access_span_filter_group_entry/tasks/main.yml", + "name": "tests/integration/targets/aci_fabric_interface_policy_group/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "2bb778f87e5538a417e3629d1545ea4995df371213a705e81956e0497b86f9a7", + "chksum_sha256": "e49d3ab8dc00b23ced354238f15530310af0f86643a79d3d7264aba9fb3f8600", "format": 1 }, { - "name": "tests/integration/targets/aci_access_span_filter_group_entry/aliases", + "name": "tests/integration/targets/aci_fabric_interface_policy_group/aliases", "ftype": "file", "chksum_type": "sha256", "chksum_sha256": "616f27a9a7bb49e561ef3782330e18d1a8cea3840e3166e798796684dd546a69", "format": 1 }, { - "name": "tests/integration/targets/aci_system", + "name": "tests/integration/targets/aci_aaa_certificate_authority", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/aci_system/tasks", + "name": "tests/integration/targets/aci_aaa_certificate_authority/tasks", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/aci_system/tasks/main.yml", + "name": "tests/integration/targets/aci_aaa_certificate_authority/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "38c9cb66642f19daee872411bd6dc8df26d1ab38edad0c521397557003124ac4", + "chksum_sha256": "a28a838e0ac37e529e9b2d07a23aa641181eec92493e7ae1f20ff6e8f007829d", "format": 1 }, { - "name": "tests/integration/targets/aci_system/aliases", + "name": "tests/integration/targets/aci_aaa_certificate_authority/aliases", "ftype": "file", "chksum_type": "sha256", "chksum_sha256": "616f27a9a7bb49e561ef3782330e18d1a8cea3840e3166e798796684dd546a69", "format": 1 }, { - "name": "tests/integration/targets/aci_epg_subnet", + "name": "tests/integration/targets/aci_aaa_certificate_authority/pki", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/aci_epg_subnet/tasks", + "name": "tests/integration/targets/aci_aaa_certificate_authority/pki/admin.crt", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "f97928b2cd1ce43cfe9ae9bbf47a40b858a749c4c3f25a7ec02898611f4fee90", + "format": 1 + }, + { + "name": "tests/integration/targets/aci_match_as_path_regex_term", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/aci_epg_subnet/tasks/main.yml", + "name": "tests/integration/targets/aci_match_as_path_regex_term/tasks", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, + "format": 1 + }, + { + "name": "tests/integration/targets/aci_match_as_path_regex_term/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "88b56f6acb0c44928cab5e4b92aaf89a13a592bc7d1e0b88f70515743e29e624", + "chksum_sha256": "3e2a11094eae846a760da9b46d13d900c6cb4c74d5d120ae6ad81ad1cf3fccc2", "format": 1 }, { - "name": "tests/integration/targets/aci_epg_subnet/aliases", + "name": "tests/integration/targets/aci_match_as_path_regex_term/aliases", "ftype": "file", "chksum_type": "sha256", "chksum_sha256": "616f27a9a7bb49e561ef3782330e18d1a8cea3840e3166e798796684dd546a69", "format": 1 }, { - "name": "tests/integration/targets/aci_interface_policy_spanning_tree", + "name": "tests/integration/targets/aci_fabric_pod_external_tep", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/aci_interface_policy_spanning_tree/tasks", + "name": "tests/integration/targets/aci_fabric_pod_external_tep/tasks", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/aci_interface_policy_spanning_tree/tasks/main.yml", + "name": "tests/integration/targets/aci_fabric_pod_external_tep/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "04a8da39c4907965a8fcde343dd74c02f1dc4963d9ba8ed98d08ec90a95340e8", + "chksum_sha256": "d7eaf53338446482dd5fa4fe5140cc31e54b3601bc8453db94dccbde15690cbc", "format": 1 }, { - "name": "tests/integration/targets/aci_interface_policy_spanning_tree/aliases", + "name": "tests/integration/targets/aci_fabric_pod_external_tep/aliases", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "7e5f1f59656b5c296b78849e4845810f74bbe10151203a6d224474a31f470f3f", + "chksum_sha256": "616f27a9a7bb49e561ef3782330e18d1a8cea3840e3166e798796684dd546a69", "format": 1 }, { - "name": "tests/integration/targets/aci_fabric_interface_policy_group", + "name": "tests/integration/targets/aci_bd_dhcp_label", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/aci_fabric_interface_policy_group/tasks", + "name": "tests/integration/targets/aci_bd_dhcp_label/tasks", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/aci_fabric_interface_policy_group/tasks/main.yml", + "name": "tests/integration/targets/aci_bd_dhcp_label/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "827c31fe1653a6a1609f63e81ff2387defe400094845091b89f9b22ae5f536b8", + "chksum_sha256": "30093f02b96084749a02daa955a8b2a71a3086d069340a0d885a8c48e16b54bb", "format": 1 }, { - "name": "tests/integration/targets/aci_fabric_interface_policy_group/aliases", + "name": "tests/integration/targets/aci_bd_dhcp_label/aliases", "ftype": "file", "chksum_type": "sha256", "chksum_sha256": "616f27a9a7bb49e561ef3782330e18d1a8cea3840e3166e798796684dd546a69", "format": 1 }, { - "name": "tests/integration/targets/aci_match_as_path_regex_term", + "name": "tests/integration/targets/aci_qos_custom_policy", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/aci_match_as_path_regex_term/tasks", + "name": "tests/integration/targets/aci_qos_custom_policy/tasks", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/aci_match_as_path_regex_term/tasks/main.yml", + "name": "tests/integration/targets/aci_qos_custom_policy/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "c80e4ffc685fcdc906015246d0d97a767f81e3e76531b08571ed9033f0791dbb", + "chksum_sha256": "13b956ae3c20c1479e51191caf501a84bb8749ce2fe6116ba1f1d693b6252ce7", "format": 1 }, { - "name": "tests/integration/targets/aci_match_as_path_regex_term/aliases", + "name": "tests/integration/targets/aci_qos_custom_policy/aliases", "ftype": "file", "chksum_type": "sha256", "chksum_sha256": "616f27a9a7bb49e561ef3782330e18d1a8cea3840e3166e798796684dd546a69", "format": 1 }, { - "name": "tests/integration/targets/aci_bd_dhcp_label", + "name": "tests/integration/targets/aci_bgp_peer_prefix_policy", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/aci_bd_dhcp_label/tasks", + "name": "tests/integration/targets/aci_bgp_peer_prefix_policy/tasks", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/aci_bd_dhcp_label/tasks/main.yml", + "name": "tests/integration/targets/aci_bgp_peer_prefix_policy/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "e3479a63f7af0ecb0d46bbf2052d4dc3591acaac7ed031c599b4041766f3e34d", + "chksum_sha256": "beda6e7ae2ba6b0f606bbf28ac41e5f08cdcc0d758ce0232579799a79910682f", "format": 1 }, { - "name": "tests/integration/targets/aci_bd_dhcp_label/aliases", + "name": "tests/integration/targets/aci_bgp_peer_prefix_policy/aliases", "ftype": "file", "chksum_type": "sha256", "chksum_sha256": "616f27a9a7bb49e561ef3782330e18d1a8cea3840e3166e798796684dd546a69", @@ -7109,7 +9426,7 @@ "name": "tests/integration/targets/aci_dns_profile/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "7710ef1928ec6670a9c427f5ecbaf920cfceab9998ceb45f88c007388e057124", + "chksum_sha256": "c8f059c2c339e427920a26eb766b5792a91a770f26b8ae2ad5160c14d77b7e63", "format": 1 }, { @@ -7137,7 +9454,7 @@ "name": "tests/integration/targets/aci_l3out_bgp_protocol_profile/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "4c9776bba48af35f22f3ac068ec7c2fa8ebd63127faababdbfff602bedca5452", + "chksum_sha256": "198c5b9ccd95bda9d4931575ca2714b0d88ddf86b11d8ffa21b85f796950adca", "format": 1 }, { @@ -7165,7 +9482,7 @@ "name": "tests/integration/targets/aci_l2out_logical_node_profile/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "78a938d1fd71466218d1a89cd69ba640ed575842f4665e018198f5a2d9b7f627", + "chksum_sha256": "5cbba841fa4aebaf26a55019f4116fa1cdc3d0396985f40237af47821d2fdd50", "format": 1 }, { @@ -7193,7 +9510,7 @@ "name": "tests/integration/targets/aci_cloud_ap/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "a3a8ba85c62882aa47375c7e9877ada0fcd25ceb5e7bc1938b5048553ed0352e", + "chksum_sha256": "6bc7926291ab1290f45c80070ef68096e893db7e23e159b9b988955589267cfb", "format": 1 }, { @@ -7221,7 +9538,7 @@ "name": "tests/integration/targets/aci_fabric_spine_switch_assoc/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "e2971f15de4547047270593a21abab181456009320ef73e072fd24bf4c1db51b", + "chksum_sha256": "fa98c42f0c0d87f0c3522290313cc5a788c1ba2a17bb590ba1fc32080ff6a3ab", "format": 1 }, { @@ -7256,21 +9573,21 @@ "name": "tests/integration/targets/aci_encap_pool/tasks/vlan.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "224201f12daddafc57289377385550b04202dec31060f9cf6599b05ec7016c54", + "chksum_sha256": "20cb0a9ba6b321d2ac5f2a4634e40a1490aba30b4c2267090ecc9e44f9486288", "format": 1 }, { "name": "tests/integration/targets/aci_encap_pool/tasks/vxlan.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "ad7cdd676df819a942211e1ce2ed6cc4b5f0e187035ca0b30c1197179c0ea24a", + "chksum_sha256": "33f714e802c7e5b5cd2cf544ea467938afdda7b0316be4e7a7812a6bd0934173", "format": 1 }, { "name": "tests/integration/targets/aci_encap_pool/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "83fcd807207de6f0e46bafbf20f7c8754cb1f94440e85602cbc8aeea53a67404", + "chksum_sha256": "e43f5aed967a030170540532416573092347695e1eb1f65615e9e97a16bf3c00", "format": 1 }, { @@ -7329,6 +9646,27 @@ "chksum_sha256": "5267e54c38bbd88f23c3f75dff417d2ab9923b7c69e3d038ecc0fee9f337d902", "format": 1 }, + { + "name": "tests/integration/targets/aci_rest/tasks/xml_files/tag.xml", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "1d3f6bdeccd46f8336ce26ddb03789dc48cba17146ce0a00a823c16c29615a2a", + "format": 1 + }, + { + "name": "tests/integration/targets/aci_rest/tasks/xml_files/tn-ans_test_annotation_children.xml", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "2c29bf62b5be93bcf156d3b8ce35c9436149f9c757b284a1cab663a382d4df16", + "format": 1 + }, + { + "name": "tests/integration/targets/aci_rest/tasks/xml_files/tn-ans_test_annotation.xml", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "aba1435ee60db759fd78cd5965c8be68d409021d5ef569330227b24badb05084", + "format": 1 + }, { "name": "tests/integration/targets/aci_rest/tasks/xml_files/tn-ans_test_update.xml", "ftype": "file", @@ -7347,56 +9685,56 @@ "name": "tests/integration/targets/aci_rest/tasks/json_inline.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "e927a5abc052195e3e728d73c5c66557b87ae3bbd976a8c8b7f6611b0c6c16d0", + "chksum_sha256": "891a6726743b1acc2f05b500bf832ae3ab02647a4f355344cc7b4f81748dff56", "format": 1 }, { "name": "tests/integration/targets/aci_rest/tasks/json_string.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "f3da19544e0a9300231d8b96368c1eea2f0e818d0279cece4198e3ba5f89535e", + "chksum_sha256": "59ac5789bef4ea7ec604c2d1a8fa31ca631a81fb646fdb0d1f8b402cfc056199", "format": 1 }, { "name": "tests/integration/targets/aci_rest/tasks/yaml_inline.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "5703d0de444ddbe609527833236735e85bd605f60e50b81ac7f003f53cc37f9c", + "chksum_sha256": "aa1cff215a621eac4aad114ca61de35e74d4263ae4ca99166bf2af5895e3b67c", "format": 1 }, { "name": "tests/integration/targets/aci_rest/tasks/xml_file.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "940d954f67332ff5ff2a853dc92968a7017fab3d4346b0c1703f38ba43993451", + "chksum_sha256": "973a375b620782177e8fcc0795bcd3bc552ca01de5c10e200c8bab4db23f986f", "format": 1 }, { "name": "tests/integration/targets/aci_rest/tasks/xml_string.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "0f0aa8fde34bbb16b8ddfc80dd8a80f596004a8f5b0242d5e0403ac820e1b3d4", + "chksum_sha256": "e2068bc8abb044a6fb8e61131f57cf54b750a448e4ca0cfe152c08512840b0e1", "format": 1 }, { "name": "tests/integration/targets/aci_rest/tasks/yaml_string.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "3616adeb0651848fca25ffd6a229d10f1093581059463d24c783aa9775380dd4", + "chksum_sha256": "d8f45953cd9360d74067a65d045d5f1fa47fed7e0bf28fbc0b30ba61db1bb97d", "format": 1 }, { "name": "tests/integration/targets/aci_rest/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "83f24d55d45b7d9dabfb4f332f208eabee34d9dd97e56bcc555ad83bc1f81c5a", + "chksum_sha256": "654d542ee3a83ed5c83d5256be4e7d79d7b31603284f5333cbd84f0183e6d85e", "format": 1 }, { "name": "tests/integration/targets/aci_rest/tasks/error_handling.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "4b5de110ac6eb32bf731bea15cc3c88b19571e0d39a1c9e85c9131c822bfa242", + "chksum_sha256": "62999920c1d70b945a8ceb759fdfe54999882d8b62d8acb1de17547a42511e56", "format": 1 }, { @@ -7427,6 +9765,34 @@ "chksum_sha256": "616f27a9a7bb49e561ef3782330e18d1a8cea3840e3166e798796684dd546a69", "format": 1 }, + { + "name": "tests/integration/targets/aci_interface_policy_pim", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, + "format": 1 + }, + { + "name": "tests/integration/targets/aci_interface_policy_pim/tasks", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, + "format": 1 + }, + { + "name": "tests/integration/targets/aci_interface_policy_pim/tasks/main.yml", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "8d9b42c2b3624aa7ae1bf269bf711f5f7403e59309aa9c3f60a3a6cdfca742e5", + "format": 1 + }, + { + "name": "tests/integration/targets/aci_interface_policy_pim/aliases", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "616f27a9a7bb49e561ef3782330e18d1a8cea3840e3166e798796684dd546a69", + "format": 1 + }, { "name": "tests/integration/targets/aci_match_community_term", "ftype": "dir", @@ -7445,7 +9811,7 @@ "name": "tests/integration/targets/aci_match_community_term/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "d5be84110acb7260a79bb832aa116b5cd301a6455705e9091bc963ee35ba0fe7", + "chksum_sha256": "d096df2878c4e9a46d0c1291f06a4af8c154d9fb8153fee6ed10e3610942e80a", "format": 1 }, { @@ -7473,7 +9839,7 @@ "name": "tests/integration/targets/aci_contract_subject_to_filter/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "32b77df5bb1d7d8a17718eee2daef2bc17af9e26c0cced27a70e5ea23ccf3e10", + "chksum_sha256": "d943c5183480a1f6d7883c7c86e1470fc780796c8fcff1e10ddf93bdbe02842c", "format": 1 }, { @@ -7501,7 +9867,7 @@ "name": "tests/integration/targets/aci_tag/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "cff28fccf6e21336295bd82d9f68362b37ad95c7ada235ad3fb4a1cbf7d4960e", + "chksum_sha256": "2f61a62d362e61daab4037c313920173d9ed917413863bfa336da68550c1447b", "format": 1 }, { @@ -7529,7 +9895,7 @@ "name": "tests/integration/targets/aci_access_sub_port_block_to_access_port/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "db3e4e59ab75655579f9f793573f3d20b66c50b9d7592ea5b20ed0923e51b593", + "chksum_sha256": "5c6d9c565eb54740091677f27faa6c143f6d637e108f4e59ac724d0e84c96c63", "format": 1 }, { @@ -7557,7 +9923,7 @@ "name": "tests/integration/targets/aci_vrf_leak_internal_subnet/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "a2109f9cc263e3a385afdc3517ddc75c744865636b0dff13915aeecff9e0adb0", + "chksum_sha256": "ac7d1e3e65b11f8a28aaa575ca9a35faed3e8769f692ce165ca530e23c4e1793", "format": 1 }, { @@ -7585,7 +9951,7 @@ "name": "tests/integration/targets/aci_cloud_cidr/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "ba0cb3b0e88b985e8f7ea8f954549e0ca8588a64296c1ac7583a2eda37f0aaa5", + "chksum_sha256": "4a34ccc33268446297b8e7b32ec1cd0069737d00bebe3a4fc436e15d173d21d3", "format": 1 }, { @@ -7613,7 +9979,7 @@ "name": "tests/integration/targets/aci_maintenance_policy/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "e19c89dc5c8b6d6d369ffd128946262764e40ba0a31d63cdd9ecb6a9ef2c8534", + "chksum_sha256": "ee748ee2fb13791df016d81aa90ba0a5eb76c797a90640f773a82e3970d1da65", "format": 1 }, { @@ -7641,7 +10007,7 @@ "name": "tests/integration/inventory.networking", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "ad3de59540f46afab94288be8016738381fb364db4a1cce0f7b26f9e63ac521a", + "chksum_sha256": "066dd1d6fdad5e035f5f03d4c4936694df0725c866ff07b97cb0b890b5cdba0a", "format": 1 }, { @@ -7676,7 +10042,7 @@ "name": "meta/runtime.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "f46a8922200bc41ffe0f26b3be9ef551b64046819d574471631f87913ac8d0b2", + "chksum_sha256": "823478f3e3fece3c5f21468fc12dc2bdf2a7acc90b67ac8c0e585aed4a7b2b5b", "format": 1 }, { @@ -7732,21 +10098,21 @@ "name": "changelogs/.plugin-cache.yaml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "8760c5fd8ac292f4cb5d1e38be9d92e149e5c38f6575d75e62afaf606fb56d4a", + "chksum_sha256": "226a81b01ab9166e26e1b50e58c1062e9d9794cba1ee29aa0291f364c9b2400e", "format": 1 }, { "name": "changelogs/changelog.yaml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "5b5b4f364b875b398bfc855bf601a4acf3199406aaeba2d3191cf0e18bd670db", + "chksum_sha256": "6c1cd0d336c59576dd14c2e88a25cdf9e8f3c21a943b16408c69fe513127d7eb", "format": 1 }, { "name": "README.md", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "9a92f358d773d20208cf3d33bc9b0c297ee9e097ecf04369b558c9fa0a3ae5b8", + "chksum_sha256": "b4cc7dd84bc559d59d2ea5069c4d2cb4036514b0b79809e9370fc642dbd73f02", "format": 1 }, { @@ -7774,7 +10140,7 @@ "name": ".github/workflows/galaxy-importer.cfg", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "edc6f2746e7b8c7b94dea479036ba246953cf69234974b89c069c10d614dcaad", + "chksum_sha256": "495797aee3d8a36d013c51e137187e94b639b998c59e84b64574584c826846a8", "format": 1 }, { @@ -7788,7 +10154,7 @@ "name": ".github/workflows/ansible-test.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "ecb3d932b0557681e1d6713dffa67bf02bab7dca0184cbebe82dac9242c7411a", + "chksum_sha256": "9d19ebb16e37d1dcbde16ceb2dea03b469473f09f22a657f9e5d8f622acfbe89", "format": 1 }, { @@ -7830,7 +10196,7 @@ "name": "CHANGELOG.rst", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "803f408887301e778901174e6ac06a58a26ce84267e24936b3aa58d4441bd333", + "chksum_sha256": "172713983098b06ee2c985e3f0fa30bc70b7fb0fd1113a60efd4e0d6a4bcd1a0", "format": 1 }, { diff --git a/ansible_collections/cisco/aci/MANIFEST.json b/ansible_collections/cisco/aci/MANIFEST.json index f326a92fb..2678c4881 100644 --- a/ansible_collections/cisco/aci/MANIFEST.json +++ b/ansible_collections/cisco/aci/MANIFEST.json @@ -2,7 +2,7 @@ "collection_info": { "namespace": "cisco", "name": "aci", - "version": "2.8.0", + "version": "2.9.0", "authors": [ "Dag Wieers (@dagwieers) ", "Swetha Chunduri (@schunduri)", @@ -40,7 +40,7 @@ "name": "FILES.json", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "0c3eb373bfc6269787c650369f02ac533918bab3cdc51c3bf65c4e6de2114714", + "chksum_sha256": "eed2d47ee4bc72dd865fa06f0d1de3c613afb2c01741dd8ebc66706ddc89f62e", "format": 1 }, "format": 1 diff --git a/ansible_collections/cisco/aci/README.md b/ansible_collections/cisco/aci/README.md index 4e5cdf6af..7ff6e85ea 100644 --- a/ansible_collections/cisco/aci/README.md +++ b/ansible_collections/cisco/aci/README.md @@ -8,7 +8,7 @@ Modules supporting new features introduced in ACI API in specific ACI versions m *Note: This collection is not compatible with versions of Ansible before v2.8.* ## Requirements -Ansible v2.9 or newer +Ansible v2.14 or newer ## Install Ansible must be installed diff --git a/ansible_collections/cisco/aci/changelogs/.plugin-cache.yaml b/ansible_collections/cisco/aci/changelogs/.plugin-cache.yaml index 18556ea00..d7425ab9d 100644 --- a/ansible_collections/cisco/aci/changelogs/.plugin-cache.yaml +++ b/ansible_collections/cisco/aci/changelogs/.plugin-cache.yaml @@ -6,7 +6,11 @@ plugins: callback: {} cliconf: {} connection: {} - filter: {} + filter: + aci_listify: + description: Flattens the nested dictionaries representing the ACI model data. + name: aci_listify + version_added: null httpapi: aci: description: Ansible ACI HTTPAPI Plugin. @@ -19,6 +23,11 @@ plugins: name: interface_range version_added: null module: + aci_aaa_certificate_authority: + description: Manage AAA Certificate Authorities (pki:TP) + name: aci_aaa_certificate_authority + namespace: '' + version_added: null aci_aaa_custom_privilege: description: Manage AAA RBAC Custom Privileges (aaa:RbacClassPriv) name: aci_aaa_custom_privilege @@ -29,13 +38,23 @@ plugins: name: aci_aaa_domain namespace: '' version_added: null + aci_aaa_key_ring: + description: Manage AAA Key Rings (pki:KeyRing) + name: aci_aaa_key_ring + namespace: '' + version_added: null aci_aaa_role: description: Manage AAA roles (aaa:Role) name: aci_aaa_role namespace: '' version_added: null + aci_aaa_security_default_settings: + description: Manage AAA Key Rings (pki:Ep) + name: aci_aaa_security_default_settings + namespace: '' + version_added: null aci_aaa_ssh_auth: - description: Manage AAA SSH auth (aaaSshAuth) objects. + description: Manage AAA SSH auth objects (aaa:SshAuth) name: aci_aaa_ssh_auth namespace: '' version_added: null @@ -60,14 +79,14 @@ plugins: 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) + description: Manage Port blocks of Fabric Access Leaf/Spine Interface Port Selectors + (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) + (infra:HPortS, infra:RsAccBaseGrp, and infra:PortBlk) name: aci_access_port_to_interface_policy_leaf_profile namespace: '' version_added: null @@ -101,15 +120,61 @@ plugins: name: aci_access_span_src_group_src_path namespace: '' version_added: null + aci_access_spine_interface_profile: + description: Manage fabric interface policy spine profiles (infra:SpAccPortP) + name: aci_access_spine_interface_profile + namespace: '' + version_added: null + aci_access_spine_interface_profile_to_spine_switch_profile: + description: Bind Fabric Access Spine Interface Profiles to Fabric Acces Spine + Switch Profiles (infra:RsSpAccPortP) + name: aci_access_spine_interface_profile_to_spine_switch_profile + namespace: '' + version_added: null + aci_access_spine_interface_selector: + description: Manage Fabric Access Policy Spine Interface Port Selectors (infra:SHPortS) + name: aci_access_spine_interface_selector + namespace: '' + version_added: null + aci_access_spine_switch_profile: + description: Manage Fabric Access Spine Switch Profiles (infra:SpineP) + name: aci_access_spine_switch_profile + namespace: '' + version_added: null + aci_access_spine_switch_selector: + description: Manage Fabric Access Policy Spine Switch Port Selectors (infra:SpineS) + name: aci_access_spine_switch_selector + 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) + interface selectors (infra:HPortS and infra:SubPortBlk) name: aci_access_sub_port_block_to_access_port namespace: '' version_added: null + aci_access_switch_policy_group: + description: Manage Access Switch Policy Groups (infra:AccNodePGrp and infra:SpineAccNodePGrp). + name: aci_access_switch_policy_group + namespace: '' + version_added: null + aci_action_rule_additional_communities: + description: Manage Action Rules based on Additional Communities (rtctrl:SetAddComm) + name: aci_action_rule_additional_communities + namespace: '' + version_added: null + aci_action_rule_set_as_path: + description: Manage the AS Path action rules (rtctrl:SetASPath) + name: aci_action_rule_set_as_path + namespace: '' + version_added: null + aci_action_rule_set_as_path_asn: + description: Manage the AS Path ASN (rtctrl:SetASPathASN) + name: aci_action_rule_set_as_path_asn + namespace: '' + version_added: null aci_aep: - description: Manage attachable Access Entity Profile (AEP) objects (infra:AttEntityP, - infra:ProvAcc) + description: Manage attachable Access Entity Profile (AEP) objects (infra:AttEntityP + and infra:ProvAcc) name: aci_aep namespace: '' version_added: null @@ -119,7 +184,7 @@ plugins: namespace: '' version_added: null aci_aep_to_epg: - description: Bind EPG to AEP (infra:RsFuncToEpg). + description: Bind EPG to AEP (infra:RsFuncToEpg) name: aci_aep_to_epg namespace: '' version_added: null @@ -138,6 +203,11 @@ plugins: name: aci_bd_dhcp_label namespace: '' version_added: null + aci_bd_rogue_exception_mac: + description: Manage Rogue Exception MAC (fv:RogueExceptionMac) + name: aci_bd_rogue_exception_mac + namespace: '' + version_added: null aci_bd_subnet: description: Manage Subnets (fv:Subnet) name: aci_bd_subnet @@ -148,18 +218,43 @@ plugins: name: aci_bd_to_l3out namespace: '' version_added: null + aci_bd_to_netflow_monitor_policy: + description: Bind Bridge Domain to Netflow Monitor Policy (fv:RsBDToNetflowMonitorPol) + name: aci_bd_to_netflow_monitor_policy + namespace: '' + version_added: null + aci_bfd_multihop_node_policy: + description: Manage BFD Multihop Node policies (bfd:MhNodePol) + name: aci_bfd_multihop_node_policy + namespace: '' + version_added: null + aci_bgp_address_family_context_policy: + description: Manage BGP address family context policy (bgp:CtxAfPol) + name: aci_bgp_address_family_context_policy + namespace: '' + version_added: null aci_bgp_best_path_policy: description: Manage BGP Best Path policy (bgp:BestPathCtrlPol) name: aci_bgp_best_path_policy namespace: '' version_added: null + aci_bgp_peer_prefix_policy: + description: Manage BGP peer prefix policy (bgp:PeerPfxPol) + name: aci_bgp_peer_prefix_policy + namespace: '' + version_added: null + aci_bgp_route_summarization_policy: + description: Manage BGP route summarization policy (bgp:RtSummPol) + name: aci_bgp_route_summarization_policy + namespace: '' + version_added: null aci_bgp_rr_asn: - description: Manage BGP Route Reflector ASN. + description: Manage BGP Route Reflector ASN (bgp:AsP) name: aci_bgp_rr_asn namespace: '' version_added: null aci_bgp_rr_node: - description: Manage BGP Route Reflector objects. + description: Manage BGP Route Reflector objects (bgp:RRNodePEp) name: aci_bgp_rr_node namespace: '' version_added: null @@ -254,7 +349,7 @@ plugins: namespace: '' version_added: null aci_config_snapshot: - description: Manage Config Snapshots (config:Snapshot, config:ExportP) + description: Manage Config Snapshots (config:Snapshot and config:ExportP) name: aci_config_snapshot namespace: '' version_added: null @@ -279,38 +374,48 @@ plugins: namespace: '' version_added: null aci_contract_subject_to_service_graph: - description: Bind contract subject to service graph (vz:RsSubjGraphAtt). + description: Bind contract subject to service graph (vz:RsSubjGraphAtt) name: aci_contract_subject_to_service_graph namespace: '' version_added: null + aci_dhcp_option: + description: Manage DHCP Option (dhcp:Option) + name: aci_dhcp_option + namespace: '' + version_added: null + aci_dhcp_option_policy: + description: Manage DHCP Option Policy (dhcp:OptionPol) + name: aci_dhcp_option_policy + namespace: '' + version_added: null aci_dhcp_relay: - description: Manage DHCP relay policies. + description: Manage DHCP relay policies (dhcp:RelayP) name: aci_dhcp_relay namespace: '' version_added: null aci_dhcp_relay_provider: - description: Manage DHCP relay policy providers. + description: Manage DHCP relay policy providers (dhcp:RsProv) name: aci_dhcp_relay_provider namespace: '' version_added: null aci_dns_domain: - description: Manage DNS Provider (dnsDomain) objects. + description: Manage DNS Provider objects (dns:Domain) name: aci_dns_domain namespace: '' version_added: null aci_dns_profile: - description: Manage DNS Profile (dnsProfile) objects. + description: Manage DNS Profile objects (dns:Profile) name: aci_dns_profile namespace: '' version_added: null aci_dns_provider: - description: Manage DNS Provider (dnsProv) objects. + description: Manage DNS Provider objects (dns:Prov) name: aci_dns_provider 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) + (phys:DomP, vmm:DomP, l2ext:DomP, l3ext:DomP, and fc:DomP) name: aci_domain namespace: '' version_added: null @@ -325,12 +430,12 @@ plugins: namespace: '' version_added: null aci_encap_pool: - description: Manage encap pools (fvns:VlanInstP, fvns:VxlanInstP, fvns:VsanInstP) + description: Manage encap pools (fvns:VlanInstP, fvns:VxlanInstP, and 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) + description: Manage encap ranges assigned to pools (fvns:EncapBlk and fvns:VsanEncapBlk) name: aci_encap_pool_range namespace: '' version_added: null @@ -350,12 +455,13 @@ plugins: namespace: '' version_added: null aci_epg_to_contract: - description: Bind EPGs to Contracts (fv:RsCons, fv:RsProv) + description: Bind EPGs to Contracts (fv:RsCons, fv:RsProv, fv:RsProtBy, fv:RsConsIf, + and fv:RsIntraEpg) name: aci_epg_to_contract namespace: '' version_added: null aci_epg_to_contract_interface: - description: Bind EPGs to Consumed Contracts Interface (fv:RsConsIf). + description: Bind EPGs to Consumed Contracts Interface (fv:RsConsIf) name: aci_epg_to_contract_interface namespace: '' version_added: null @@ -369,6 +475,17 @@ plugins: name: aci_epg_to_domain namespace: '' version_added: null + aci_epg_useg_attribute_block_statement: + description: Manage EPG useg Attributes Block Statements (fv:SCrtrn) + name: aci_epg_useg_attribute_block_statement + namespace: '' + version_added: null + aci_epg_useg_attribute_simple_statement: + description: Manage EPG useg Attributes Simple Statements (fv:DnsAttr, fv:IdGroupAttr, + fv:IpAttr, fv:MacAttr, and fv:VmAttr) + name: aci_epg_useg_attribute_simple_statement + namespace: '' + version_added: null aci_esg: description: Manage Endpoint Security Groups (ESGs) objects (fv:ESg) name: aci_esg @@ -385,7 +502,7 @@ plugins: namespace: '' version_added: null aci_esg_ip_subnet_selector: - description: Manage ESG IP Subnet selector(fv:EPSelector) + description: Manage ESG IP Subnet selector (fv:EPSelector) name: aci_esg_ip_subnet_selector namespace: '' version_added: null @@ -394,13 +511,23 @@ plugins: name: aci_esg_tag_selector namespace: '' version_added: null + aci_fabric_external_connection_profile: + description: Manage Fabric External Connection Profiles (fv:FabricExtConnP). + name: aci_fabric_external_connection_profile + namespace: '' + version_added: null + aci_fabric_external_routing_profile: + description: Manage Fabric External Routing Profiles (l3ext:FabricExtRoutingP) + name: aci_fabric_external_routing_profile + namespace: '' + version_added: null aci_fabric_interface_policy_group: - description: Manage Fabric Interface Policy Groups (fabric:LePortPGrp, fabric:SpPortPGrp) + description: Manage Fabric Interface Policy Groups (fabric:LePortPGrp and fabric:SpPortPGrp) name: aci_fabric_interface_policy_group namespace: '' version_added: null aci_fabric_leaf_profile: - description: Manage fabric leaf profiles (fabric:LeafP). + description: Manage fabric leaf profiles (fabric:LeafP) name: aci_fabric_leaf_profile namespace: '' version_added: null @@ -410,6 +537,17 @@ plugins: name: aci_fabric_leaf_switch_assoc namespace: '' version_added: null + aci_fabric_management_access: + description: Manage Fabric Management Access (comm:Pol) + name: aci_fabric_management_access + namespace: '' + version_added: null + aci_fabric_management_access_https_cipher: + description: Manage Fabric Management Access HTTPS SSL Cipher Configuration + (comm:Cipher) + name: aci_fabric_management_access_https_cipher + namespace: '' + version_added: null aci_fabric_node: description: Manage Fabric Node Members (fabric:NodeIdentP) name: aci_fabric_node @@ -420,11 +558,36 @@ plugins: name: aci_fabric_node_control namespace: '' version_added: null + aci_fabric_pod: + description: Manage Fabric Pod Setup Policy (fabric:SetupP) + name: aci_fabric_pod + namespace: '' + version_added: null + aci_fabric_pod_connectivity_profile: + description: Manage Fabric External Pod Connectivity Profiles (fv:PodConnP) + name: aci_fabric_pod_connectivity_profile + namespace: '' + version_added: null + aci_fabric_pod_external_tep: + description: Manage Fabric Pod External TEP (fabric:ExtRoutablePodSubnet) + name: aci_fabric_pod_external_tep + namespace: '' + version_added: null aci_fabric_pod_policy_group: description: Manage Fabric Pod Policy Groups (fabric:PodPGrp) name: aci_fabric_pod_policy_group namespace: '' version_added: null + aci_fabric_pod_profile: + description: Manage Fabric Pod Profile (fabric:PodP) + name: aci_fabric_pod_profile + namespace: '' + version_added: null + aci_fabric_pod_remote_pool: + description: Manage Fabric Pod Remote Pool (fabric:ExtSetupP) + name: aci_fabric_pod_remote_pool + namespace: '' + version_added: null aci_fabric_pod_selector: description: Manage Fabric Pod Selectors (fabric:PodS) name: aci_fabric_pod_selector @@ -461,23 +624,24 @@ plugins: namespace: '' version_added: null aci_fabric_spine_profile: - description: Manage fabric spine profiles (fabric:SpineP). + description: Manage fabric spine profiles (fabric:SpineP) name: aci_fabric_spine_profile namespace: '' version_added: null aci_fabric_spine_switch_assoc: description: Manage spine switch bindings to profiles and policy groups (fabric:SpineS - and fabric:RsSpNodePGrp). + and fabric:RsSpNodePGrp) name: aci_fabric_spine_switch_assoc namespace: '' version_added: null aci_fabric_switch_block: - description: Manage switch blocks (fabric:NodeBlk). + description: Manage switch blocks (fabric:NodeBlk) name: aci_fabric_switch_block namespace: '' version_added: null aci_fabric_switch_policy_group: - description: Manage Fabric Switch Policy Group objects. + description: Manage Fabric Switch Policy Group objects (fabric:LeNodePGrp and + fabric:SpNodePGrp) name: aci_fabric_switch_policy_group namespace: '' version_added: null @@ -527,7 +691,7 @@ plugins: namespace: '' version_added: null aci_interface_blacklist: - description: Enabling or Disabling physical interfaces. + description: Enabling or Disabling physical interfaces (fabric:RsOosPath) name: aci_interface_blacklist namespace: '' version_added: null @@ -538,20 +702,41 @@ plugins: namespace: '' version_added: null aci_interface_description: - description: Setting and removing description on physical interfaces. + description: Setting and removing description on physical interfaces (infra:HPathS, + infra:RsHPathAtt, infra:SHPathS, and infra:RsSHPathAtt) name: aci_interface_description namespace: '' version_added: null + aci_interface_policy_bfd: + description: Manage BFD Interface policies (bfd:IfPol) + name: aci_interface_policy_bfd + namespace: '' + version_added: null + aci_interface_policy_bfd_multihop: + description: Manage BFD Multihop Interface policies (bfd:MhIfPol) + name: aci_interface_policy_bfd_multihop + 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_eigrp: + description: Manage EIGRP interface policies (eigrp:IfPol) + name: aci_interface_policy_eigrp + 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_hsrp: + description: Manage HSRP interface policies (hsrp:IfPol) + name: aci_interface_policy_hsrp + namespace: '' + version_added: null aci_interface_policy_l2: description: Manage Layer 2 interface policies (l2:IfPol) name: aci_interface_policy_l2 @@ -563,14 +748,14 @@ plugins: namespace: '' version_added: null aci_interface_policy_leaf_fc_policy_group: - description: Manage Fibre Channel (FC) interface policy groups (infra:FcAccBndlGrp, - infra:FcAccPortGrp) + description: Manage Fibre Channel (FC) interface policy groups (infra:FcAccBndlGrp + and infra:FcAccPortGrp) name: aci_interface_policy_leaf_fc_policy_group namespace: '' version_added: null aci_interface_policy_leaf_policy_group: - description: Manage fabric interface policy leaf policy groups (infra:AccBndlGrp, - infra:AccPortGrp) + description: Manage fabric interface policy leaf policy groups (infra:AccBndlGrp + and infra:AccPortGrp) name: aci_interface_policy_leaf_policy_group namespace: '' version_added: null @@ -604,6 +789,12 @@ plugins: name: aci_interface_policy_ospf namespace: '' version_added: null + aci_interface_policy_pim: + description: Manage Protocol-Independent Multicast (PIM) interface policies + (pim:IfPol) + name: aci_interface_policy_pim + namespace: '' + version_added: null aci_interface_policy_port_channel: description: Manage port channel interface policies (lacp:LagPol) name: aci_interface_policy_port_channel @@ -624,29 +815,45 @@ plugins: name: aci_interface_policy_spine_policy_group namespace: '' version_added: null + aci_interface_policy_storm_control: + description: Manage Storm Control interface policies (stormctrl:IfPol) + name: aci_interface_policy_storm_control + 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_key_policy: + description: Manage Key Policy (fv:KeyPol) + name: aci_key_policy + namespace: '' + version_added: null + aci_keychain_policy: + description: Manage KeyChain Policy (fv:KeyChainPol) + name: aci_keychain_policy + namespace: '' + version_added: null aci_l2out: - description: Manage Layer2 Out (L2Out) objects. + description: Manage Layer2 Out (L2Out) objects (l2ext:Out) name: aci_l2out namespace: '' version_added: null aci_l2out_extepg: - description: Manage External Network Instance (L2Out External EPG) objects (l2extInstP). + description: Manage External Network Instance (L2Out External EPG) objects (l2ext:InstP). name: aci_l2out_extepg namespace: '' version_added: null aci_l2out_extepg_to_contract: - description: Bind Contracts to L2 External End Point Groups (EPGs) + description: Bind Contracts to L2 External End Point Groups (EPGs) (fv:RsCons + and fv:RsProv) name: aci_l2out_extepg_to_contract namespace: '' version_added: null aci_l2out_logical_interface_path: - description: Manage Layer 2 Outside (L2Out) logical interface path (l2extRsPathL2OutAtt) + description: Manage Layer 2 Outside (L2Out) logical interface path (l2ext:RsPathL2OutAtt) name: aci_l2out_logical_interface_path namespace: '' version_added: null @@ -665,8 +872,18 @@ plugins: name: aci_l3out namespace: '' version_added: null + aci_l3out_bfd_interface_profile: + description: Manage L3Out BFD Interface profiles (bfd:IfP) + name: aci_l3out_bfd_interface_profile + namespace: '' + version_added: null + aci_l3out_bfd_multihop_interface_profile: + description: Manage BFD Multihop Interface profiles (bfd:MhIfP) + name: aci_l3out_bfd_multihop_interface_profile + namespace: '' + version_added: null aci_l3out_bgp_peer: - description: Manage Layer 3 Outside (L3Out) BGP Peers (bgp:PeerP) + description: Manage Layer 3 Outside (L3Out) BGP Peers (bgp:PeerP and bgp:InfraPeerP) name: aci_l3out_bgp_peer namespace: '' version_added: null @@ -675,21 +892,69 @@ plugins: name: aci_l3out_bgp_protocol_profile namespace: '' version_added: null + aci_l3out_dhcp_relay_label: + description: Manage Layer 3 Outside (L3Out) DHCP Relay Label (dhcp:Lbl) + name: aci_l3out_dhcp_relay_label + namespace: '' + version_added: null + aci_l3out_eigrp_interface_profile: + description: Manage Layer 3 Outside (L3Out) EIGRP interface profile (eigrp:IfP) + name: aci_l3out_eigrp_interface_profile + 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) + description: Bind Contracts to External End Point Groups (EPGs) (fv:RsCons, + fv:RsProv, fv:RsProtBy, fv:RsConsIf, and fv:RsIntraEpg) name: aci_l3out_extepg_to_contract namespace: '' version_added: null aci_l3out_extsubnet: - description: Manage External Subnet objects (l3extSubnet:extsubnet) + description: Manage External Subnet objects (l3ext:Subnet) name: aci_l3out_extsubnet namespace: '' version_added: null + aci_l3out_floating_svi: + description: Manage Layer 3 Outside (L3Out) interfaces (l3ext:VirtualLIfP) + name: aci_l3out_floating_svi + namespace: '' + version_added: null + aci_l3out_floating_svi_path: + description: Manage Layer 3 Outside (L3Out) Floating SVI Path Attributes (l3ext:RsDynPathAtt) + name: aci_l3out_floating_svi_path + namespace: '' + version_added: null + aci_l3out_floating_svi_path_secondary_ip: + description: Manages Layer 3 Outside (L3Out) Floating SVI Path Attribute's Secondary + IP addresses (l3ext:Ip) + name: aci_l3out_floating_svi_path_secondary_ip + namespace: '' + version_added: null + aci_l3out_floating_svi_secondary_ip: + description: Manages Layer 3 Outside (L3Out) Floating SVI Secondary IP addresses + (l3ext:Ip) + name: aci_l3out_floating_svi_secondary_ip + namespace: '' + version_added: null + aci_l3out_hsrp_group: + description: Manage HSRP group (hsrp:GroupP) of the HSRP interface profile (hsrp:IfP) + name: aci_l3out_hsrp_group + namespace: '' + version_added: null + aci_l3out_hsrp_interface_profile: + description: Manages Layer 3 Outside (L3Out) HSRP interface profile (hsrp:IfP) + name: aci_l3out_hsrp_interface_profile + namespace: '' + version_added: null + aci_l3out_hsrp_secondary_vip: + description: Manage HSRP Secondary Virtual IP of a HSRP group (hsrp:SecVip) + name: aci_l3out_hsrp_secondary_vip + namespace: '' + version_added: null aci_l3out_interface: description: Manage Layer 3 Outside (L3Out) interfaces (l3ext:RsPathL3OutAtt) name: aci_l3out_interface @@ -697,7 +962,7 @@ plugins: version_added: null aci_l3out_interface_secondary_ip: description: Manage Layer 3 Outside (L3Out) interface secondary IP addresses - (l3ext:Ip). + (l3ext:Ip) name: aci_l3out_interface_secondary_ip namespace: '' version_added: null @@ -707,8 +972,7 @@ plugins: namespace: '' version_added: null aci_l3out_logical_interface_profile_ospf_policy: - description: Manage Layer 3 Outside (L3Out) logical interface profile (l3ext:LIfP) - OSPF policy (ospfIfP) + description: Manage Layer 3 Outside (L3Out) OSPF interface profile (ospf:IfP) name: aci_l3out_logical_interface_profile_ospf_policy namespace: '' version_added: null @@ -742,6 +1006,12 @@ plugins: name: aci_l3out_static_routes_nexthop namespace: '' version_added: null + aci_l3out_to_sr_mpls_infra_l3out: + description: Manage Layer 3 Outside (L3Out) to SR-MPLS Infra L3Outs objects + (l3ext:ConsLbl) + name: aci_l3out_to_sr_mpls_infra_l3out + namespace: '' + version_added: null aci_maintenance_group: description: This creates an ACI maintenance group (maint:MaintGrp) name: aci_maintenance_group @@ -778,7 +1048,7 @@ plugins: namespace: '' version_added: null aci_match_route_destination: - description: Manage Match action rule term based on the Route Destination. (rtctrl:MatchRtDest) + description: Manage Match action rule term based on the Route Destination (rtctrl:MatchRtDest) name: aci_match_route_destination namespace: '' version_added: null @@ -787,21 +1057,71 @@ plugins: name: aci_match_rule namespace: '' version_added: null + aci_netflow_exporter_policy: + description: Manage Netflow Exporter Policy (netflow:ExporterPol) + name: aci_netflow_exporter_policy + namespace: '' + version_added: null + aci_netflow_monitor_policy: + description: Manage Netflow Monitor Policy (netflow:MonitorPol) + name: aci_netflow_monitor_policy + namespace: '' + version_added: null + aci_netflow_monitor_to_exporter: + description: Manage Netflow Monitor to Exporter (netflow:RsMonitorToExporter) + name: aci_netflow_monitor_to_exporter + namespace: '' + version_added: null + aci_netflow_record_policy: + description: Manage Netflow Record Policy (netflow:RecordPol) + name: aci_netflow_record_policy + namespace: '' + version_added: null + aci_node_block: + description: Manage Node Block (infra:NodeBlk) + name: aci_node_block + namespace: '' + version_added: null aci_node_mgmt_epg: - description: In band or Out of band management EPGs + description: In band or Out of band management EPGs (mgmt:OoB and mgmt:InB) name: aci_node_mgmt_epg namespace: '' version_added: null aci_ntp_policy: - description: Manage NTP policies. + description: Manage NTP policies (datetime:Pol) name: aci_ntp_policy namespace: '' version_added: null aci_ntp_server: - description: Manage NTP servers. + description: Manage NTP servers (datetime:NtpProv) name: aci_ntp_server namespace: '' version_added: null + aci_pim_route_map_entry: + description: Manage Protocol-Independent Multicast (PIM) Route Map Entry (pim:RouteMapEntry) + name: aci_pim_route_map_entry + namespace: '' + version_added: null + aci_pim_route_map_policy: + description: Manage Protocol-Independent Multicast (PIM) Route Map Policy (pim:RouteMapPol) + name: aci_pim_route_map_policy + namespace: '' + version_added: null + aci_qos_custom_policy: + description: Manage QoS Custom Policy (qos:CustomPol) + name: aci_qos_custom_policy + namespace: '' + version_added: null + aci_qos_dot1p_class: + description: Manage QoS Dot1P Class (qos:Dot1PClass) + name: aci_qos_dot1p_class + namespace: '' + version_added: null + aci_qos_dscp_class: + description: Manage QoS DSCP Class (qos:DscpClass) + name: aci_qos_dscp_class + namespace: '' + version_added: null aci_rest: description: Direct access to the Cisco APIC REST API name: aci_rest @@ -818,27 +1138,27 @@ plugins: namespace: '' version_added: null aci_snmp_client: - description: Manage SNMP clients (snmp:ClientP). + description: Manage SNMP clients (snmp:ClientP) name: aci_snmp_client namespace: '' version_added: null aci_snmp_client_group: - description: Manage SNMP client groups (snmp:ClientGrpP). + description: Manage SNMP client groups (snmp:ClientGrpP) name: aci_snmp_client_group namespace: '' version_added: null aci_snmp_community_policy: - description: Manage SNMP community policies (snmp:CommunityP). + description: Manage SNMP community policies (snmp:CommunityP) name: aci_snmp_community_policy namespace: '' version_added: null aci_snmp_policy: - description: Manage Syslog groups (snmp:Pol). + description: Manage Syslog groups (snmp:Pol) name: aci_snmp_policy namespace: '' version_added: null aci_snmp_user: - description: Manage SNMP v3 Users (snmp:UserP). + description: Manage SNMP v3 Users (snmp:UserP) name: aci_snmp_user namespace: '' version_added: null @@ -848,13 +1168,19 @@ plugins: namespace: '' version_added: null aci_static_node_mgmt_address: - description: In band or Out of band management IP address + description: In band or Out of band management IP address (mgmt:RsOoBStNode + and mgmt:RsInBStNode) name: aci_static_node_mgmt_address namespace: '' version_added: null + aci_subject_label: + description: Manage Subject Labels (vz:ConsSubjLbl and vz:ProvSubjLbl) + name: aci_subject_label + namespace: '' + version_added: null aci_switch_leaf_selector: description: Bind leaf selectors to switch policy leaf profiles (infra:LeafS, - infra:NodeBlk, infra:RsAccNodePGrep) + infra:NodeBlk, and infra:RsAccNodePGrep) name: aci_switch_leaf_selector namespace: '' version_added: null @@ -864,19 +1190,19 @@ plugins: namespace: '' version_added: null aci_switch_policy_vpc_protection_group: - description: Manage switch policy explicit vPC protection groups (fabric:ExplicitGEp, - fabric:NodePEp). + description: Manage switch policy explicit vPC protection groups (fabric:ExplicitGEp + and fabric:NodePEp). name: aci_switch_policy_vpc_protection_group namespace: '' version_added: null aci_syslog_group: description: Manage Syslog groups (syslog:Group, syslog:Console, syslog:File - and syslog:Prof). + and syslog:Prof) name: aci_syslog_group namespace: '' version_added: null aci_syslog_remote_dest: - description: Manage Syslog Remote Destinations (syslog:RemoteDest). + description: Manage Syslog Remote Destinations (syslog:RemoteDest) name: aci_syslog_remote_dest namespace: '' version_added: null @@ -912,7 +1238,7 @@ plugins: namespace: '' version_added: null aci_tag: - description: Tagging of ACI objects + description: Tagging of ACI objects (tag:Annotation, tag:Inst, and tag:Tag) name: aci_tag namespace: '' version_added: null @@ -982,7 +1308,7 @@ plugins: namespace: '' version_added: null aci_vmm_vswitch_policy: - description: Manage vSwitch policy for VMware virtual domains profiles (vmm:DomP) + description: Manage vSwitch policy for VMware virtual domains profiles (vmm:VSwitchPolicyCont) name: aci_vmm_vswitch_policy namespace: '' version_added: null @@ -996,8 +1322,14 @@ plugins: name: aci_vrf_leak_internal_subnet namespace: '' version_added: null + aci_vrf_multicast: + description: Manage VRF Multicast objects (pim:CtxP) + name: aci_vrf_multicast + namespace: '' + version_added: null aci_vzany_to_contract: - description: Attach contracts to vzAny (vz:RsAnyToProv, vz:RsAnyToCons, vz:RsAnyToConsIf) + description: Attach contracts to vzAny (vz:RsAnyToProv, vz:RsAnyToCons, and + vz:RsAnyToConsIf) name: aci_vzany_to_contract namespace: '' version_added: null @@ -1006,4 +1338,4 @@ plugins: strategy: {} test: {} vars: {} -version: 2.8.0 +version: 2.9.0 diff --git a/ansible_collections/cisco/aci/changelogs/changelog.yaml b/ansible_collections/cisco/aci/changelogs/changelog.yaml index ae1c6a3f5..9070ec916 100644 --- a/ansible_collections/cisco/aci/changelogs/changelog.yaml +++ b/ansible_collections/cisco/aci/changelogs/changelog.yaml @@ -459,3 +459,101 @@ releases: " release_date: "2023-11-04" + 2.9.0: + changes: + bugfixes: + - Fix auto logout issue in aci connection plugin to keep connection active between + tasks + - Fix idempotency for l3out configuration when l3protocol is used in aci_l3out + - Fix issues with new attributes in aci_interface_policy_leaf_policy_group module + by adding conditions to include attributes in the payload only when they are + specified by the user (#578) + - Fix query in aci_vmm_controller + minor_changes: + - Add Authentification option for EIGRP interface profile. + - Add L3out Floating SVI modules (aci_l3out_floating_svi, aci_l3out_floating_svi_path, + aci_l3out_floating_svi_path_secondary_ip and aci_l3out_floating_svi_secondary_ip) + (#478) + - Add No-verification flag option to reduce the number of API calls. If true, + a verifying GET will not be sent after a POST update to APIC + - Add access spine interface selector and port block binding in aci_access_port_block_to_access_port + - Add aci_access_spine_interface_selector module + - Add aci_action_rule_additional_communities module + - Add aci_action_rule_set_as_path and aci_action_rule_set_as_path_asn modules + - Add aci_bgp_peer_prefix_policy, aci_bgp_route_summarization_policy and aci_bgp_address_family_context_policy + modules + - Add aci_fabric_pod, aci_fabric_pod_external_tep, aci_fabric_pod_profile, aci_fabric_pod_remote_pool + modules (#558) + - Add aci_hsrp_interface_policy, aci_l3out_hsrp_group, aci_l3out_hsrp_interface_profile + and aci_l3out_hsrp_secondary_vip modules (#505) + - Add aci_interface_policy_eigrp (class:eigrpIfPol) module + - Add aci_interface_policy_pim module + - Add aci_interface_policy_storm_control module + - Add aci_keychain_policy and aci_key_policy modules + - Add aci_l3out_bfd_multihop_interface_profile, aci_l3out_bfd_interface_profile, + aci_interface_policy_bfd_multihop, aci_interface_policy_bfd and aci_bfd_multihop_node_policy + modules (#492) + - Add aci_l3out_dhcp_relay_label, aci_dhcp_option_policy and aci_dhcp_option + modules + - Add aci_l3out_eigrp_interface_profile module + - Add aci_listify filter plugin to flattens nested dictionaries + - Add aci_netflow_exporter_policy module + - Add aci_netflow_monitor_policy and aci_netflow_record_policy modules + - Add aci_netflow_monitor_to_exporter module + - Add aci_node_block module + - Add aci_pim_route_map_policy and aci_pim_route_map_entry modules + - Add aci_qos_custom_policy and aci_qos_dscp_class modules + - Add aci_qos_dot1p_class module + - Add action rules attributes to aci_tenant_action_rule_profile. + - Add auto to speed attribute options in aci_interface_policy_link_level module + (#577) + - Add missing options to aci_bd module + - Add modules aci_bd_to_netflow_monitor_policy and aci_bd_rogue_exception_mac + (#600) + - Add modules for Fabric External Connection Policies and its childs + - Add option to set delimiter to _ in aci_epg_to_domain module + - Add qos_custom_policy, pim_interface_policy and igmp_interface_policy as new + child_classes for aci_l3out_logical_interface_profile. + - Add support for annotation in aci_rest module (#437) + - Add support for block statements in useg attributes with the aci_epg_useg_attribute_block_statement + module + - Add support for configuration of access switch policy groups with aci_access_switch_policy_group + module + - Add support for configuration of certificate authorities in aci_aaa_certificate_authority + - Add support for configuration of fabric management access policies in aci_fabric_management_access + - Add support for configuration of vrf multicast with aci_vrf_multicast module + - Add support for configuring Azure cloud subnets using the aci_cloud_subnet + module + - Add support for encap scope in aci_l3out_interface + - Add support for https ssl cipher configuration in aci_fabric_management_access_https_cipher + - Add support for infra l3out nodes bgp-evpn loopback, mpls transport loopback + and segment id in aci_l3out_logical_node + - Add support for infra sr mpls micro bfd in aci_l3out_interface + - Add support for intra epg, taboo, and contract interface in aci_epg_to_contract + - Add support for key ring configuration in aci_aaa_key_ring + - Add support for mac and description in aci_l3out_interface + - Add support for mpls custom qos policy for infra sr mpls l3outs node profiles + in aci_l3out_logical_node_profile + - Add support for security default settings configuration in aci_aaa_security_default_settings + - Add support for simple statements in useg attributes with the aci_epg_useg_attribute_simple_statement + module + - Add support for sr-mpls bgpInfraPeerP and bgp_password in aci_l3out_bgp_peer + module (#543) + - Add support for sr-mpls in aci_l3out module + - Add support for sr-mpls l3out to infra l3out in aci_l3out_to_sr_mpls_infra_l3out + - Add support for subject labels for EPG, EPG Contract, ESG, Contract Subject, + L2Out External EPG, L3out External EPG, and L3out External EPG Contract with + the aci_subject_label module + - Add support for taboo contract, contract interface and intra_epg contract + in aci_l3out_extepg_to_contract + - Add support for useg default block statement configuration for useg epg in + aci_epg + - Modify child class node block conditions to be optional in aci_switch_leaf_selector + release_summary: + "Release v2.9.0 of the ``ansible-aci`` collection on 2024-04-06. + + This changelog describes all changes made to the modules and plugins included + in this collection since v2.8.0. + + " + release_date: "2024-04-06" diff --git a/ansible_collections/cisco/aci/meta/runtime.yml b/ansible_collections/cisco/aci/meta/runtime.yml index 9dcf11ce2..945315643 100644 --- a/ansible_collections/cisco/aci/meta/runtime.yml +++ b/ansible_collections/cisco/aci/meta/runtime.yml @@ -1,10 +1,13 @@ --- -requires_ansible: '>=2.9.10' +requires_ansible: '>=2.14.0' action_groups: all: + - aci_aaa_certificate_authority - aci_aaa_custom_privilege - aci_aaa_domain + - aci_aaa_key_ring - aci_aaa_role + - aci_aaa_security_default_settings - aci_aaa_ssh_auth - aci_aaa_user - aci_aaa_user_certificate @@ -18,16 +21,31 @@ action_groups: - aci_access_span_src_group - aci_access_span_src_group_src - aci_access_span_src_group_src_path + - aci_access_spine_interface_profile + - aci_access_spine_interface_profile_to_spine_switch_profile + - aci_access_spine_interface_selector + - aci_access_spine_switch_profile + - aci_access_spine_switch_selector - aci_access_sub_port_block_to_access_port + - aci_access_switch_policy_group + - aci_action_rule_additional_communities + - aci_action_rule_set_as_path + - aci_action_rule_set_as_path_asn - aci_aep - aci_aep_to_domain - aci_aep_to_epg - aci_ap - aci_bd - aci_bd_dhcp_label + - aci_bd_rogue_exception_mac - aci_bd_subnet - aci_bd_to_l3out + - aci_bd_to_netflow_monitor_policy + - aci_bfd_multihop_node_policy + - aci_bgp_address_family_context_policy - aci_bgp_best_path_policy + - aci_bgp_peer_prefix_policy + - aci_bgp_route_summarization_policy - aci_bgp_rr_asn - aci_bgp_rr_node - aci_bgp_timers_policy @@ -54,6 +72,8 @@ action_groups: - aci_contract_subject - aci_contract_subject_to_filter - aci_contract_subject_to_service_graph + - aci_dhcp_option + - aci_dhcp_option_policy - aci_dhcp_relay - aci_dhcp_relay_provider - aci_dns_domain @@ -71,17 +91,28 @@ action_groups: - aci_epg_to_contract_interface - aci_epg_to_contract_master - aci_epg_to_domain + - aci_epg_useg_attribute_block_statement + - aci_epg_useg_attribute_simple_statement - aci_esg - aci_esg_contract_master - aci_esg_epg_selector - aci_esg_ip_subnet_selector - aci_esg_tag_selector + - aci_fabric_external_connection_profile + - aci_fabric_external_routing_profile - aci_fabric_interface_policy_group - aci_fabric_leaf_profile - aci_fabric_leaf_switch_assoc + - aci_fabric_management_access + - aci_fabric_management_access_https_cipher - aci_fabric_node - aci_fabric_node_control + - aci_fabric_pod + - aci_fabric_pod_connectivity_profile + - aci_fabric_pod_external_tep - aci_fabric_pod_policy_group + - aci_fabric_pod_profile + - aci_fabric_pod_remote_pool - aci_fabric_pod_selector - aci_fabric_scheduler - aci_fabric_span_dst_group @@ -105,8 +136,12 @@ action_groups: - aci_interface_blacklist - aci_interface_config - aci_interface_description + - aci_interface_policy_bfd + - aci_interface_policy_bfd_multihop - aci_interface_policy_cdp + - aci_interface_policy_eigrp - aci_interface_policy_fc + - aci_interface_policy_hsrp - aci_interface_policy_l2 - aci_interface_policy_leaf_breakout_port_group - aci_interface_policy_leaf_fc_policy_group @@ -117,11 +152,15 @@ action_groups: - aci_interface_policy_lldp - aci_interface_policy_mcp - aci_interface_policy_ospf + - aci_interface_policy_pim - aci_interface_policy_port_channel - aci_interface_policy_port_security - aci_interface_policy_spanning_tree - aci_interface_policy_spine_policy_group + - aci_interface_policy_storm_control - aci_interface_selector_to_switch_policy_leaf_profile + - aci_key_policy + - aci_keychain_policy - aci_l2out - aci_l2out_extepg - aci_l2out_extepg_to_contract @@ -129,11 +168,22 @@ action_groups: - aci_l2out_logical_interface_profile - aci_l2out_logical_node_profile - aci_l3out + - aci_l3out_bfd_interface_profile + - aci_l3out_bfd_multihop_interface_profile - aci_l3out_bgp_peer - aci_l3out_bgp_protocol_profile + - aci_l3out_dhcp_relay_label + - aci_l3out_eigrp_interface_profile - aci_l3out_extepg - aci_l3out_extepg_to_contract - aci_l3out_extsubnet + - aci_l3out_floating_svi + - aci_l3out_floating_svi_path + - aci_l3out_floating_svi_path_secondary_ip + - aci_l3out_floating_svi_secondary_ip + - aci_l3out_hsrp_group + - aci_l3out_hsrp_interface_profile + - aci_l3out_hsrp_secondary_vip - aci_l3out_interface - aci_l3out_interface_secondary_ip - aci_l3out_logical_interface_profile @@ -144,6 +194,7 @@ action_groups: - aci_l3out_route_tag_policy - aci_l3out_static_routes - aci_l3out_static_routes_nexthop + - aci_l3out_to_sr_mpls_infra_l3out - aci_maintenance_group - aci_maintenance_group_node - aci_maintenance_policy @@ -153,9 +204,19 @@ action_groups: - aci_match_community_term - aci_match_route_destination - aci_match_rule + - aci_netflow_exporter_policy + - aci_netflow_monitor_policy + - aci_netflow_monitor_to_exporter + - aci_netflow_record_policy + - aci_node_block - aci_node_mgmt_epg - aci_ntp_policy - aci_ntp_server + - aci_pim_route_map_entry + - aci_pim_route_map_policy + - aci_qos_custom_policy + - aci_qos_dot1p_class + - aci_qos_dscp_class - aci_rest - aci_route_control_context - aci_route_control_profile @@ -166,6 +227,7 @@ action_groups: - aci_snmp_user - aci_static_binding_to_epg - aci_static_node_mgmt_address + - aci_subject_label - aci_switch_leaf_selector - aci_switch_policy_leaf_profile - aci_switch_policy_vpc_protection_group @@ -194,4 +256,5 @@ action_groups: - aci_vmm_vswitch_policy - aci_vrf - aci_vrf_leak_internal_subnet + - aci_vrf_multicast - aci_vzany_to_contract diff --git a/ansible_collections/cisco/aci/plugins/doc_fragments/aci.py b/ansible_collections/cisco/aci/plugins/doc_fragments/aci.py index e6b18a289..aaedff669 100644 --- a/ansible_collections/cisco/aci/plugins/doc_fragments/aci.py +++ b/ansible_collections/cisco/aci/plugins/doc_fragments/aci.py @@ -2,6 +2,7 @@ # Copyright: (c) 2017, Dag Wieers (@dagwieers) # Copyright: (c) 2017, Swetha Chunduri (@schunduri) +# Copyright: (c) 2024, Samita Bhattacharjee (@samiib) # 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 @@ -94,6 +95,15 @@ options: - 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 + suppress_verification: + description: + - If C(true), a verifying GET will not be sent after a POST update to APIC. + - If the value is not specified in the task, the value of environment variable C(ACI_NO_VERIFICATION) will be used instead. + - The default value is C(false). + - WARNING - This causes the current return value to be set to the proposed value. + - The current object including default values will be unverifiable in a single task. + type: bool + aliases: [ no_verification, no_verify, suppress_verify ] seealso: - ref: aci_guide description: Detailed information on how to manage your ACI infrastructure using Ansible. diff --git a/ansible_collections/cisco/aci/plugins/filter/listify.py b/ansible_collections/cisco/aci/plugins/filter/listify.py new file mode 100644 index 000000000..2bb090b25 --- /dev/null +++ b/ansible_collections/cisco/aci/plugins/filter/listify.py @@ -0,0 +1,295 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +# Copyright: (c) 2017, Ramses Smeyers +# Copyright: (c) 2023, Shreyas Srish +# Copyright: (c) 2024, Akini Ross +# 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": "certified"} + +DOCUMENTATION = r""" + name: aci_listify + short_description: Flattens the nested dictionaries representing the ACI model data. + description: + - This filter flattens and transforms the input data into a list. + - See the Examples section below. + options: + data: + description: This option represents the ACI model data which is a list of dictionaries or a dictionary with any level of nesting data. + type: raw + required: True + keys: + description: Comma separated keys of type string denoting the ACI objects. + required: True +""" + +EXAMPLES = r""" +- name: Set vars + ansible.builtin.set_fact: + data: + tenant: + - name: ansible_test + description: Created using listify + app: + - name: app_test + epg: + - name: web + bd: web_bd + - name: app + bd: app_bd + bd: + - name: bd_test + subnet: + - name: 10.10.10.1 + mask: 24 + scope: + - public + - shared + vrf: vrf_test + - name: bd_test2 + subnet: + - name: 20.20.20.1 + mask: 24 + scope: public + vrf: vrf_test + vrf: + - name: vrf_test + policies: + protocol: + bfd: + - name: BFD-ON + description: Enable BFD + admin_state: enabled + detection_multiplier: 3 + min_tx_interval: 50 + min_rx_interval: 50 + echo_rx_interval: 50 + echo_admin_state: enabled + sub_interface_optimization_state: enabled + ospf: + interface: + - name: OSPF-P2P-IntPol + network_type: p2p + priority: 1 + - name: OSPF-Broadcast-IntPol + network_type: bcast + priority: 1 + +- name: Create tenants + cisco.aci.aci_tenant: + host: apic + username: admin + password: SomeSecretPassword + tenant: '{{ item.tenant_name }}' + description: '{{ item.tenant_description }}' + with_items: '{{ data|cisco.aci.aci_listify("tenant") }}' + +- name: Create VRFs + cisco.aci.aci_vrf: + host: apic + username: admin + password: SomeSecretPassword + tenant: '{{ item.tenant_name }}' + vrf_name: '{{ item.tenant_vrf_name }}' + with_items: '{{ data|cisco.aci.aci_listify("tenant","vrf") }}' + +- name: Create BDs + cisco.aci.aci_bd: + host: apic + username: admin + password: SomeSecretPassword + tenant: '{{ item.tenant_name }}' + vrf: '{{ item.tenant_bd_vrf }}' + bd: '{{ item.tenant_bd_name }}' + enable_routing: yes + with_items: '{{ data|cisco.aci.aci_listify("tenant","bd") }}' + +- name: Create BD subnets + cisco.aci.aci_bd_subnet: + host: apic + username: admin + password: SomeSecretPassword + tenant: '{{ item.tenant_name }}' + bd: '{{ item.tenant_bd_name }}' + gateway: '{{ item.tenant_bd_subnet_name }}' + mask: '{{ item.tenant_bd_subnet_mask }}' + scope: '{{ item.tenant_bd_subnet_scope }}' + with_items: '{{ data|cisco.aci.aci_listify("tenant","bd","subnet") }}' + +- name: Create APs + cisco.aci.aci_ap: + host: apic + username: admin + password: SomeSecretPassword + tenant: '{{ item.tenant_name }}' + app_profile: '{{ item.tenant_app_name }}' + with_items: '{{ data|cisco.aci.aci_listify("tenant","app") }}' + +- name: Create EPGs + cisco.aci.aci_epg: + host: apic + username: admin + password: SomeSecretPassword + tenant: '{{ item.tenant_name }}' + app_profile: '{{ item.tenant_app_name }}' + epg: '{{ item.tenant_app_epg_name }}' + bd: '{{ item.tenant_app_epg_bd }}' + with_items: '{{ data|cisco.aci.aci_listify("tenant","app","epg") }}' +""" + +RETURN = r""" +current: + description: The existing configuration from the APIC after the module has finished + returned: success + type: list + sample: + [ + { + "fvTenant": { + "attributes": { + "descr": "Production environment", + "dn": "uni/tn-production", + "name": "production", + "nameAlias": "", + "ownerKey": "", + "ownerTag": "" + } + } + } + ] +error: + description: The error information as returned from the APIC + returned: failure + type: dict + sample: + { + "code": "122", + "text": "unknown managed object class foo" + } +raw: + description: The raw output returned by the APIC REST API (xml or json) + returned: parse error + type: str + sample: '' +sent: + description: The actual/minimal configuration pushed to the APIC + returned: info + type: list + sample: + { + "fvTenant": { + "attributes": { + "descr": "Production environment" + } + } + } +previous: + description: The original configuration from the APIC before the module has started + returned: info + type: list + sample: + [ + { + "fvTenant": { + "attributes": { + "descr": "Production", + "dn": "uni/tn-production", + "name": "production", + "nameAlias": "", + "ownerKey": "", + "ownerTag": "" + } + } + } + ] +proposed: + description: The assembled configuration from the user-provided parameters + returned: info + type: dict + sample: + { + "fvTenant": { + "attributes": { + "descr": "Production environment", + "name": "production" + } + } + } +filter_string: + description: The filter string used for the request + returned: failure or debug + type: str + sample: ?rsp-prop-include=config-only +method: + description: The HTTP method used for the request to the APIC + returned: failure or debug + type: str + sample: POST +response: + description: The HTTP response from the APIC + returned: failure or debug + type: str + sample: OK (30 bytes) +status: + description: The HTTP status from the APIC + returned: failure or debug + type: int + sample: 200 +url: + description: The HTTP url used for the request to the APIC + returned: failure or debug + type: str + sample: https://10.11.12.13/api/mo/uni/tn-production.json +""" + + +# This function takes a dictionary and a series of keys, +# and returns a list of dictionaries using recursive helper function 'listify_worker' +def listify(d, *keys): + return list(listify_worker(d, keys, 0, {}, "")) + + +# This function walks through a dictionary 'd', depth-first, +# using the keys provided, and generates a new dictionary for each key:value pair encountered +def listify_worker(d, keys, depth, cache, prefix): + # The prefix in the code is used to store the path of keys traversed in the nested dictionary, + # which helps to generate unique keys for each value when flattening the dictionary. + prefix += keys[depth] + "_" + + if keys[depth] in d: + for item in d[keys[depth]]: + cache_work = cache.copy() + if isinstance(item, dict): + for k, v in item.items(): + if isinstance(v, list) and all(isinstance(x, (str, int, float, bool, bytes)) for x in v) or not isinstance(v, (dict, list)): + # The cache in this code is a temporary storage that holds key-value pairs as the function navigates through the nested dictionary. + # It helps to generate the final output by remembering the traversed path in each recursive call. + cache_key = prefix + k + cache_value = v + cache_work[cache_key] = cache_value + # If we're at the deepest level of keys + if len(keys) - 1 == depth: + yield cache_work + else: + for k, v in item.items(): + if k == keys[depth + 1] and isinstance(v, (dict, list)): + for result in listify_worker({k: v}, keys, depth + 1, cache_work, prefix): + yield result + # Conditional to support nested dictionaries which are detected by item is string + elif isinstance(item, str) and isinstance(d[keys[depth]], dict): + for result in listify_worker({item: d[keys[depth]][item]}, keys, depth + 1, cache_work, prefix): + yield result + + +class FilterModule(object): + """Ansible core jinja2 filters""" + + def filters(self): + return { + "aci_listify": listify, + } diff --git a/ansible_collections/cisco/aci/plugins/httpapi/aci.py b/ansible_collections/cisco/aci/plugins/httpapi/aci.py index a0474576a..dfab2c14e 100644 --- a/ansible_collections/cisco/aci/plugins/httpapi/aci.py +++ b/ansible_collections/cisco/aci/plugins/httpapi/aci.py @@ -102,19 +102,6 @@ class HttpApi(HttpApiBase): exc_login.path = path raise - def logout(self): - method = "POST" - path = "/api/aaaLogout.json" - payload = {"aaaUser": {"attributes": {"name": self.connection.get_option("remote_user")}}} - data = json.dumps(payload) - try: - response, response_data = self.connection.send(path, data, method=method) - except Exception as exc_logout: - msg = "Error on attempt to logout from APIC. {0}".format(exc_logout) - raise ConnectionError(self._return_info("", method, path, msg)) - self.connection._auth = None - self._verify_response(response, method, path, response_data) - def set_parameters(self): connection_parameters = {} for key in CONNECTION_KEYS: diff --git a/ansible_collections/cisco/aci/plugins/module_utils/aci.py b/ansible_collections/cisco/aci/plugins/module_utils/aci.py index 9c6e2db2d..88b49cd6e 100644 --- a/ansible_collections/cisco/aci/plugins/module_utils/aci.py +++ b/ansible_collections/cisco/aci/plugins/module_utils/aci.py @@ -15,6 +15,8 @@ # Copyright: (c) 2020, Anvitha Jain (@anvitha-jain) # Copyright: (c) 2023, Gaspard Micol (@gmicol) # Copyright: (c) 2023, Shreyas Srish (@shrsr) +# Copyright: (c) 2023, Tim Cragg (@timcragg) +# Copyright: (c) 2024, Samita Bhattacharjee (@samiib) # All rights reserved. # Redistribution and use in source and binary forms, with or without modification, @@ -134,6 +136,7 @@ def aci_argument_spec(): use_ssl=dict(type="bool", fallback=(env_fallback, ["ACI_USE_SSL"])), validate_certs=dict(type="bool", fallback=(env_fallback, ["ACI_VALIDATE_CERTS"])), output_path=dict(type="str", fallback=(env_fallback, ["ACI_OUTPUT_PATH"])), + suppress_verification=dict(type="bool", aliases=["no_verification", "no_verify", "suppress_verify"], fallback=(env_fallback, ["ACI_NO_VERIFICATION"])), ) @@ -320,6 +323,64 @@ def integrate_url(httpapi_url, local_path): return {"protocol": parse_url.scheme, "host": parse_url.netloc, "path": local_path} +def action_rule_set_comm_spec(): + return dict( + community=dict(type="str"), + criteria=dict(type="str", choices=["append", "none", "replace"]), + ) + + +def action_rule_set_dampening_spec(): + return dict( + half_life=dict(type="int"), + max_suppress_time=dict(type="int"), + reuse=dict(type="int"), + suppress=dict(type="int"), + ) + + +def associated_netflow_exporter_epg_spec(): + return dict( + tenant=dict(type="str"), + ap=dict(type="str"), + epg=dict(type="str"), + ) + + +def associated_netflow_exporter_extepg_spec(): + return dict( + tenant=dict(type="str"), + l3out=dict(type="str"), + extepg=dict(type="str"), + ) + + +def associated_netflow_exporter_vrf_spec(): + return dict( + tenant=dict(type="str"), + vrf=dict(type="str"), + ) + + +def pim_interface_profile_spec(): + return dict( + tenant=dict(type="str", aliases=["tenant_name"]), + pim=dict(type="str", aliases=["pim_interface_policy", "name"]), + ) + + +def igmp_interface_profile_spec(): + return dict(tenant=dict(type="str", aliases=["tenant_name"]), igmp=dict(type="str", aliases=["igmp_interface_policy", "name"])) + + +def storm_control_policy_rate_spec(): + return dict( + rate=dict(type="str"), + burst_rate=dict(type="str"), + rate_type=dict(type="str", choices=["percentage", "pps"], required=True), + ) + + class ACIModule(object): def __init__(self, module): self.module = module @@ -356,6 +417,9 @@ class ACIModule(object): self.imdata = None self.totalCount = None + # get no verify flag + self.suppress_verification = self.params.get("suppress_verification") + # Ensure protocol is set self.define_protocol() @@ -779,8 +843,10 @@ class ACIModule(object): subclass_3=None, subclass_4=None, subclass_5=None, + subclass_6=None, child_classes=None, config_only=True, + rsp_subtree="full", ): """ This method is used to retrieve the appropriate URL path and filter_string to make the request to the APIC. @@ -796,6 +862,7 @@ class ACIModule(object): :type subclass_3: dict :type subclass_4: dict :type subclass_5: dict + :type subclass_6: dict :type child_classes: list :return: The path and filter_string needed to build the full URL. """ @@ -806,7 +873,9 @@ class ACIModule(object): else: self.child_classes = set(child_classes) - if subclass_5 is not None: + if subclass_6 is not None: + self._construct_url_7(root_class, subclass_1, subclass_2, subclass_3, subclass_4, subclass_5, subclass_6, config_only) + elif 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) @@ -828,10 +897,12 @@ class ACIModule(object): # Append child_classes to filter_string if filter string is empty self.update_qs( { - "rsp-subtree": "full", + "rsp-subtree": rsp_subtree, "rsp-subtree-class": ",".join(sorted(self.child_classes)), } ) + elif rsp_subtree == "children": + self.update_qs({"rsp-subtree": rsp_subtree}) def _construct_url_1(self, obj, config_only=True): """ @@ -1077,7 +1148,7 @@ class ACIModule(object): 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. + This method is used by construct_url when the object is the fifth-level class. """ root_rn = root.get("aci_rn") root_obj = root.get("module_object") @@ -1145,6 +1216,85 @@ class ACIModule(object): # 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 _construct_url_7(self, root, quin, quad, ter, sec, parent, obj, config_only=True): + """ + This method is used by construct_url when the object is the sixth-level class. + """ + root_rn = root.get("aci_rn") + root_obj = root.get("module_object") + quin_rn = quin.get("aci_rn") + quin_obj = quin.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}/{6}.json".format(root_rn, quin_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 quin_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 quin_filter, parent and obj_filter + self.update_qs({"rsp-subtree-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}/{1}.json".format(root_rn, quin_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 quin_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}/{2}.json".format(root_rn, quin_rn, quad_rn) + # NOTE: No need to select by quad_filter + # self.update_qs({'query-target-filter': self.build_filter(quin_class, quin_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}/{3}.json".format(root_rn, quin_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}/{4}.json".format(root_rn, quin_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}/{5}.json".format(root_rn, quin_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}/{6}.json".format(root_rn, quin_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 @@ -1161,7 +1311,7 @@ class ACIModule(object): self.result["changed"] = True self.method = "DELETE" - def get_diff(self, aci_class): + def get_diff(self, aci_class, required_properties=None): """ 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 @@ -1183,6 +1333,8 @@ class ACIModule(object): # 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 + if required_properties and isinstance(required_properties, dict): + config.update(required_properties) config = {aci_class: {"attributes": config}} # check for updates to child configs and update new config dictionary @@ -1369,23 +1521,30 @@ class ACIModule(object): # 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) + children = self.handle_child_configs(child_configs) if children: self.proposed[aci_class].update(dict(children=children)) + def handle_child_configs(self, child_configs): + children = [] + for child in child_configs: + child_copy = deepcopy(child) + has_value = False + for class_name in child_copy.keys(): + for attribute, value in child_copy[class_name]["attributes"].items(): + if value is None: + child[class_name]["attributes"].pop(attribute) + else: + child[class_name]["attributes"][attribute] = str(value) + has_value = True + if child_copy[class_name].get("children") is not None: + has_value = True + child[class_name]["children"] = self.handle_child_configs(child_copy[class_name]["children"]) + if has_value: + children.append(child) + return children + def post_config(self, parent_class=None): """ This method is used to handle the logic when the modules state is equal to present. The method only pushes a change if @@ -1438,7 +1597,15 @@ class ACIModule(object): if "state" in self.params: self.original = self.existing if self.params.get("state") in ("absent", "present"): - self.get_existing() + if self.suppress_verification: + if self.result["changed"]: + self.result["current_verified"] = False + self.existing = [self.proposed] + else: + self.result["current_verified"] = True + # exisiting already equals the previous + else: + self.get_existing() # if self.module._diff and self.original != self.existing: # self.result['diff'] = dict( diff --git a/ansible_collections/cisco/aci/plugins/module_utils/annotation_unsupported.py b/ansible_collections/cisco/aci/plugins/module_utils/annotation_unsupported.py new file mode 100644 index 000000000..6e34889fb --- /dev/null +++ b/ansible_collections/cisco/aci/plugins/module_utils/annotation_unsupported.py @@ -0,0 +1,853 @@ +# Code generated by release_script GitHub action; DO NOT EDIT MANUALLY. +ANNOTATION_UNSUPPORTED = [ + "topRoot", + "monPol", + "monATarget", + "monTarget", + "moTopProps", + "moModifiable", + "moOwnable", + "moResolvable", + "moASubj", + "actionACont", + "taskExec", + "namingNamedObject", + "namingNamedIdentifiedObject", + "conditionInfo", + "conditionRetP", + "conditionRecord", + "conditionLoggable", + "faultInfo", + "relnInst", + "relnTo", + "relnFrom", + "statsItem", + "statsAColl", + "statsAThrP", + "relnTaskRef", + "hvsNode", + "qosACong", + "qosAQueue", + "qosABuffer", + "qosASched", + "qosClassification", + "qosADscpClass", + "qosADot1PClass", + "lacpALagPol", + "pconsRef", + "eventARetP", + "faultAThrValue", + "faultARetP", + "configABackupP", + "dnsAProfile", + "dnsAProv", + "dnsADomain", + "dnsALbl", + "sysdebugRepository", + "sysdebugFile", + "sysdebugLogBehavior", + "firmwareSource", + "firmwareAFwStatusCont", + "firmwareARunning", + "firmwareAFwP", + "maintAMaintP", + "maintUserNotif", + "fabricComp", + "fabricANode", + "fabricALink", + "ruleDefinition", + "ruleItem", + "ruleRequirement", + "ruleSizeRequirement", + "stpAIfPol", + "haHaTest", + "rtctrlAMatchRule", + "rtctrlAMatchIpRule", + "rtctrlAMatchRtType", + "rtctrlASubnet", + "rtctrlAAttrP", + "rtctrlASetRule", + "rtctrlASetTag", + "rtctrlASetComm", + "rtctrlASetRtMetric", + "rtctrlASetPref", + "rtctrlASetNh", + "rtctrlASetOspfFwdAddr", + "rtctrlASetOspfNssa", + "bgpAAsP", + "bgpACtxPol", + "bgpAPeerPfxPol", + "bgpAPeerP", + "bgpAExtP", + "cdpAIfPol", + "fabricProtoIfPol", + "fabricL2IfPol", + "fabricL3IfPol", + "lldpAIfPol", + "fabricProtoPol", + "fabricProtoComp", + "fabricL2ProtoPol", + "fabricL3ProtoPol", + "fabricL2ProtoComp", + "fabricL3ProtoComp", + "fabricProtoInstPol", + "fabricUtilInstPol", + "fabricL2InstPol", + "fabricL3InstPol", + "fabricProtoDomPol", + "fabricL2DomPol", + "fabricL3DomPol", + "fabricL3CtxPol", + "l2AInstPol", + "fabricMaintPol", + "fabricNodeGrp", + "fabricAPodBlk", + "fabricANodeBlk", + "fabricAPortBlk", + "fabricSelector", + "fabricANodeS", + "fabricNodeS", + "fabricACardS", + "fabricCardS", + "fabricAPortS", + "fabricPortS", + "fabricIntfPol", + "fabricAProfile", + "fabricProfile", + "fabricPolGrp", + "fabricNodeP", + "fabricCardP", + "fabricPortP", + "fabricAPortPGrp", + "fabricANodePGrp", + "fabricACardPGrp", + "fabricSpAPortPGrp", + "fabricLeAPortPGrp", + "fabricAProtPol", + "fabricANodePEp", + "fabricPol", + "fabricInfrP", + "fabricInfrExP", + "fabricDom", + "fabricDef", + "fabricAPolGrp", + "vsvcAProvLbl", + "vsvcAConsLbl", + "compASvcVM", + "compNic", + "compPNic", + "compEntity", + "compElement", + "compContE", + "compObj", + "compCont", + "compProvP", + "compDomP", + "compCtrlrP", + "compAccessP", + "compUsrAccP", + "compHost", + "compPHost", + "vzACollection", + "vzACtrct", + "vzABrCP", + "vzAIf", + "vzAFilterable", + "vzAFilterableUnit", + "vzASubj", + "vzATerm", + "vzASTerm", + "vzALbl", + "vzACompLbl", + "vzAnyToCollection", + "vzAFilter", + "vzAFiltEntry", + "ospfACtxPol", + "ospfAIfP", + "ospfAExtP", + "dhcpARelayP", + "dhcpALbl", + "dhcpAInfraProvP", + "poolElement", + "poolPoolable", + "poolPoolMember", + "poolPool", + "pkiItem", + "aaaDefinition", + "commDefinition", + "pkiDefinition", + "aaaSystemUser", + "aaaBanner", + "aaaUserAction", + "aaaARetP", + "commComp", + "commWeb", + "commShell", + "aaaRealm", + "aaaConfig", + "aaaAuthMethod", + "aaaEp", + "aaaAProvider", + "aaaProviderGroup", + "adcomATsInfoUnit", + "adcomARwi", + "healthARetP", + "healthAInst", + "igmpASnoopPol", + "sysfileEp", + "sysfileRepository", + "sysfileInstance", + "fileARemoteHost", + "fileARemotePath", + "monProtoP", + "monSecAuthP", + "monGroup", + "monSubj", + "monSrc", + "conditionCondP", + "ctrlrDom", + "l2extADomP", + "l2extALNodeP", + "l2extAIfP", + "l2extAInstPSubnet", + "extnwEPg", + "extnwOut", + "extnwDomP", + "extnwAInstPSubnet", + "extnwALNodeP", + "extnwALIfP", + "l3extADomP", + "l3extALNodeP", + "l3extAIfP", + "l3extAMember", + "l3extAInstPSubnet", + "trigSchedWindowP", + "trigInst", + "trigWindow", + "trigSchedWindow", + "trigExecutable", + "trigTriggerable", + "trigSingleTriggerable", + "fvACont", + "fvADeplCont", + "fvL2Dom", + "fvABD", + "fvABDPol", + "fvAEpRetPol", + "fvComp", + "fvATg", + "fvEPgToCollection", + "fvADomP", + "fvEPg", + "fvCEPg", + "fvAREpPCtrct", + "fvDom", + "fvL3Dom", + "fvACtx", + "fvNwEp", + "fvATp", + "fvEp", + "fvPEp", + "fvAEpDef", + "fvTo", + "fvFrom", + "mgmtAZone", + "mgmtAInstPSubnet", + "eqptdiagpTestSet", + "eqptdiagpTestSetBoot", + "eqptdiagpTestSetHealth", + "eqptdiagpTestSetOd", + "eqptdiagpPortTestSetOd", + "eqptdiagpPortTestSetBt", + "eqptdiagpPortTestSetHl", + "eqptdiagpLpTsOd", + "eqptdiagpFpTsOd", + "eqptdiagpCardTestSetOd", + "eqptdiagpSupCTsOd", + "eqptdiagpSysCTsOd", + "eqptdiagpFcTsOd", + "eqptdiagpLcTsOd", + "eqptdiagpExtChCardTsOd", + "eqptdiagpPol", + "eqptdiagpHealthPol", + "eqptdiagpASynthObj", + "oamExec", + "pingAExec", + "tracerouteAExec", + "bgpAf", + "dhcpAddr", + "dhcpNode", + "dhcpResp", + "eqptALPort", + "dbgACRulePCommon", + "dbgacTenantSpaceCmn", + "dbgacEpgCmn", + "dbgacFromEpgCmn", + "dbgacToEpgCmn", + "dbgacFromEpCmn", + "dbgacToEpCmn", + "dbgexpExportP", + "dbgexpNodeStatus", + "spanASrcGrp", + "spanASrc", + "spanASpanLbl", + "spanADest", + "spanAVSrc", + "spanAVSrcGrp", + "spanAVDestGrp", + "spanAVDest", + "svccorePol", + "svccoreACore", + "traceroutepTrP", + "syntheticObject", + "syntheticAContext", + "syntheticATestObj", + "syntheticTLTestObj", + "syntheticCTestObj", + "monExportP", + "ipARouteP", + "ipANexthopP", + "infraFexBlk", + "infraANodeS", + "infraNodeGrp", + "infraPortS", + "infraEPg", + "infraACEPg", + "infraAPEPg", + "infraANode", + "infraAIpP", + "infraProfile", + "infraPolGrp", + "infraAccBaseGrp", + "infraFexGrp", + "infraAccGrp", + "infraLbl", + "infraAPEp", + "infraACEp", + "infraAFunc", + "infraGeNode", + "infraADomP", + "infraDomP", + "infraExP", + "datetimeAPol", + "datetimeANtpAuthKey", + "datetimeANtpProv", + "fvnsAAddrBlk", + "fvnsAEncapBlk", + "fvnsAInstP", + "fvnsAVxlanInstP", + "fvnsAAddrInstP", + "polAttTgt", + "snmpAPol", + "snmpACommunityP", + "snmpAUserP", + "snmpAClientGrpP", + "snmpAClientP", + "snmpACtxP", + "fvDef", + "fvNp", + "fvUp", + "polNToRef", + "polNFromRef", + "polObj", + "polDef", + "polDefRoot", + "polComp", + "polInstr", + "polCont", + "polDom", + "polCtrlr", + "polCompl", + "polComplElem", + "polConsElem", + "polLbl", + "polProvLbl", + "polConsLbl", + "polIf", + "polProvIf", + "polConsIf", + "polRelnHolder", + "polNs", + "polAConfIssues", + "vnsAGraph", + "vnsANode", + "vnsAFuncNode", + "vnsAFolder", + "vnsACCfgRel", + "vnsAParam", + "vnsATerm", + "vnsATermNode", + "vnsAbsTermNode", + "vnsALDevCtx", + "vnsALIfCtx", + "vnsAConn", + "vnsAFuncConn", + "vnsATermConn", + "vnsAConnection", + "vnsAL4L7ServiceFault", + "vnsACCfg", + "vnsALDevIf", + "vnsALDev", + "vnsALIf", + "vnsALDevLIf", + "vnsDevItem", + "fabricAPathIssues", + "conditionSevAsnP", + "fvAStCEp", + "fabricNodeToPolicy", + "aaaADomainRef", + "fvAEpTaskAggr", + "vzToRFltP", + "fvAToBD", + "frmwrkARelDelCont", + "infraDomainToNs", + "infraToAInstP", + "aaaARbacRule", + "statsDebugItem", + "vzInterfaceToCollection", + "spanAToCEp", + "fabricAOOSReln", + "l4AVxlanInstPol", + "fabricVxlanInstPol", + "fabricL1IfPol", + "frmwrkARelDelControl", + "spanACEpDef", + "eptrkEpRslt", + "mcpAIfPol", + "ipmcsnoopRtrIf", + "bfdAf", + "bgpALocalAsnP", + "bgpACtxAfPol", + "l3extADefaultRouteLeakP", + "fvAStIp", + "rtctrlASetRtMetricType", + "vnsAEPpInfo", + "ndAIfPol", + "ndAPfxPol", + "eigrpACtxAfPol", + "eigrpAStubP", + "eigrpAIfP", + "eigrpAExtP", + "l3extAIp", + "fabricProtoConsFrom", + "fabricProtoConsTo", + "fabricAPathS", + "infraAAccBndlGrp", + "fabricNodeToPathOverridePolicy", + "adcomARwiAdvanced", + "fvAClassifier", + "fvACrtrn", + "fvAttr", + "fvAVmAttr", + "fvAIpAttr", + "fvAMacAttr", + "fvAProtoAttr", + "polADependentOn", + "vnsAVRoutingNetworks", + "l3extARouteTagPol", + "nwsAFwPol", + "fabricL4IfPol", + "fvAVip", + "fvAAREpPUpdate", + "conditionSummary", + "polAPrToPol", + "polAObjToPolReln", + "fvACrRule", + "fvASCrtrn", + "fvnsAVlanInstP", + "vzAnyToInterface", + "fvEPgToInterface", + "fabricPodGrp", + "fabricAPodS", + "infraPodGrp", + "vnsAMgmt", + "fabricPolicyGrpToMonitoring", + "plannerIPs", + "plannerAObject", + "plannerAEpg", + "compAPltfmP", + "compAVmmPltfmP", + "compAVmmSecP", + "bgpARRP", + "bgpARtTargetP", + "bgpARtTarget", + "l3extAFabricExtRoutingP", + "fvAFabricExtConnP", + "fvAPodConnP", + "fvAPeeringP", + "fvANode", + "plannerATmpl", + "nwsASrc", + "nwsASyslogSrc", + "throttlerASub", + "qosADscpTrans", + "fvARsToRemote", + "vnsOrchReq", + "vnsOrchResp", + "fcprARs", + "dbgexpTechSupOnDBase", + "infraGeSnNode", + "l3extAConsLbl", + "l3extAProvLbl", + "trigATriggeredWindow", + "qosADppPol", + "bfdAInstPol", + "bfdAIfPol", + "bfdAIfP", + "plannerADomainTmpl", + "plannerAEpgDomain", + "vmmACapObj", + "vmmACapInfo", + "fvARsToRemoteFC", + "rtctrlAMatchCommFactor", + "rtctrlAMatchCommTerm", + "rtctrlAMatchCommRegexTerm", + "rtctrlASetDamp", + "rtctrlASetWeight", + "hvsContE", + "hvsUsegContE", + "compAPvlanP", + "usegAUsegEPg", + "fvAStAttr", + "fvADyAttr", + "mgmtAIp", + "faultARsToRemote", + "analyticsACfgSrv", + "infraAAccGrp", + "infraSpAccGrp", + "infraANodeP", + "infraPortP", + "infraAPathS", + "ipmcsnoopMcSrc", + "ipmcsnoopTgtIf", + "analyticsACluster", + "rtdmcAIfPol", + "rtdmcARtMapPol", + "rtdmcAExtP", + "rtdmcACtxPol", + "rtdmcARPPol", + "rtdmcAAutoRPPol", + "rtdmcABSRPPol", + "rtdmcAStaticRPPol", + "rtdmcAStaticRPEntry", + "rtdmcARPGrpRangePol", + "rtdmcARegTrPol", + "rtdmcAResPol", + "rtdmcAPatPol", + "rtdmcAASMPatPol", + "rtdmcASGRangeExpPol", + "rtdmcASharedRangePol", + "rtdmcASSMPatPol", + "rtdmcASSMRangePol", + "rtdmcABidirPatPol", + "pimAIfP", + "rtdmcARtMapEntry", + "rtdmcAJPFilterPol", + "rtdmcANbrFilterPol", + "rtdmcAMAFilter", + "rtdmcABSRFilter", + "rtdmcAFilterPol", + "fvAEPgPathAtt", + "fvnsAVsanInstP", + "ipmcAIfPol", + "ipmcAStRepPol", + "ipmcAStateLPol", + "ipmcARepPol", + "ipmcACtxPol", + "ipmcASSMXlateP", + "igmpAIfP", + "vmmEpgAggr", + "apPluginName", + "rtdmcAIfPolCont", + "fabricL2PortSecurityPol", + "fcAPinningP", + "fcAPinningLbl", + "fabricAONodeS", + "infraAONodeS", + "analyticsRemoteNode", + "analyticsTarget", + "fabricASubPortBlk", + "bgpARtTargetInstrP", + "hsrpAIfPol", + "hsrpAGroupPol", + "hsrpAGroupP", + "hsrpASecVip", + "hsrpAIfP", + "netflowARecordPol", + "netflowAExporterPol", + "netflowARsInterfaceToMonitor", + "netflowARsMonitorToRecord", + "netflowARsMonitorToExporter", + "netflowAMonitorPol", + "igmpASnoopStaticGroup", + "igmpASnoopAccessGroup", + "netflowAFabExporterPol", + "fabricQinqIfPol", + "orchsEntity", + "orchsElement", + "vnsNATReq", + "vnsLBReq", + "aclACL", + "aclL3ACE", + "apDockerName", + "hostprotASubj", + "macsecAAIfPol", + "macsecAIfPol", + "macsecAAParamPol", + "macsecAParamPol", + "macsecAAKeyChainPol", + "macsecAAKeyPol", + "macsecAKeyChainPol", + "macsecAKeyPol", + "fvAIntersiteConnP", + "fvAIntersiteConnPDef", + "fvASiteConnP", + "coppAProfile", + "coppACustomValues", + "infraNodeS", + "rtctrlASetASPath", + "rtctrlASetASPathASN", + "fvADnsAttr", + "dnsepgFault", + "dnsepgASvrGrp", + "dnsepgAMgmt", + "dnsepgASvr", + "dnsepgADomain", + "ipANexthopEpP", + "vmmInjectedObject", + "poeAIfPol", + "iaclAProfile", + "telemetryAServer", + "snmpATrapFwdServerP", + "dwdmAOptChnlIfPol", + "vzARuleOwner", + "telemetryAServerPol", + "telemetryARemoteServer", + "telemetryAFlowServers", + "telemetryAServerP", + "plannerAEpgFilter", + "callhomeASrc", + "callhomeADest", + "callhomeAGroup", + "fvAEpAnycast", + "tagTag", + "tagAnnotation", + "tagASelector", + "infraFcAccGrp", + "infraAFcAccBndlGrp", + "vsanARsVsanPathAtt", + "vsanARtVsanPathAtt", + "vzSubjectToFilter", + "telemetryAStreamEnable", + "cloudsecASaKeyP", + "rtdmcAInterVRFPol", + "rtdmcAInterVRFEntry", + "cloudsecAControl", + "adepgAResElement", + "adepgAElement", + "adepgACont", + "adepgAOrgUnit", + "adepgEntity", + "adepgContE", + "fvAIdAttr", + "edmObj", + "edmCont", + "edmGroupP", + "edmMgrP", + "edmEntity", + "edmElement", + "edmContE", + "authASvrGroup", + "authASvr", + "authBaseUsrAccP", + "cloudsecASaKeyPLocal", + "cloudsecASaKeyPRemote", + "cloudsecASaKeyStatus", + "cloudsecASaKeyStatusLocal", + "cloudsecASaKeyStatusRemote", + "cloudsecASpKeySt", + "cloudsecACapability", + "aaaRbacAnnotation", + "lacpAEnhancedLagPol", + "compAHvHealth", + "mldASnoopPol", + "fvAExtRoutes", + "fvAExtRoutableRemoteSitePodSubnet", + "fvAEpNlb", + "extdevSDWanASlaPol", + "eigrpAAuthIfP", + "fvAAKeyChainPol", + "fvAAKeyPol", + "fvAKeyChainPol", + "fvAKeyPol", + "fvSyntheticIp", + "edmACapFlags", + "cloudABgpPeerP", + "cloudABgpAsP", + "cloudARouterP", + "cloudAIntNetworkP", + "cloudAExtNetworkP", + "cloudAHostRouterPol", + "cloudAHostBootstrapPol", + "cloudAVpnGwPol", + "cloudAHostIfP", + "cloudALoopbackIfP", + "cloudAL3IfP", + "cloudAIpv4AddrP", + "cloudAL3TunnelIfP", + "cloudAIpSecTunnelIfP", + "cloudAOspfIfP", + "cloudAOspfAreaP", + "cloudACtxProfile", + "cloudACidr", + "cloudASubnet", + "cloudAAwsLogGroup", + "cloudAAwsFlowLogPol", + "cloudAProvider", + "cloudAAwsProvider", + "cloudAAEPg", + "cloudAEPSelector", + "cloudAEPSelectorDef", + "cloudADomP", + "genericsARule", + "ipsecAIsakmpPhase1Pol", + "ipsecAIsakmpPhase2Pol", + "resolutionARsToRemote", + "cloudtemplateASubnetPool", + "fvAACrtrn", + "fvAUsegAssocBD", + "cloudALDev", + "cloudAListener", + "cloudAPool", + "cloudAListenerRule", + "cloudARuleCondition", + "cloudARuleAction", + "cloudACertStore", + "cloudACertificate", + "arpAIfPol", + "compNameIdentEntity", + "edmAOperCont", + "edmAStatsCont", + "cloudASvcPol", + "hcloudATgStats", + "statsANWStatsObj", + "statsATunnel", + "cloudAController", + "cloudAApicSubnet", + "cloudAApicSubnetPool", + "cloudABaseEPg", + "cloudASvcEPg", + "statsAALbStats", + "mldASnoopStaticGroup", + "mldASnoopAccessGroup", + "datetimeANtpIFFKey", + "hcloudRouterStateOper", + "vmmAUplinkP", + "vmmAUplinkPCont", + "cloudAAFilter", + "fvASDWanPrefixTaskAggr", + "cloudAProvResP", + "bfdAMhInstPol", + "bfdAMhIfPol", + "fvAEPSelector", + "ptpAACfg", + "ptpACfg", + "fabricL2BDPol", + "rtdmcABDPol", + "rtdmcABDFilter", + "ptpAProfile", + "mdpADomP", + "mdpADomainPeeringPol", + "mdpAPeeringDomain", + "mdpANodeP", + "mdpAClassId", + "mdpATenant", + "mplsAExtP", + "mplsAIfP", + "mplsALabelPol", + "mplsANodeSidP", + "qosAMplsIngressRule", + "qosMplsMarking", + "qosAMplsEgressRule", + "cloudAGatewayRouterP", + "cloudATransitHubGwPol", + "cloudAL3IntTunnelIfP", + "cloudABdiId", + "mplsASrgbLabelPol", + "bfdAMhNodePol", + "bfdANodeP", + "leakASubnet", + "rtctrlASetNhUnchanged", + "mdpAService", + "cloudALIf", + "cloudAParamPol", + "cloudAComputePol", + "cloudAMgmtPol", + "cloudANWParams", + "fvRtScopeFrom", + "cloudACtxUnderlayP", + "cloudAHealthProbe", + "leakARouteCont", + "netflowAVmmExporterPol", + "cloudABrownfield", + "cloudAMapping", + "cloudASelectedEP", + "statsANlbStats", + "mdpAEntity", + "dbgANodeInst", + "snmpACtrlrInst", + "cloudAFrontendIPv4Addr", + "qosAUburst", + "telemetryAFteEvents", + "telemetryAFteEventsTcpFlags", + "telemetryAFteEventsExt", + "cloudACloudSvcEPg", + "hcloudASvcResBase", + "bgpADomainIdBase", + "fvAEpTag", + "bgpASiteOfOriginP", + "fvAEPSelectorDef", + "vmmCFaultInfo", + "synceAAIfPol", + "synceAIfPol", + "rtctrlASetRedistMultipath", + "cloudANextHopIp", + "cloudAVrfRouteLeakPol", + "hcloudALeakedPfx", + "leakAPrefix", + "fvARogueExceptionMac", + "bfdAMicroBfdP", + "hcloudAIntPfx", + "hcloudAExtPfx", + "cloudAVpnNetworkP", + "snmpUser", + "cloudAVirtualWanP", + "fvAFBRGroup", + "fvAFBRoute", + "fvAFBRMember", + "rtctrlASetPolicyTag", + "fvACtxRtSummPol", + "fvARtSummSubnet", + "fvAIntraVrfFabricImpRtctrlP", + "fvAFabricExpRtctrlP", + "cloudAVip", + "rtctrlAMatchAsPathRegexTerm", + "cloudAGcpFlowLogPol", + "statsAGcpNWStatsObj", + "cloudABfdPol", + "cloudABfdP", + "bgpACtxAddlPathPol", + "xcvrOpticsIfPol", + "xcvrOpticsFabIfPol", + "hostprotANamespace", + "fvARouteDeployP", + "rtdmcACSWPol", + "rtdmcACSWEntry", + "analyticsTo", + "analyticsFrom", + "dmemotltestAbsObject", + "bgpAsnmpBgpTraps", + "l3extARogueExceptionMac", + "l3extARogueExceptionMacGroup", + "vzAFiltPZEntry", +] diff --git a/ansible_collections/cisco/aci/plugins/module_utils/constants.py b/ansible_collections/cisco/aci/plugins/module_utils/constants.py index 165b63431..26818ff64 100644 --- a/ansible_collections/cisco/aci/plugins/module_utils/constants.py +++ b/ansible_collections/cisco/aci/plugins/module_utils/constants.py @@ -97,4 +97,340 @@ EP_LOOP_PROTECTION_ACTION_MAPPING = {"bd": "bd-learn-disable", "port": "port-dis FABRIC_POD_SELECTOR_TYPE_MAPPING = dict(all="ALL", range="range") -TLS_MAPPING = {"tls_v1.0": "TLSv1", "tls_v1.1": "TLSv1.1", "tls_v1.2": "TLSv1.2"} +OPFLEX_TLS_MAPPING = {"tls_v1.0": "TLSv1", "tls_v1.1": "TLSv1.1", "tls_v1.2": "TLSv1.2"} + +HTTP_TLS_MAPPING = {"tls_v1.0": "TLSv1", "tls_v1.1": "TLSv1.1", "tls_v1.2": "TLSv1.2", "tls_v1.3": "TLSv1.3"} + +ACI_ACCESS_SWITCH_POLICY_GROUP_CLASS_MAPPING = dict( + spine=dict( + class_name="infraSpineAccNodePGrp", + rn="infra/funcprof/spaccnodepgrp-{0}", + copp_pre_filter_policy=dict(class_name="infraRsIaclSpineProfile", tn_name="tnIaclSpineProfileName"), + bfd_ipv4_policy=dict(class_name="infraRsSpineBfdIpv4InstPol", tn_name="tnBfdIpv4InstPolName"), + bfd_ipv6_policy=dict(class_name="infraRsSpineBfdIpv6InstPol", tn_name="tnBfdIpv6InstPolName"), + copp_policy=dict(class_name="infraRsSpineCoppProfile", tn_name="tnCoppSpineProfileName"), + cdp_policy=dict(class_name="infraRsSpinePGrpToCdpIfPol", tn_name="tnCdpIfPolName"), + lldp_policy=dict(class_name="infraRsSpinePGrpToLldpIfPol", tn_name="tnLldpIfPolName"), + usb_configuration_policy=dict(class_name="infraRsSpineTopoctrlUsbConfigProfilePol", tn_name="tnTopoctrlUsbConfigProfilePolName"), + ), + leaf=dict( + class_name="infraAccNodePGrp", + rn="infra/funcprof/accnodepgrp-{0}", + copp_pre_filter_policy=dict(class_name="infraRsIaclLeafProfile", tn_name="tnIaclLeafProfileName"), + bfd_ipv4_policy=dict(class_name="infraRsBfdIpv4InstPol", tn_name="tnBfdIpv4InstPolName"), + bfd_ipv6_policy=dict(class_name="infraRsBfdIpv6InstPol", tn_name="tnBfdIpv6InstPolName"), + copp_policy=dict(class_name="infraRsLeafCoppProfile", tn_name="tnCoppLeafProfileName"), + cdp_policy=dict(class_name="infraRsLeafPGrpToCdpIfPol", tn_name="tnCdpIfPolName"), + lldp_policy=dict(class_name="infraRsLeafPGrpToLldpIfPol", tn_name="tnLldpIfPolName"), + usb_configuration_policy=dict(class_name="infraRsLeafTopoctrlUsbConfigProfilePol", tn_name="tnTopoctrlUsbConfigProfilePolName"), + ), +) + +PIM_SETTING_CONTROL_STATE_MAPPING = {"fast": "fast-conv", "strict": "strict-rfc-compliant"} + +ACI_CLASS_MAPPING = dict( + consumer={ + "class": "fvRsCons", + "rn": "rscons-", + "name": "tnVzBrCPName", + }, + provider={ + "class": "fvRsProv", + "rn": "rsprov-", + "name": "tnVzBrCPName", + }, + taboo={ + "class": "fvRsProtBy", + "rn": "rsprotBy-", + "name": "tnVzTabooName", + }, + interface={ + "class": "fvRsConsIf", + "rn": "rsconsIf-", + "name": "tnVzCPIfName", + }, + intra_epg={ + "class": "fvRsIntraEpg", + "rn": "rsintraEpg-", + "name": "tnVzBrCPName", + }, +) + +PROVIDER_MATCH_MAPPING = dict( + all="All", + at_least_one="AtleastOne", + at_most_one="AtmostOne", + none="None", +) + +CONTRACT_LABEL_MAPPING = dict( + consumer="vzConsLbl", + provider="vzProvLbl", +) + +SUBJ_LABEL_MAPPING = dict( + consumer="vzConsSubjLbl", + provider="vzProvSubjLbl", +) + +SUBJ_LABEL_RN = dict( + consumer="conssubjlbl-", + provider="provsubjlbl-", +) + +MATCH_ACTION_RULE_SET_METRIC_TYPE_MAPPING = {"ospf_type_1": "ospf-type1", "ospf_type_2": "ospf-type2", "": ""} + +MATCH_EIGRP_INTERFACE_POLICY_DELAY_UNIT_MAPPING = dict(picoseconds="pico", tens_of_microseconds="tens-of-micro") + +MATCH_EIGRP_INTERFACE_POLICY_CONTROL_STATE_MAPPING = dict(bfd="bfd", nexthop_self="nh-self", passive="passive", split_horizon="split-horizon") + +MATCH_TARGET_COS_MAPPING = { + "background": "0", + "best_effort": "1", + "excellent_effort": "2", + "critical_applications": "3", + "video": "4", + "voice": "5", + "internetwork_control": "6", + "network_control": "7", + "unspecified": "unspecified", +} + +MATCH_PIM_INTERFACE_POLICY_CONTROL_STATE_MAPPING = dict(multicast_domain_boundary="border", strict_rfc_compliant="strict-rfc-compliant", passive="passive") + +MATCH_PIM_INTERFACE_POLICY_AUTHENTICATION_TYPE_MAPPING = dict(none="none", md5_hmac="ah-md5") + +MATCH_COLLECT_NETFLOW_RECORD_MAPPING = dict( + bytes_counter="count-bytes", + pkts_counter="count-pkts", + pkt_disposition="pkt-disp", + sampler_id="sampler-id", + source_interface="src-intf", + tcp_flags="tcp-flags", + first_pkt_timestamp="ts-first", + recent_pkt_timestamp="ts-recent", +) + +MATCH_MATCH_NETFLOW_RECORD_MAPPING = dict( + destination_ipv4_v6="dst-ip", + destination_ipv4="dst-ipv4", + destination_ipv6="dst-ipv6", + destination_mac="dst-mac", + destination_port="dst-port", + ethertype="ethertype", + ip_protocol="proto", + source_ipv4_v6="src-ip", + source_ipv4="src-ipv4", + source_ipv6="src-ipv6", + source_mac="src-mac", + source_port="src-port", + ip_tos="tos", + unspecified="unspecified", + vlan="vlan", +) + +MATCH_SOURCE_IP_TYPE_NETFLOW_EXPORTER_MAPPING = dict( + custom_source_ip="custom-src-ip", + inband_management_ip="inband-mgmt-ip", + out_of_band_management_ip="oob-mgmt-ip", + ptep="ptep", +) + +ECC_CURVE = {"P256": "prime256v1", "P384": "secp384r1", "P521": "secp521r1", "none": "none"} + +THROTTLE_UNIT = dict(requests_per_second="r/s", requests_per_minute="r/m") + +SSH_CIPHERS = dict( + aes128_ctr="aes128-ctr", + aes192_ctr="aes192-ctr", + aes256_ctr="aes256-ctr", + aes128_gcm="aes128-gcm@openssh.com", + aes256_gcm="aes256-gcm@openssh.com", + chacha20="chacha20-poly1305@openssh.com", +) + +SSH_MACS = dict( + sha1="hmac-sha1", + sha2_256="hmac-sha2-256", + sha2_512="hmac-sha2-512", + sha2_256_etm="hmac-sha2-256-etm@openssh.com", + sha2_512_etm="hmac-sha2-512-etm@openssh.com", +) + +KEX_ALGORITHMS = dict( + dh_sha1="diffie-hellman-group14-sha1", + dh_sha256="diffie-hellman-group14-sha256", + dh_sha512="diffie-hellman-group16-sha512", + curve_sha256="curve25519-sha256", + curve_sha256_libssh="curve25519-sha256@libssh.org", + ecdh_256="ecdh-sha2-nistp256", + ecdh_384="ecdh-sha2-nistp384", + ecdh_521="ecdh-sha2-nistp521", +) + +USEG_ATTRIBUTE_MAPPING = dict( + ip=dict(attribute_type="ip", attribute_class="fvIpAttr", rn_format="ipattr-{0}"), + mac=dict(attribute_type="mac", attribute_class="fvMacAttr", rn_format="macattr-{0}"), + dns=dict(attribute_type="dns", attribute_class="fvDnsAttr", rn_format="dnsattr-{0}"), + ad_group=dict(attribute_type="ad", attribute_class="fvIdGroupAttr", rn_format="idgattr-[{0}]"), + vm_custom_attr=dict(attribute_type="custom-label", attribute_class="fvVmAttr", rn_format="vmattr-{0}"), + vm_vmm_domain=dict(attribute_type="domain", attribute_class="fvVmAttr", rn_format="vmattr-{0}"), + vm_operating_system=dict(attribute_type="guest-os", attribute_class="fvVmAttr", rn_format="vmattr-{0}"), + vm_hypervisor_id=dict(attribute_type="hv", attribute_class="fvVmAttr", rn_format="vmattr-{0}"), + vm_datacenter=dict(attribute_type="rootContName", attribute_class="fvVmAttr", rn_format="vmattr-{0}"), + vm_id=dict(attribute_type="vm", attribute_class="fvVmAttr", rn_format="vmattr-{0}"), + vm_name=dict(attribute_type="vm-name", attribute_class="fvVmAttr", rn_format="vmattr-{0}"), + vm_folder=dict(attribute_type="vm-folder", attribute_class="fvVmAttr", rn_format="vmattr-{0}"), + vm_folder_path=dict(attribute_type="vmfolder-path", attribute_class="fvVmAttr", rn_format="vmattr-{0}"), + vm_vnic=dict(attribute_type="vnic", attribute_class="fvVmAttr", rn_format="vmattr-{0}"), + vm_tag=dict(attribute_type="tag", attribute_class="fvVmAttr", rn_format="vmattr-{0}"), +) + +OPERATOR_MAPPING = dict(equals="equals", contains="contains", starts_with="startsWith", ends_with="endsWith") + +MATCH_STORM_CONTROL_POLICY_TYPE_MAPPING = dict(all_types="Invalid", unicast_broadcast_multicast="Valid") + +POLICY_LABEL_COLORS = [ + "alice_blue", + "antique_white", + "aqua", + "aquamarine", + "azure", + "beige", + "bisque", + "black", + "blanched_almond", + "blue", + "blue_violet", + "brown", + "burlywood", + "cadet_blue", + "chartreuse", + "chocolate", + "coral", + "cornflower_blue", + "cornsilk", + "crimson", + "cyan", + "dark_blue", + "dark_cyan", + "dark_goldenrod", + "dark_gray", + "dark_green", + "dark_khaki", + "dark_magenta", + "dark_olive_green", + "dark_orange", + "dark_orchid", + "dark_red", + "dark_salmon", + "dark_sea_green", + "dark_slate_blue", + "dark_slate_gray", + "dark_turquoise", + "dark_violet", + "deep_pink", + "deep_sky_blue", + "dim_gray", + "dodger_blue", + "fire_brick", + "floral_white", + "forest_green", + "fuchsia", + "gainsboro", + "ghost_white", + "gold", + "goldenrod", + "gray", + "green", + "green_yellow", + "honeydew", + "hot_pink", + "indian_red", + "indigo", + "ivory", + "khaki", + "lavender", + "lavender_blush", + "lawn_green", + "lemon_chiffon", + "light_blue", + "light_coral", + "light_cyan", + "light_goldenrod_yellow", + "light_gray", + "light_green", + "light_pink", + "light_salmon", + "light_sea_green", + "light_sky_blue", + "light_slate_gray", + "light_steel_blue", + "light_yellow", + "lime", + "lime_green", + "linen", + "magenta", + "maroon", + "medium_aquamarine", + "medium_blue", + "medium_orchid", + "medium_purple", + "medium_sea_green", + "medium_slate_blue", + "medium_spring_green", + "medium_turquoise", + "medium_violet_red", + "midnight_blue", + "mint_cream", + "misty_rose", + "moccasin", + "navajo_white", + "navy", + "old_lace", + "olive", + "olive_drab", + "orange", + "orange_red", + "orchid", + "pale_goldenrod", + "pale_green", + "pale_turquoise", + "pale_violet_red", + "papaya_whip", + "peachpuff", + "peru", + "pink", + "plum", + "powder_blue", + "purple", + "red", + "rosy_brown", + "royal_blue", + "saddle_brown", + "salmon", + "sandy_brown", + "sea_green", + "seashell", + "sienna", + "silver", + "sky_blue", + "slate_blue", + "slate_gray", + "snow", + "spring_green", + "steel_blue", + "tan", + "teal", + "thistle", + "tomato", + "turquoise", + "violet", + "wheat", + "white", + "white_smoke", + "yellow", + "yellow_green", +] + +MATCH_ACCESS_POLICIES_SELECTOR_TYPE = dict(range="range", all="ALL") diff --git a/ansible_collections/cisco/aci/plugins/modules/aci_aaa_certificate_authority.py b/ansible_collections/cisco/aci/plugins/modules/aci_aaa_certificate_authority.py new file mode 100644 index 000000000..673515185 --- /dev/null +++ b/ansible_collections/cisco/aci/plugins/modules/aci_aaa_certificate_authority.py @@ -0,0 +1,290 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- + +# Copyright: (c) 2024, Akini Ross (@akinross) +# 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_certificate_authority +short_description: Manage AAA Certificate Authorities (pki:TP) +description: +- Manage AAA Certificate Authorities on Cisco ACI fabrics. +options: + name: + description: + - The name of the Certificate Authority. + type: str + aliases: [ certificate_authority, cert_authority, cert_authority_name, certificate_authority_name ] + cloud_tenant: + description: + - The name of the cloud tenant. + - This attribute is only applicable for Cloud APIC. + type: str + aliases: [ tenant, tenant_name ] + description: + description: + - The description of the Certificate Authority. + type: str + aliases: [ descr ] + certificate_chain: + description: + - The PEM-encoded chain of trust from the trustpoint to a trusted root authority. + type: str + aliases: [ cert_data, certificate_data, cert, certificate ] + 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 +- cisco.aci.annotation +- cisco.aci.owner + +notes: +- The C(cloud_tenant) used must exist before using this module in your playbook. + The M(cisco.aci.aci_tenant) module can be used for this. +seealso: +- name: APIC Management Information Model reference + description: More information about the internal APIC class B(pki:TP). + link: https://developer.cisco.com/docs/apic-mim-ref/ +author: +- Akini Ross (@akinross) +""" + +EXAMPLES = r""" +- name: Create a Certificate Authority + cisco.aci.aci_aaa_certificate_authority: + host: apic + username: admin + password: SomeSecretPassword + name: example_authority + certificate_chain: '{{ lookup("file", "pki/example_authority.crt") }}' + state: present + delegate_to: localhost + +- name: Query a Certificate Authority + cisco.aci.aci_aaa_certificate_authority: + host: apic + username: admin + password: SomeSecretPassword + name: example_authority + state: query + delegate_to: localhost + register: query_result + +- name: Query all Certificate Authorities + cisco.aci.aci_aaa_certificate_authority: + host: apic + username: admin + password: SomeSecretPassword + state: query + delegate_to: localhost + register: query_result + +- name: Delete a Certificate Authority + cisco.aci.aci_aaa_certificate_authority: + host: apic + username: admin + password: SomeSecretPassword + name: example_authority + 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: '' +sent: + description: The actual/minimal configuration pushed to the APIC + returned: info + type: list + sample: + { + "fvTenant": { + "attributes": { + "descr": "Production environment" + } + } + } +previous: + description: The original configuration from the APIC before the module has started + returned: info + type: list + sample: + [ + { + "fvTenant": { + "attributes": { + "descr": "Production", + "dn": "uni/tn-production", + "name": "production", + "nameAlias": "", + "ownerKey": "", + "ownerTag": "" + } + } + } + ] +proposed: + description: The assembled configuration from the user-provided parameters + returned: info + type: dict + sample: + { + "fvTenant": { + "attributes": { + "descr": "Production environment", + "name": "production" + } + } + } +filter_string: + description: The filter string used for the request + returned: failure or debug + type: str + sample: ?rsp-prop-include=config-only +method: + description: The HTTP method used for the request to the APIC + returned: failure or debug + type: str + sample: POST +response: + description: The HTTP response from the APIC + returned: failure or debug + type: str + sample: OK (30 bytes) +status: + description: The HTTP status from the APIC + returned: failure or debug + type: int + sample: 200 +url: + description: The HTTP url used for the request to the APIC + returned: failure or debug + type: str + sample: https://10.11.12.13/api/mo/uni/tn-production.json +""" + +from ansible.module_utils.basic import AnsibleModule +from ansible_collections.cisco.aci.plugins.module_utils.aci import ACIModule, aci_argument_spec, aci_annotation_spec, aci_owner_spec + + +def main(): + argument_spec = aci_argument_spec() + argument_spec.update(aci_annotation_spec()) + argument_spec.update(aci_owner_spec()) + argument_spec.update( + name=dict( + type="str", aliases=["certificate_authority", "cert_authority", "cert_authority_name", "certificate_authority_name"] + ), # Not required for querying all objects + cloud_tenant=dict(type="str", aliases=["tenant", "tenant_name"]), + description=dict(type="str", aliases=["descr"]), + certificate_chain=dict(type="str", aliases=["cert_data", "certificate_data", "cert", "certificate"]), + 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", "certificate_chain"]], + ], + ) + + name = module.params.get("name") + cloud_tenant = module.params.get("cloud_tenant") + description = module.params.get("description") + certificate_chain = module.params.get("certificate_chain") + state = module.params.get("state") + name_alias = module.params.get("name_alias") + + aci = ACIModule(module) + aci_class = "pkiTP" + parent_class = "cloudCertStore" if cloud_tenant else "pkiEp" + parent_rn = "tn-{0}/certstore".format(cloud_tenant) if cloud_tenant else "userext/pkiext" + + aci.construct_url( + root_class=dict( + aci_class=parent_class, + aci_rn=parent_rn, + ), + subclass_1=dict( + aci_class=aci_class, + aci_rn="tp-{0}".format(name), + module_object=name, + target_filter={"name": name}, + ), + ) + aci.get_existing() + + if state == "present": + aci.payload( + aci_class=aci_class, + class_config=dict( + name=name, + descr=description, + certChain=certificate_chain, + nameAlias=name_alias, + ), + ) + + aci.get_diff(aci_class=aci_class) + + # Only wrap the payload in parent class if cloud_tenant is set to avoid apic error + aci.post_config(parent_class=parent_class if cloud_tenant else None) + + elif state == "absent": + aci.delete_config() + + aci.exit_json() + + +if __name__ == "__main__": + main() diff --git a/ansible_collections/cisco/aci/plugins/modules/aci_aaa_key_ring.py b/ansible_collections/cisco/aci/plugins/modules/aci_aaa_key_ring.py new file mode 100644 index 000000000..2aa2649c7 --- /dev/null +++ b/ansible_collections/cisco/aci/plugins/modules/aci_aaa_key_ring.py @@ -0,0 +1,339 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- + +# Copyright: (c) 2024, Akini Ross (@akinross) +# 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_key_ring +short_description: Manage AAA Key Rings (pki:KeyRing) +description: +- Manage AAA Key Rings on Cisco ACI fabrics. +options: + name: + description: + - The name of the Key Ring. + type: str + aliases: [ key_ring, key_ring_name ] + cloud_tenant: + description: + - The name of the cloud tenant. + - This attribute is only applicable for Cloud APIC. + type: str + aliases: [ tenant, tenant_name ] + description: + description: + - The description of the Key Ring. + type: str + aliases: [ descr ] + certificate: + description: + - The certificate of the Key Ring. + - The certificate contains a public key and signed information for verifying the identity. + type: str + aliases: [ cert_data, certificate_data, cert ] + modulus: + description: + - The modulus is the length of the key in bits. + type: int + choices: [ 512, 1024, 1536, 2048 ] + certificate_authority: + description: + - The name of the Certificate Authority. + type: str + aliases: [ cert_authority, cert_authority_name, certificate_authority_name ] + key: + description: + - The private key for the certificate. + type: str + key_type: + description: + - The type of the private key. + - This attribute is only configurable in ACI versions 6.0(2h) and above. + type: str + choices: [ rsa, ecc ] + ecc_curve: + description: + - The curve of the private key. + - This attribute requires O(key_type=ecc). + - This attribute is only configurable in ACI versions 6.0(2h) and above. + type: str + choices: [ P256, P384, P521, none ] + aliases: [ curve ] + 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 +- cisco.aci.annotation +- cisco.aci.owner + +notes: +- The C(cloud_tenant) used must exist before using this module in your playbook. + The M(cisco.aci.aci_tenant) module can be used for this. +seealso: +- name: APIC Management Information Model reference + description: More information about the internal APIC class B(pki:KeyRing). + link: https://developer.cisco.com/docs/apic-mim-ref/ +author: +- Akini Ross (@akinross) +""" + +EXAMPLES = r""" +- name: Create a Key Ring + cisco.aci.aci_aaa_key_ring: + host: apic + username: admin + password: SomeSecretPassword + name: example_key_ring + certificate: '{{ lookup("file", "pki/example_certificate.crt") }}' + modulus: 2048 + certificate_authority: example_certificate_authority + key: '{{ lookup("file", "pki/example_key.key") }}' + state: present + delegate_to: localhost + +- name: Query a Key Ring + cisco.aci.aci_aaa_key_ring: + host: apic + username: admin + password: SomeSecretPassword + name: example_key_ring + state: query + delegate_to: localhost + register: query_result + +- name: Query all Certificate Authorities + cisco.aci.aci_aaa_key_ring: + host: apic + username: admin + password: SomeSecretPassword + state: query + delegate_to: localhost + register: query_result + +- name: Delete a Key Ring + cisco.aci.aci_aaa_key_ring: + host: apic + username: admin + password: SomeSecretPassword + name: example_key_ring + 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: '' +sent: + description: The actual/minimal configuration pushed to the APIC + returned: info + type: list + sample: + { + "fvTenant": { + "attributes": { + "descr": "Production environment" + } + } + } +previous: + description: The original configuration from the APIC before the module has started + returned: info + type: list + sample: + [ + { + "fvTenant": { + "attributes": { + "descr": "Production", + "dn": "uni/tn-production", + "name": "production", + "nameAlias": "", + "ownerKey": "", + "ownerTag": "" + } + } + } + ] +proposed: + description: The assembled configuration from the user-provided parameters + returned: info + type: dict + sample: + { + "fvTenant": { + "attributes": { + "descr": "Production environment", + "name": "production" + } + } + } +filter_string: + description: The filter string used for the request + returned: failure or debug + type: str + sample: ?rsp-prop-include=config-only +method: + description: The HTTP method used for the request to the APIC + returned: failure or debug + type: str + sample: POST +response: + description: The HTTP response from the APIC + returned: failure or debug + type: str + sample: OK (30 bytes) +status: + description: The HTTP status from the APIC + returned: failure or debug + type: int + sample: 200 +url: + description: The HTTP url used for the request to the APIC + returned: failure or debug + type: str + sample: https://10.11.12.13/api/mo/uni/tn-production.json +""" + +from ansible.module_utils.basic import AnsibleModule +from ansible_collections.cisco.aci.plugins.module_utils.aci import ACIModule, aci_argument_spec, aci_annotation_spec, aci_owner_spec +from ansible_collections.cisco.aci.plugins.module_utils.constants import ECC_CURVE + + +def main(): + argument_spec = aci_argument_spec() + argument_spec.update(aci_annotation_spec()) + argument_spec.update(aci_owner_spec()) + argument_spec.update( + name=dict(type="str", aliases=["key_ring", "key_ring_name"]), # Not required for querying all objects + cloud_tenant=dict(type="str", aliases=["tenant_name", "tenant"]), + description=dict(type="str", aliases=["descr"]), + certificate=dict(type="str", aliases=["cert_data", "certificate_data", "cert"]), + modulus=dict(type="int", choices=[512, 1024, 1536, 2048]), + certificate_authority=dict(type="str", aliases=["cert_authority", "cert_authority_name", "certificate_authority_name"]), + key=dict(type="str", no_log=True), + key_type=dict(type="str", choices=["rsa", "ecc"]), + ecc_curve=dict(type="str", choices=["P256", "P384", "P521", "none"], aliases=["curve"]), + 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"]], + ], + ) + + name = module.params.get("name") + cloud_tenant = module.params.get("cloud_tenant") + description = module.params.get("description") + certificate = module.params.get("certificate") + modulus = "mod{0}".format(module.params.get("modulus")) if module.params.get("modulus") else None + certificate_authority = module.params.get("certificate_authority") + key = module.params.get("key") + key_type = module.params.get("key_type") + ecc_curve = ECC_CURVE[module.params.get("ecc_curve")] if module.params.get("ecc_curve") else None + state = module.params.get("state") + name_alias = module.params.get("name_alias") + + aci = ACIModule(module) + aci_class = "pkiKeyRing" + parent_class = "cloudCertStore" if cloud_tenant else "pkiEp" + parent_rn = "tn-{0}/certstore".format(cloud_tenant) if cloud_tenant else "userext/pkiext" + + aci.construct_url( + root_class=dict( + aci_class=parent_class, + aci_rn=parent_rn, + ), + subclass_1=dict( + aci_class=aci_class, + aci_rn="keyring-{0}".format(name), + module_object=name, + target_filter={"name": name}, + ), + ) + aci.get_existing() + + if state == "present": + class_config = dict( + name=name, + descr=description, + cert=certificate, + modulus=modulus, + tp=certificate_authority, + nameAlias=name_alias, + key=key, + ) + + if key_type: + class_config["keyType"] = key_type.upper() + + if ecc_curve: + class_config["eccCurve"] = ecc_curve + + aci.payload(aci_class=aci_class, class_config=class_config) + + aci.get_diff(aci_class=aci_class, required_properties=dict(name=name) if cloud_tenant else None) + + # Only wrap the payload in parent class if cloud_tenant is set to avoid apic error + aci.post_config(parent_class=parent_class if cloud_tenant else None) + + elif state == "absent": + aci.delete_config() + + aci.exit_json() + + +if __name__ == "__main__": + main() diff --git a/ansible_collections/cisco/aci/plugins/modules/aci_aaa_security_default_settings.py b/ansible_collections/cisco/aci/plugins/modules/aci_aaa_security_default_settings.py new file mode 100644 index 000000000..4ba18fded --- /dev/null +++ b/ansible_collections/cisco/aci/plugins/modules/aci_aaa_security_default_settings.py @@ -0,0 +1,531 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- + +# Copyright: (c) 2024, Akini Ross (@akinross) +# 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_security_default_settings +short_description: Manage AAA Key Rings (pki:Ep) +description: +- Manage AAA Key Rings on Cisco ACI fabrics. +options: + password_strength_check: + description: + - Enable password strength check. + - Use C(true) to enable and C(false) to disable. + - The APIC defaults to C(true) when unset during creation. + type: bool + password_strength_profile: + description: + - The password strength profile (aaa:PwdStrengthProfile). + type: dict + suboptions: + enable: + description: + - Enable or disable password strength profile. + - Use C(true) to enable and C(false) to disable. + type: bool + required: true + type: + description: + - The type of the password strength profile. + - The APIC defaults to C(any_three) when unset during creation. + type: str + choices: [ custom, any_three ] + min_length: + description: + - The minimum length of the password. + - The APIC defaults to C(8) when unset during creation. + type: int + aliases: [ minimum_length, min ] + max_length: + description: + - The maximum length of the password. + - The APIC defaults to C(64) when unset during creation. + type: int + aliases: [ maximum_length, max ] + class_flags: + description: + - The class flags of the password strength profile. + - At least 3 class flags must be specified. + - This attribute is only applicable when type is set to O(password_strength_profile.type=custom). + - The APIC defaults to C(digits,lowercase,uppercase) when unset during creation. + type: list + elements: str + choices: [ digits, lowercase, specialchars, uppercase ] + aliases: [ flags ] + password_change: + description: + - The password change interval (aaa:PwdProfile). + type: dict + suboptions: + enable: + description: + - Enforce password change interval. + - Use C(true) to enable and C(false) to disable. + - The APIC defaults to C(true) when unset during creation. + type: bool + interval: + description: + - The password change interval in hours. + - The APIC defaults to C(48) when unset during creation. + type: int + allowed_changes: + description: + - The number of changes allowed within the change interval. + - The APIC defaults to C(2) when unset during creation. + type: int + minimum_period: + description: + - The minimum period between password changes in hours. + - The APIC defaults to C(24) when unset during creation. + type: int + aliases: [ minimum_period_between_password_changes, min_period ] + history_storage_amount: + description: + - The number of recent user passwords to store. + - The APIC defaults to C(5) when unset during creation. + type: int + aliases: [ history, amount ] + lockout: + description: + - Lockout behaviour after multiple failed login attempts (aaa:BlockLoginProfile). + type: dict + suboptions: + enable: + description: + - Enable lockout behaviour. + - Use C(true) to enable and C(false) to disable. + - The APIC defaults to C(false) when unset during creation. + type: bool + max_attempts: + description: + - The maximum number of failed attempts before user is locked out. + - The APIC defaults to C(5) when unset during creation. + type: int + aliases: [ max_failed_attempts, failed_attempts, attempts ] + window: + description: + - The time period in which consecutive attempts were failed in minutes. + - The APIC defaults to C(5) when unset during creation. + type: int + aliases: [ max_failed_attempts_window, failed_attempts_window ] + duration: + description: + - The duration of lockout in minutes. + - The APIC defaults to C(60) when unset during creation. + type: int + web_token: + description: + - The web token related configuration (pki:WebTokenData). + type: dict + suboptions: + timeout: + description: + - The web token timeout in seconds. + - The APIC defaults to C(600) when unset during creation. + type: int + idle_timeout: + description: + - The web/console (SSH/Telnet) session idle timeout in seconds. + - The APIC defaults to C(1200) when unset during creation. + type: int + aliases: [ session_idle_timeout ] + validity_period: + description: + - The maximum validity period in hours. + - The APIC defaults to C(24) when unset during creation. + type: int + aliases: [ maximum_validity_period ] + refresh: + description: + - Include refresh in session records. + - Use C(true) to include and C(false) to exclude. + - The APIC defaults to C(false) 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: [ 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 +- cisco.aci.annotation +- cisco.aci.owner + +seealso: +- name: APIC Management Information Model reference + description: More information about the internal APIC class B(pki:Ep). + link: https://developer.cisco.com/docs/apic-mim-ref/ +author: +- Akini Ross (@akinross) +""" + +EXAMPLES = r""" +- name: Set AAA Security Default Settings + cisco.aci.aci_aaa_security_default_settings: + host: apic + username: admin + password: SomeSecretPassword + password_strength_check: true + password_strength_profile: + enable: true + type: custom + min_length: 10 + max_length: 60 + class_flags: + - digits + - lowercase + - specialchars + - uppercase + password_change: + enable: true + interval: 49 + allowed_changes: 6 + minimum_period_between_password_changes: 25 + history_storage_amount: 6 + lockout: + enable: true + max_attempts: 6 + window: 6 + duration: 61 + web_token: + timeout: 601 + idle_timeout: 1201 + validity_period: 23 + refresh: true + state: present + delegate_to: localhost + +- name: Set AAA Security Default Settings to Default Values + cisco.aci.aci_aaa_security_default_settings: + host: apic + username: admin + password: SomeSecretPassword + password_strength_check: true + password_strength_profile: + enable: false + password_change: + enable: true + interval: 48 + allowed_changes: 2 + minimum_period_between_password_changes: 24 + history_storage_amount: 5 + lockout: + enable: false + max_attempts: 5 + window: 5 + duration: 60 + web_token: + timeout: 600 + idle_timeout: 1200 + validity_period: 24 + refresh: false + state: present + delegate_to: localhost + +- name: Query AAA Security Default Settings + cisco.aci.aci_aaa_security_default_settings: + host: apic + username: admin + password: SomeSecretPassword + state: query + delegate_to: localhost + register: query_result +""" + +RETURN = r""" +current: + description: The existing configuration from the APIC after the module has finished + returned: success + type: list + sample: + [ + { + "fvTenant": { + "attributes": { + "descr": "Production environment", + "dn": "uni/tn-production", + "name": "production", + "nameAlias": "", + "ownerKey": "", + "ownerTag": "" + } + } + } + ] +error: + description: The error information as returned from the APIC + returned: failure + type: dict + sample: + { + "code": "122", + "text": "unknown managed object class foo" + } +raw: + description: The raw output returned by the APIC REST API (xml or json) + returned: parse error + type: str + sample: '' +sent: + description: The actual/minimal configuration pushed to the APIC + returned: info + type: list + sample: + { + "fvTenant": { + "attributes": { + "descr": "Production environment" + } + } + } +previous: + description: The original configuration from the APIC before the module has started + returned: info + type: list + sample: + [ + { + "fvTenant": { + "attributes": { + "descr": "Production", + "dn": "uni/tn-production", + "name": "production", + "nameAlias": "", + "ownerKey": "", + "ownerTag": "" + } + } + } + ] +proposed: + description: The assembled configuration from the user-provided parameters + returned: info + type: dict + sample: + { + "fvTenant": { + "attributes": { + "descr": "Production environment", + "name": "production" + } + } + } +filter_string: + description: The filter string used for the request + returned: failure or debug + type: str + sample: ?rsp-prop-include=config-only +method: + description: The HTTP method used for the request to the APIC + returned: failure or debug + type: str + sample: POST +response: + description: The HTTP response from the APIC + returned: failure or debug + type: str + sample: OK (30 bytes) +status: + description: The HTTP status from the APIC + returned: failure or debug + type: int + sample: 200 +url: + description: The HTTP url used for the request to the APIC + returned: failure or debug + type: str + sample: https://10.11.12.13/api/mo/uni/tn-production.json +""" + +from ansible.module_utils.basic import AnsibleModule +from ansible_collections.cisco.aci.plugins.module_utils.aci import ACIModule, aci_argument_spec, aci_annotation_spec, aci_owner_spec + + +def main(): + argument_spec = aci_argument_spec() + argument_spec.update(aci_annotation_spec()) + argument_spec.update(aci_owner_spec()) + argument_spec.update( + password_strength_check=dict(type="bool", no_log=False), + password_strength_profile=dict( + type="dict", + no_log=False, + options=dict( + enable=dict(type="bool", required=True), + type=dict(type="str", choices=["custom", "any_three"]), + min_length=dict(type="int", aliases=["minimum_length", "min"]), + max_length=dict(type="int", aliases=["maximum_length", "max"]), + class_flags=dict(type="list", elements="str", choices=["digits", "lowercase", "specialchars", "uppercase"], aliases=["flags"]), + ), + ), + password_change=dict( + type="dict", + no_log=False, + options=dict( + enable=dict(type="bool"), + interval=dict(type="int"), + allowed_changes=dict(type="int"), + minimum_period=dict(type="int", aliases=["minimum_period_between_password_changes", "min_period"]), + history_storage_amount=dict(type="int", aliases=["history", "amount"]), + ), + ), + lockout=dict( + type="dict", + options=dict( + enable=dict(type="bool"), + max_attempts=dict(type="int", aliases=["max_failed_attempts", "failed_attempts", "attempts"]), + window=dict(type="int", aliases=["max_failed_attempts_window", "failed_attempts_window"]), + duration=dict(type="int"), + ), + ), + web_token=dict( + type="dict", + no_log=False, + options=dict( + timeout=dict(type="int"), + idle_timeout=dict(type="int", aliases=["session_idle_timeout"]), + validity_period=dict(type="int", aliases=["maximum_validity_period"]), + refresh=dict(type="bool"), + ), + ), + state=dict(type="str", default="present", choices=["present", "query"]), + name_alias=dict(type="str"), + ) + + module = AnsibleModule( + argument_spec=argument_spec, + supports_check_mode=True, + ) + aci = ACIModule(module) + + password_strength_check = aci.boolean(module.params.get("password_strength_check")) + password_strength_profile = module.params.get("password_strength_profile") + password_change = module.params.get("password_change") + lockout = module.params.get("lockout") + web_token = module.params.get("web_token") + state = module.params.get("state") + name_alias = module.params.get("name_alias") + + aci_class = "aaaUserEp" + child_classes = ["aaaPwdStrengthProfile", "aaaPwdProfile", "aaaBlockLoginProfile", "pkiWebTokenData"] + + aci.construct_url( + root_class=dict( + aci_class=aci_class, + aci_rn="userext", + ), + child_classes=child_classes, + ) + aci.get_existing() + + if state == "present": + child_configs = [] + + class_config = dict( + pwdStrengthCheck=password_strength_check, + nameAlias=name_alias, + ) + + if password_strength_profile: + if password_strength_profile.get("enable"): + child_configs.append( + dict( + aaaPwdStrengthProfile=dict( + attributes=dict( + pwdStrengthTestType=password_strength_profile.get("type"), + pwdMinLength=password_strength_profile.get("min_length"), + pwdMaxLength=password_strength_profile.get("max_length"), + pwdClassFlags=",".join(sorted(password_strength_profile.get("class_flags"))), + ), + ), + ), + ) + # Delete existing aaaPwdStrengthProfile if enable is set to false and it exists + # This is done for setting the correct output for changed state + elif len(aci.existing) > 0 and len(aci.existing[0].get("aaaUserEp", {}).get("children", {})) > 3: + for child in aci.existing[0].get("aaaUserEp", {}).get("children", {}): + if "aaaPwdStrengthProfile" in child.keys(): + child_configs.append(dict(aaaPwdStrengthProfile=dict(attributes=dict(status="deleted")))) + break + + if password_change: + child_configs.append( + dict( + aaaPwdProfile=dict( + attributes=dict( + changeDuringInterval=aci.boolean(password_change.get("enable"), "enable", "disable"), + changeInterval=password_change.get("interval"), + changeCount=password_change.get("allowed_changes"), + noChangeInterval=password_change.get("minimum_period"), + historyCount=password_change.get("history_storage_amount"), + ), + ), + ), + ) + + if lockout: + child_configs.append( + dict( + aaaBlockLoginProfile=dict( + attributes=dict( + enableLoginBlock=aci.boolean(lockout.get("enable"), "enable", "disable"), + maxFailedAttempts=lockout.get("max_attempts"), + maxFailedAttemptsWindow=lockout.get("window"), + blockDuration=lockout.get("duration"), + ), + ), + ), + ) + + if web_token: + child_configs.append( + dict( + pkiEp=dict( + attributes=dict(descr=""), + children=[ + dict( + pkiWebTokenData=dict( + attributes=dict( + webtokenTimeoutSeconds=web_token.get("timeout"), + uiIdleTimeoutSeconds=web_token.get("idle_timeout"), + maximumValidityPeriod=web_token.get("validity_period"), + sessionRecordFlags="login,logout,refresh" if web_token.get("refresh") else "login,logout", + ), + ), + ), + ], + ), + ), + ) + + aci.payload( + aci_class=aci_class, + class_config=class_config, + child_configs=child_configs, + ) + + aci.get_diff(aci_class=aci_class) + + aci.post_config() + + aci.exit_json() + + +if __name__ == "__main__": + main() diff --git a/ansible_collections/cisco/aci/plugins/modules/aci_aaa_ssh_auth.py b/ansible_collections/cisco/aci/plugins/modules/aci_aaa_ssh_auth.py index df4732f28..e1eb4b4d7 100644 --- a/ansible_collections/cisco/aci/plugins/modules/aci_aaa_ssh_auth.py +++ b/ansible_collections/cisco/aci/plugins/modules/aci_aaa_ssh_auth.py @@ -13,7 +13,7 @@ ANSIBLE_METADATA = {"metadata_version": "1.1", "status": ["preview"], "supported DOCUMENTATION = r""" --- module: aci_aaa_ssh_auth -short_description: Manage AAA SSH auth (aaaSshAuth) objects. +short_description: Manage AAA SSH auth objects (aaa:SshAuth) description: - Manage AAA SSH Auth key configuration on Cisco ACI fabrics. options: @@ -47,7 +47,7 @@ notes: The M(cisco.aci.aci_aaa_user) modules can be used for this. seealso: - name: APIC Management Information Model reference - description: More information about the internal APIC class B(aaaSshAuth). + description: More information about the internal APIC class B(aaa:SshAuth). link: https://developer.cisco.com/docs/apic-mim-ref/ author: - Tim Cragg (@timcragg) diff --git a/ansible_collections/cisco/aci/plugins/modules/aci_access_port_block_to_access_port.py b/ansible_collections/cisco/aci/plugins/modules/aci_access_port_block_to_access_port.py index 646423290..0067d0463 100644 --- a/ansible_collections/cisco/aci/plugins/modules/aci_access_port_block_to_access_port.py +++ b/ansible_collections/cisco/aci/plugins/modules/aci_access_port_block_to_access_port.py @@ -4,6 +4,7 @@ # Copyright: (c) 2018, Simon Metzger # Copyright: (c) 2020, Shreyas Srish # Copyright: (c) 2020, Zak Lantz (@manofcolombia) +# Copyright: (c) 2024, Gaspard Micol (@gmicol) # 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 @@ -15,55 +16,60 @@ ANSIBLE_METADATA = {"metadata_version": "1.1", "status": ["preview"], "supported 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) +short_description: Manage Port blocks of Fabric Access Leaf/Spine Interface Port Selectors (infra:PortBlk) description: -- Manage port blocks of Fabric interface policy leaf profile interface selectors on Cisco ACI fabrics. +- Manage Port blocks of Fabric Access Interface Leaf/Spine Port Selectors on Cisco ACI fabrics. options: interface_profile: description: - - The name of the Fabric access policy leaf interface profile. + - The name of the Fabric access policy leaf/spine interface profile. type: str - aliases: [ leaf_interface_profile_name, leaf_interface_profile, interface_profile_name ] + aliases: + - leaf_interface_profile_name + - leaf_interface_profile + - interface_profile_name + - spine_interface_profile + - spine_interface_profile_name access_port_selector: description: - - The name of the Fabric access policy leaf interface profile access port selector. + - The name of the Fabric access policy leaf/spine interface 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. + - The name of the Fabric access policy interface 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). + - The description for the port block. 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. + - The beginning (from-range) of the port range block for the 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. + - The end (to-range) of the port range block for the 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. + - The beginning (from-range) of the card range block for the 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. + - The end (to-range) of the card range block for the port block. type: str aliases: [ to_card_range ] type: description: - - The type of access port block to be created under respective access port. + - The type of port block to be created under respective access port. type: str - choices: [ fex, leaf ] + choices: [ fex, leaf, spine ] default: leaf state: description: @@ -77,18 +83,27 @@ extends_documentation_fragment: - cisco.aci.annotation notes: -- The C(interface_profile) and C(access_port_selector) must exist before using this module in your playbook. +- If Adding a port block on an access leaf interface port selector of I(type) C(leaf), + The I(interface_profile) and I(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. +- If Adding a port block on an access interface port selector of C(type) C(spine), + The I(interface_profile) and I(access_port_selector) must exist before using this module in your playbook. + The M(cisco.aci.aci_access_spine_interface_profile) and M(cisco.aci.aci_access_spine_interface_selector) modules can be used for this. seealso: +- module: cisco.aci.aci_interface_policy_leaf_profile +- module: cisco.aci.aci_access_port_to_interface_policy_leaf_profile +- module: cisco.aci.aci_access_spine_interface_profile +- module: cisco.aci.aci_access_spine_interface_selector - name: APIC Management Information Model reference - description: More information about the internal APIC classes B(infra:HPortS) and B(infra:PortBlk). + description: More information about the internal APIC classes B(infra:PortBlk). link: https://developer.cisco.com/docs/apic-mim-ref/ author: - Simon Metzger (@smnmtzgr) +- Gaspard Micol (@gmicol) """ EXAMPLES = r""" -- name: Associate an access port block (single port) to an interface selector +- name: Associate a Fabric access policy interface port block (single port) to an interface selector cisco.aci.aci_access_port_block_to_access_port: host: apic username: admin @@ -101,7 +116,7 @@ EXAMPLES = r""" state: present delegate_to: localhost -- name: Associate an access port block (port range) to an interface selector +- name: Associate a Fabric access policy interface port block (port range) to an interface selector cisco.aci.aci_access_port_block_to_access_port: host: apic username: admin @@ -114,7 +129,7 @@ EXAMPLES = r""" state: present delegate_to: localhost -- name: Associate an access port block (single port) to an interface selector of type fex +- name: Associate a Fabric access policy interface port block (single port) to an interface selector of type fex cisco.aci.aci_access_port_block_to_access_port: host: apic username: admin @@ -128,7 +143,7 @@ EXAMPLES = r""" state: present delegate_to: localhost -- name: Associate an access port block (port range) to an interface selector of type fex +- name: Associate a Fabric access policy interface port block (port range) to an interface selector of type fex cisco.aci.aci_access_port_block_to_access_port: host: apic username: admin @@ -142,7 +157,7 @@ EXAMPLES = r""" state: present delegate_to: localhost -- name: Remove an access port block from an interface selector +- name: Query Specific Fabric access policy interface port block under given access port selector cisco.aci.aci_access_port_block_to_access_port: host: apic username: admin @@ -150,12 +165,11 @@ EXAMPLES = r""" interface_profile: leafintprfname access_port_selector: accessportselectorname port_blk: leafportblkname - from_port: 13 - to_port: 13 - state: absent + state: query delegate_to: localhost + register: query_result -- name: Remove an access port block from an interface selector of type fex +- name: Query Specific Fabric access policy interface port block under given access port selector of type fex cisco.aci.aci_access_port_block_to_access_port: host: apic username: admin @@ -164,75 +178,76 @@ EXAMPLES = r""" interface_profile: leafintprfname_fex access_port_selector: accessportselectorname_fex port_blk: leafportblkname_fex - from_port: 13 - to_port: 13 - state: absent + state: query delegate_to: localhost + register: query_result -- name: Query Specific access port block under given access port selector +- name: Query all Fabric access policy interface 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 - 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 +- name: Query all Fabric access policy interface 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 - 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 +- name: Query all Fabric access policy interface port blocks in the fabric 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 +- name: Query all Fabric access policy interface 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 - interface_profile: leafintprfname_fex state: query delegate_to: localhost register: query_result -- name: Query all access port blocks in the fabric +- name: Remove a Fabric access policy interface port block from an interface selector cisco.aci.aci_access_port_block_to_access_port: host: apic username: admin password: SomeSecretPassword - state: query + interface_profile: leafintprfname + access_port_selector: accessportselectorname + port_blk: leafportblkname + from_port: 13 + to_port: 13 + state: absent delegate_to: localhost - register: query_result -- name: Query all access port blocks in the fabric of type fex +- name: Remove a Fabric access policy interface 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 - state: query + interface_profile: leafintprfname_fex + access_port_selector: accessportselectorname_fex + port_blk: leafportblkname_fex + from_port: 13 + to_port: 13 + state: absent delegate_to: localhost - register: query_result """ RETURN = r""" @@ -348,7 +363,16 @@ def main(): argument_spec = aci_argument_spec() argument_spec.update(aci_annotation_spec()) argument_spec.update( - interface_profile=dict(type="str", aliases=["leaf_interface_profile_name", "leaf_interface_profile", "interface_profile_name"]), + interface_profile=dict( + type="str", + aliases=[ + "leaf_interface_profile_name", + "leaf_interface_profile", + "interface_profile_name", + "spine_interface_profile", + "spine_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"]), @@ -357,15 +381,15 @@ def main(): 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 + type=dict(type="str", default="leaf", choices=["fex", "leaf", "spine"]), # 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"]], + ["state", "absent", ["interface_profile", "access_port_selector", "port_blk"]], + ["state", "present", ["interface_profile", "access_port_selector", "port_blk", "from_port", "to_port"]], ], ) @@ -381,26 +405,45 @@ def main(): 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), + subclass_1 = dict( + aci_class=aci_class, + aci_rn="{0}-{1}".format(aci_rn, interface_profile), + module_object=interface_profile, + target_filter={"name": interface_profile}, + ) + subclass_2 = dict( + aci_class="infraHPortS", + aci_rn="hports-{0}-typ-range".format(access_port_selector), + module_object=access_port_selector, + target_filter={"name": access_port_selector}, + ) + if type_port == "spine": + subclass_1 = dict( + aci_class="infraSpAccPortP", + aci_rn="spaccportprof-{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), + ) + subclass_2 = dict( + aci_class="infraSHPortS", + aci_rn="shports-{0}-typ-range".format(access_port_selector), module_object=access_port_selector, target_filter={"name": access_port_selector}, + ) + aci.construct_url( + root_class=dict( + aci_class="infraInfra", + aci_rn="infra", ), - subclass_2=dict( + subclass_1=subclass_1, + subclass_2=subclass_2, + subclass_3=dict( aci_class="infraPortBlk", aci_rn="portblk-{0}".format(port_blk), module_object=port_blk, @@ -420,7 +463,6 @@ def main(): toPort=to_port, fromCard=from_card, toCard=to_card, - # type='range', ), ) diff --git a/ansible_collections/cisco/aci/plugins/modules/aci_access_port_to_interface_policy_leaf_profile.py b/ansible_collections/cisco/aci/plugins/modules/aci_access_port_to_interface_policy_leaf_profile.py index 7b5c896ad..f2e921394 100644 --- a/ansible_collections/cisco/aci/plugins/modules/aci_access_port_to_interface_policy_leaf_profile.py +++ b/ansible_collections/cisco/aci/plugins/modules/aci_access_port_to_interface_policy_leaf_profile.py @@ -14,7 +14,7 @@ ANSIBLE_METADATA = {"metadata_version": "1.1", "status": ["preview"], "supported 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) +short_description: Manage Fabric interface policy leaf profile interface selectors (infra:HPortS, infra:RsAccBaseGrp, and infra:PortBlk) description: - Manage Fabric interface policy leaf profile interface selectors on Cisco ACI fabrics. options: diff --git a/ansible_collections/cisco/aci/plugins/modules/aci_access_spine_interface_profile.py b/ansible_collections/cisco/aci/plugins/modules/aci_access_spine_interface_profile.py new file mode 100644 index 000000000..a34f269ae --- /dev/null +++ b/ansible_collections/cisco/aci/plugins/modules/aci_access_spine_interface_profile.py @@ -0,0 +1,279 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- + +# Copyright: (c) 2023, Eric Girard <@netgirard> +# Copyright: (c) 2024, Gaspard Micol (@gmicol) +# 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_spine_interface_profile +short_description: Manage fabric interface policy spine profiles (infra:SpAccPortP) +description: +- Manage fabric interface policy spine profiles on Cisco ACI fabrics. +options: + interface_profile: + description: + - The name of the Fabric access policy spine interface profile. + type: str + aliases: [ name, spine_interface_profile_name, spine_interface_profile, interface_profile_name ] + description: + description: + - The description for the Fabric access policy spine 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 +extends_documentation_fragment: +- cisco.aci.aci +- cisco.aci.annotation +- cisco.aci.owner + +seealso: +- name: APIC Management Information Model reference + description: More information about the internal APIC class B(infra:SpAccPortP). + link: https://developer.cisco.com/docs/apic-mim-ref/ +author: +- Eric Girard (@netgirard) +- Gaspard Micol (@gmicol) +""" + +EXAMPLES = r""" +- name: Add a new spine_interface_profile + cisco.aci.aci_access_spine_interface_profile: + host: apic + username: admin + password: SomeSecretPassword + interface_profile: spineintprfname + description: spineintprfname description + state: present + delegate_to: localhost + +- name: Query a spine_interface_profile + cisco.aci.aci_access_spine_interface_profile: + host: apic + username: admin + password: SomeSecretPassword + interface_profile: spineintprfname + state: query + delegate_to: localhost + register: query_result + +- name: Query all spine_interface_profiles + cisco.aci.aci_access_spine_interface_profile: + host: apic + username: admin + password: SomeSecretPassword + state: query + delegate_to: localhost + +- name: Remove a spine_interface_profile + cisco.aci.aci_access_spine_interface_profile: + host: apic + username: admin + password: SomeSecretPassword + interface_profile: spineintprfname + 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: '' +sent: + description: The actual/minimal configuration pushed to the APIC + returned: info + type: list + sample: + { + "fvTenant": { + "attributes": { + "descr": "Production environment" + } + } + } +previous: + description: The original configuration from the APIC before the module has started + returned: info + type: list + sample: + [ + { + "fvTenant": { + "attributes": { + "descr": "Production", + "dn": "uni/tn-production", + "name": "production", + "nameAlias": "", + "ownerKey": "", + "ownerTag": "" + } + } + } + ] +proposed: + description: The assembled configuration from the user-provided parameters + returned: info + type: dict + sample: + { + "fvTenant": { + "attributes": { + "descr": "Production environment", + "name": "production" + } + } + } +filter_string: + description: The filter string used for the request + returned: failure or debug + type: str + sample: ?rsp-prop-include=config-only +method: + description: The HTTP method used for the request to the APIC + returned: failure or debug + type: str + sample: POST +response: + description: The HTTP response from the APIC + returned: failure or debug + type: str + sample: OK (30 bytes) +status: + description: The HTTP status from the APIC + returned: failure or debug + type: int + sample: 200 +url: + description: The HTTP url used for the request to the APIC + returned: failure or debug + type: str + sample: https://10.11.12.13/api/mo/uni/tn-production.json +""" + +from ansible.module_utils.basic import AnsibleModule +from ansible_collections.cisco.aci.plugins.module_utils.aci import ACIModule, aci_argument_spec, aci_annotation_spec, aci_owner_spec + + +def main(): + argument_spec = aci_argument_spec() + argument_spec.update(aci_annotation_spec()) + argument_spec.update(aci_owner_spec()) + argument_spec.update( + interface_profile=dict( + type="str", + aliases=[ + "name", + "spine_interface_profile_name", + "spine_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"), + ) + + 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") + + aci = ACIModule(module) + + aci.construct_url( + root_class=dict( + aci_class="infraInfra", + aci_rn="infra", + ), + subclass_1=dict( + aci_class="infraSpAccPortP", + aci_rn="spaccportprof-{0}".format(interface_profile), + module_object=interface_profile, + target_filter={"name": interface_profile}, + ), + ) + + aci.get_existing() + + if state == "present": + aci.payload( + aci_class="infraSpAccPortP", + class_config=dict( + name=interface_profile, + descr=description, + nameAlias=name_alias, + ), + ) + + aci.get_diff(aci_class="infraSpAccPortP") + + aci.post_config() + + elif state == "absent": + aci.delete_config() + + aci.exit_json() + + +if __name__ == "__main__": + main() diff --git a/ansible_collections/cisco/aci/plugins/modules/aci_access_spine_interface_profile_to_spine_switch_profile.py b/ansible_collections/cisco/aci/plugins/modules/aci_access_spine_interface_profile_to_spine_switch_profile.py new file mode 100644 index 000000000..17d8517c1 --- /dev/null +++ b/ansible_collections/cisco/aci/plugins/modules/aci_access_spine_interface_profile_to_spine_switch_profile.py @@ -0,0 +1,292 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- + +# Copyright: (c) 2023, Eric Girard <@netgirard> +# Copyright: (c) 2024, Gaspard Micol (@gmicol) +# 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_spine_interface_profile_to_spine_switch_profile +short_description: Bind Fabric Access Spine Interface Profiles to Fabric Acces Spine Switch Profiles (infra:RsSpAccPortP) +description: +- Bind access spine interface selector profiles to access switch policy spine profiles on Cisco ACI fabrics. +options: + switch_profile: + description: + - The name of the Fabric Access Spine Switch Profile to which we add a Spine Interface Selector Profile. + type: str + aliases: [ switch_profile_name, spine_switch_profile, spine_switch_profile_name ] + interface_profile: + description: + - The name of the Fabric Access Spine Interface Profile to be added and associated with the Spine Switch Profile. + type: str + aliases: [ interface_profile_name, spine_interface_profile, spine_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 +- cisco.aci.annotation +- cisco.aci.owner + +notes: +- This module requires an existing I(switch_profile). + The module M(cisco.aci.aci_access_spine_switch_profile) can be used for this. +- The I(interface_profile) accepts non existing spine interface profile names. + They appear on APIC GUI with a state of "missing-target". + The module M(cisco.aci.aci_access_spine_interface_profile) can be used to create them. +seealso: +- module: cisco.aci.aci_access_spine_switch_profile +- module: cisco.aci.aci_access_spine_interface_profile +- name: APIC Management Information Model reference + description: More information about the internal APIC class B(infra:RsSpAccPortP). + link: https://developer.cisco.com/docs/apic-mim-ref/ +author: +- Eric Girard (@netgirard) +- Gaspard Micol (@gmicol) +""" + +EXAMPLES = r""" +- name: Associating an interface selector profile to a switch policy spine profile + cisco.aci.aci_access_spine_interface_profile_to_spine_switch_profile: + host: apic + username: admin + password: SomeSecretPassword + switch_profile: sw_name + interface_profile: interface_profile_name + state: present + delegate_to: localhost + +- name: Query an interface selector profile associated with a switch policy spine profile + cisco.aci.aci_access_spine_interface_profile_to_spine_switch_profile: + host: apic + username: admin + password: SomeSecretPassword + switch_profile: sw_name + interface_profile: interface_profile_name + state: query + delegate_to: localhost + +- name: Query all association of interface selector profiles with a switch policy spine profile + cisco.aci.aci_access_spine_interface_profile_to_spine_switch_profile: + host: apic + username: admin + password: SomeSecretPassword + state: query + delegate_to: localhost + +- name: Remove an interface selector profile associated with a switch policy spine profile + cisco.aci.aci_access_spine_interface_profile_to_spine_switch_profile: + host: apic + username: admin + password: SomeSecretPassword + switch_profile: sw_name + interface_profile: interface_profile_name + 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: '' +sent: + description: The actual/minimal configuration pushed to the APIC + returned: info + type: list + sample: + { + "fvTenant": { + "attributes": { + "descr": "Production environment" + } + } + } +previous: + description: The original configuration from the APIC before the module has started + returned: info + type: list + sample: + [ + { + "fvTenant": { + "attributes": { + "descr": "Production", + "dn": "uni/tn-production", + "name": "production", + "nameAlias": "", + "ownerKey": "", + "ownerTag": "" + } + } + } + ] +proposed: + description: The assembled configuration from the user-provided parameters + returned: info + type: dict + sample: + { + "fvTenant": { + "attributes": { + "descr": "Production environment", + "name": "production" + } + } + } +filter_string: + description: The filter string used for the request + returned: failure or debug + type: str + sample: ?rsp-prop-include=config-only +method: + description: The HTTP method used for the request to the APIC + returned: failure or debug + type: str + sample: POST +response: + description: The HTTP response from the APIC + returned: failure or debug + type: str + sample: OK (30 bytes) +status: + description: The HTTP status from the APIC + returned: failure or debug + type: int + sample: 200 +url: + description: The HTTP url used for the request to the APIC + returned: failure or debug + type: str + sample: https://10.11.12.13/api/mo/uni/tn-production.json +""" + +from ansible.module_utils.basic import AnsibleModule +from ansible_collections.cisco.aci.plugins.module_utils.aci import ACIModule, aci_argument_spec, aci_annotation_spec, aci_owner_spec + + +def main(): + argument_spec = aci_argument_spec() + argument_spec.update(aci_annotation_spec()) + argument_spec.update(aci_owner_spec()) + argument_spec.update( + switch_profile=dict( + type="str", + aliases=[ + "switch_profile_name", + "spine_switch_profile", + "spine_switch_profile_name", + ], + ), # Not required for querying all objects + interface_profile=dict( + type="str", + aliases=[ + "interface_profile_name", + "spine_interface_profile", + "spine_interface_profile_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", ["switch_profile", "interface_profile"]], + ["state", "present", ["switch_profile", "interface_profile"]], + ], + ) + + switch_profile = module.params.get("switch_profile") + interface_profile = module.params.get("interface_profile") + state = module.params.get("state") + + # Defining the interface profile tDn for clarity + interface_profile_tDn = "uni/infra/spaccportprof-{0}".format(interface_profile) + + aci = ACIModule(module) + aci.construct_url( + root_class=dict( + aci_class="infraInfra", + aci_rn="infra", + ), + subclass_1=dict( + aci_class="infraSpineP", + aci_rn="spprof-{0}".format(switch_profile), + module_object=switch_profile, + target_filter={"name": switch_profile}, + ), + subclass_2=dict( + aci_class="infraRsSpAccPortP", + aci_rn="rsspAccPortP-[{0}]".format(interface_profile_tDn), + module_object=interface_profile, + target_filter={"tDn": interface_profile_tDn}, + ), + ) + + aci.get_existing() + + if state == "present": + aci.payload( + aci_class="infraRsSpAccPortP", + class_config=dict(tDn=interface_profile_tDn), + ) + + aci.get_diff(aci_class="infraRsSpAccPortP") + + aci.post_config() + + elif state == "absent": + aci.delete_config() + + aci.exit_json() + + +if __name__ == "__main__": + main() diff --git a/ansible_collections/cisco/aci/plugins/modules/aci_access_spine_interface_selector.py b/ansible_collections/cisco/aci/plugins/modules/aci_access_spine_interface_selector.py new file mode 100644 index 000000000..373a31e76 --- /dev/null +++ b/ansible_collections/cisco/aci/plugins/modules/aci_access_spine_interface_selector.py @@ -0,0 +1,326 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- + +# Copyright: (c) 2024, Gaspard Micol (@gmicol) +# 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_spine_interface_selector +short_description: Manage Fabric Access Policy Spine Interface Port Selectors (infra:SHPortS) +description: +- Manage Fabric Access Policy Spine Interface Port Selectors on Cisco ACI fabrics. +- This selector is used for applying infrastructure policies on selected ports. +options: + spine_interface_profile: + description: + - The name of the Fabric access policy spine interface profile. + type: str + aliases: [ spine_interface_profile_name, interface_profile, interface_profile_name ] + spine_interface_selector: + description: + - The name of the Fabric access spine interface port selector. + type: str + aliases: [ name, spine_interface_selector_name, interface_selector, interface_selector_name, access_port_selector, access_port_selector_name ] + description: + description: + - The description for the spine interface port selector. + type: str + policy_group: + description: + - The name of the fabric access policy group to be associated with the spine interface port selector. + type: str + aliases: [ policy_group_name ] + selector_type: + description: + - The host port selector type. + - If using a port block to specify range of interfaces, the type must be set to C(range). + type: str + choices: [ all, range ] + 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 +extends_documentation_fragment: +- cisco.aci.aci +- cisco.aci.annotation +- cisco.aci.owner + +notes: +- The I(spine_interface_profile) must exist before using this module in your playbook. + The M(cisco.aci.aci_access_spine_interface_profile) module can be used for this. +- If a I(policy_group) is used, it must exist before using this module in your playbook. + The M(cisco.aci.aci_interface_policy_spine_policy_group) module can be used for this. +seealso: +- module: cisco.aci.aci_access_port_block_to_access_port +- module: cisco.aci.aci_interface_policy_spine_policy_group +- name: APIC Management Information Model reference + description: More information about the internal APIC classes B(infra:SHPortS) and B(infra:RsSpAccGrp). + link: https://developer.cisco.com/docs/apic-mim-ref/ +author: +- Gaspard Micol (@gmicol) +""" + +EXAMPLES = r""" +- name: Add a new access spine interface selector + cisco.aci.aci_access_spine_interface_selector: + host: apic + username: admin + password: SomeSecretPassword + spine_interface_profile: my_access_spine_interface_profile + spine_interface_selector: my_access_spine_interface_selector + selector_type: range + policy_group: my_access_spine_interface_policy_group + state: present + delegate_to: localhost + +- name: Query a specific access spine interface selector under given spine_interface_profile + cisco.aci.aci_access_spine_interface_selector: + host: apic + username: admin + password: SomeSecretPassword + spine_interface_profile: my_access_spine_interface_profile + spine_interface_selector: my_access_spine_interface_selector + selector_type: range + state: query + delegate_to: localhost + +- name: Query all access spine interface selectors under given spine_interface_profile + cisco.aci.aci_access_spine_interface_selector: + host: apic + username: admin + password: SomeSecretPassword + spine_interface_profile: my_access_spine_interface_profile + state: query + delegate_to: localhost + +- name: Query all access spine interface selectors + cisco.aci.aci_access_spine_interface_selector: + host: apic + username: admin + password: SomeSecretPassword + state: query + delegate_to: localhost + +- name: Remove an access spine interface selector + cisco.aci.aci_access_spine_interface_selector: + host: apic + username: admin + password: SomeSecretPassword + spine_interface_profile: my_access_spine_interface_profile + spine_interface_selector: my_access_spine_interface_selector + selector_type: range + 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: '' +sent: + description: The actual/minimal configuration pushed to the APIC + returned: info + type: list + sample: + { + "fvTenant": { + "attributes": { + "descr": "Production environment" + } + } + } +previous: + description: The original configuration from the APIC before the module has started + returned: info + type: list + sample: + [ + { + "fvTenant": { + "attributes": { + "descr": "Production", + "dn": "uni/tn-production", + "name": "production", + "nameAlias": "", + "ownerKey": "", + "ownerTag": "" + } + } + } + ] +proposed: + description: The assembled configuration from the user-provided parameters + returned: info + type: dict + sample: + { + "fvTenant": { + "attributes": { + "descr": "Production environment", + "name": "production" + } + } + } +filter_string: + description: The filter string used for the request + returned: failure or debug + type: str + sample: ?rsp-prop-include=config-only +method: + description: The HTTP method used for the request to the APIC + returned: failure or debug + type: str + sample: POST +response: + description: The HTTP response from the APIC + returned: failure or debug + type: str + sample: OK (30 bytes) +status: + description: The HTTP status from the APIC + returned: failure or debug + type: int + sample: 200 +url: + description: The HTTP url used for the request to the APIC + returned: failure or debug + type: str + sample: https://10.11.12.13/api/mo/uni/tn-production.json +""" + +from ansible.module_utils.basic import AnsibleModule +from ansible_collections.cisco.aci.plugins.module_utils.aci import ACIModule, aci_argument_spec, aci_annotation_spec, aci_owner_spec +from ansible_collections.cisco.aci.plugins.module_utils.constants import MATCH_ACCESS_POLICIES_SELECTOR_TYPE + + +def main(): + argument_spec = aci_argument_spec() + argument_spec.update(aci_annotation_spec()) + argument_spec.update(aci_owner_spec()) + argument_spec.update( + spine_interface_profile=dict(type="str", aliases=["spine_interface_profile_name", "interface_profile", "interface_profile_name"]), + spine_interface_selector=dict( + type="str", + aliases=[ + "name", + "spine_interface_selector_name", + "interface_selector", + "interface_selector_name", + "access_port_selector", + "access_port_selector_name", + ], + ), # Not required for querying all objects + description=dict(type="str"), + policy_group=dict(type="str", aliases=["policy_group_name"]), + selector_type=dict(type="str", choices=list(MATCH_ACCESS_POLICIES_SELECTOR_TYPE.keys()), aliases=["type"]), + state=dict(type="str", default="present", choices=["absent", "present", "query"]), + ) + + module = AnsibleModule( + argument_spec=argument_spec, + supports_check_mode=True, + required_if=[ + ["state", "absent", ["spine_interface_profile", "spine_interface_selector", "selector_type"]], + ["state", "present", ["spine_interface_profile", "spine_interface_selector", "selector_type"]], + ], + ) + + spine_interface_profile = module.params.get("spine_interface_profile") + spine_interface_selector = module.params.get("spine_interface_selector") + description = module.params.get("description") + policy_group = module.params.get("policy_group") + selector_type = MATCH_ACCESS_POLICIES_SELECTOR_TYPE.get(module.params.get("selector_type")) + state = module.params.get("state") + + child_configs = [] + if policy_group is not None: + child_configs.append(dict(infraRsSpAccGrp=dict(attributes=dict(tDn="uni/infra/funcprof/spaccportgrp-{0}".format(policy_group))))) + + aci = ACIModule(module) + + aci.construct_url( + root_class=dict( + aci_class="infraInfra", + aci_rn="infra", + ), + subclass_1=dict( + aci_class="infraSpAccPortP", + aci_rn="spaccportprof-{0}".format(spine_interface_profile), + module_object=spine_interface_profile, + target_filter={"name": spine_interface_profile}, + ), + subclass_2=dict( + aci_class="infraSHPortS", + aci_rn="shports-{0}-typ-{1}".format(spine_interface_selector, selector_type), + module_object=spine_interface_selector, + target_filter={"name": spine_interface_selector}, + ), + child_classes=["infraRsSpAccGrp"], + ) + + aci.get_existing() + + if state == "present": + aci.payload( + aci_class="infraSHPortS", + class_config=dict( + descr=description, + name=spine_interface_selector, + type=selector_type, + ), + child_configs=child_configs, + ) + + aci.get_diff(aci_class="infraSHPortS") + + aci.post_config() + + elif state == "absent": + aci.delete_config() + + aci.exit_json() + + +if __name__ == "__main__": + main() diff --git a/ansible_collections/cisco/aci/plugins/modules/aci_access_spine_switch_profile.py b/ansible_collections/cisco/aci/plugins/modules/aci_access_spine_switch_profile.py new file mode 100644 index 000000000..22d4756a7 --- /dev/null +++ b/ansible_collections/cisco/aci/plugins/modules/aci_access_spine_switch_profile.py @@ -0,0 +1,277 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- + +# Copyright: (c) 2023, Eric Girard <@netgirard> +# Copyright: (c) 2024, Gaspard Micol (@gmicol) +# 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_spine_switch_profile +short_description: Manage Fabric Access Spine Switch Profiles (infra:SpineP) +description: +- Manage Fabric access switch policy spine profiles on Cisco ACI fabrics. +options: + switch_profile: + description: + - The name of the Fabric Access Spine Switch Profile. + type: str + aliases: [ switch_profile_name, name, spine_switch_profile, spine_switch_profile_name ] + description: + description: + - The description for the Fabric Access Spine Switch 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 +- cisco.aci.annotation +- cisco.aci.owner + +seealso: +- name: APIC Management Information Model reference + description: More information about the internal APIC class B(infra:SpineP). + link: https://developer.cisco.com/docs/apic-mim-ref/ +author: +- Eric Girard (@netgirard) +- Gaspard Micol (@gmicol) +""" + +EXAMPLES = r""" +- name: Add a new Access Spine Switch Profile + cisco.aci.aci_access_spine_switch_profile: + host: apic + username: admin + password: SomeSecretPassword + switch_profile: sw_name + description: sw_description + state: present + delegate_to: localhost + +- name: Query an Access Spine Switch Profile + cisco.aci.aci_access_spine_switch_profile: + host: apic + username: admin + password: SomeSecretPassword + switch_profile: sw_name + state: query + delegate_to: localhost + +- name: Query all Access Spine Switch Profiles + cisco.aci.aci_access_spine_switch_profile: + host: apic + username: admin + password: SomeSecretPassword + state: query + delegate_to: localhost + +- name: Remove an Access Spine Switch Profile + cisco.aci.aci_access_spine_switch_profile: + host: apic + username: admin + password: SomeSecretPassword + switch_profile: sw_name + 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: '' +sent: + description: The actual/minimal configuration pushed to the APIC + returned: info + type: list + sample: + { + "fvTenant": { + "attributes": { + "descr": "Production environment" + } + } + } +previous: + description: The original configuration from the APIC before the module has started + returned: info + type: list + sample: + [ + { + "fvTenant": { + "attributes": { + "descr": "Production", + "dn": "uni/tn-production", + "name": "production", + "nameAlias": "", + "ownerKey": "", + "ownerTag": "" + } + } + } + ] +proposed: + description: The assembled configuration from the user-provided parameters + returned: info + type: dict + sample: + { + "fvTenant": { + "attributes": { + "descr": "Production environment", + "name": "production" + } + } + } +filter_string: + description: The filter string used for the request + returned: failure or debug + type: str + sample: ?rsp-prop-include=config-only +method: + description: The HTTP method used for the request to the APIC + returned: failure or debug + type: str + sample: POST +response: + description: The HTTP response from the APIC + returned: failure or debug + type: str + sample: OK (30 bytes) +status: + description: The HTTP status from the APIC + returned: failure or debug + type: int + sample: 200 +url: + description: The HTTP url used for the request to the APIC + returned: failure or debug + type: str + sample: https://10.11.12.13/api/mo/uni/tn-production.json +""" + +from ansible.module_utils.basic import AnsibleModule +from ansible_collections.cisco.aci.plugins.module_utils.aci import ACIModule, aci_argument_spec, aci_annotation_spec, aci_owner_spec + + +def main(): + argument_spec = aci_argument_spec() + argument_spec.update(aci_annotation_spec()) + argument_spec.update(aci_owner_spec()) + argument_spec.update( + switch_profile=dict( + type="str", + aliases=[ + "name", + "switch_profile_name", + "spine_switch_profile", + "spine_switch_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", ["switch_profile"]], + ["state", "present", ["switch_profile"]], + ], + ) + + switch_profile = module.params.get("switch_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="infraInfra", + aci_rn="infra", + ), + subclass_1=dict( + aci_class="infraSpineP", + aci_rn="spprof-{0}".format(switch_profile), + module_object=switch_profile, + target_filter={"name": switch_profile}, + ), + ) + + aci.get_existing() + + if state == "present": + aci.payload( + aci_class="infraSpineP", + class_config=dict( + name=switch_profile, + descr=description, + nameAlias=name_alias, + ), + ) + + aci.get_diff(aci_class="infraSpineP") + + aci.post_config() + + elif state == "absent": + aci.delete_config() + + aci.exit_json() + + +if __name__ == "__main__": + main() diff --git a/ansible_collections/cisco/aci/plugins/modules/aci_access_spine_switch_selector.py b/ansible_collections/cisco/aci/plugins/modules/aci_access_spine_switch_selector.py new file mode 100644 index 000000000..c7cee4b5e --- /dev/null +++ b/ansible_collections/cisco/aci/plugins/modules/aci_access_spine_switch_selector.py @@ -0,0 +1,321 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- + +# Copyright: (c) 2023, Eric Girard <@netgirard> +# Copyright: (c) 2024, Gaspard Micol (@gmicol) +# 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_spine_switch_selector +short_description: Manage Fabric Access Policy Spine Switch Port Selectors (infra:SpineS) +description: +- Manage Fabric Access Policy Spine Switch Port Selectors on Cisco ACI fabrics. +options: + spine_switch_profile: + description: + - The name of the Fabric access policy spine switch profile. + type: str + aliases: [ spine_switch_profile_name, switch_profile, switch_profile_name ] + spine_switch_selector: + description: + - The name of the Fabric access spine switch port selector. + type: str + aliases: [ name, spine_switch_selector_name, switch_selector, switch_selector_name, access_port_selector, access_port_selector_name ] + description: + description: + - The description for the spine switch port selector. + type: str + policy_group: + description: + - The name of the fabric access policy group to be associated with the spine switch port selector. + type: str + aliases: [ policy_group_name ] + selector_type: + description: + - The host port selector type. + - If using a port block to specify range of switches, the type must be set to C(range). + type: str + choices: [ all, range ] + 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 +extends_documentation_fragment: +- cisco.aci.aci +- cisco.aci.annotation +- cisco.aci.owner + +notes: +- The I(spine_switch_profile) must exist before using this module in your playbook. + The M(cisco.aci.aci_access_spine_switch_profile) module can be used for this. +- If a I(policy_group) is used, it must exist before using this module in your playbook. + The M(cisco.aci.aci_switch_policy_group) module can be used for this. +seealso: +- module: cisco.aci.aci_access_spine_switch_profile +- name: APIC Management Information Model reference + description: More information about the internal APIC classes B(infra:SpineS) and B(infra:RsAccNodePGrp). + link: https://developer.cisco.com/docs/apic-mim-ref/ +author: +- Eric Girard (@netgirard) +- Gaspard Micol (@gmicol) +""" + +EXAMPLES = r""" +- name: Add a switch policy spine profile selector (with policy group) + cisco.aci.aci_access_spine_switch_selector: + host: apic + username: admin + password: SomeSecretPassword + spine_switch_profile: sw_name + spine_switch_selector: spine_selector_name + selector_type: range + policy_group: somepolicygroupname + state: present + delegate_to: localhost + +- name: Query a switch policy spine profile selector + cisco.aci.aci_access_spine_switch_selector: + host: apic + username: admin + password: SomeSecretPassword + spine_switch_profile: sw_name + spine_switch_selector: spine_selector_name + selector_type: range + state: query + delegate_to: localhost + +- name: Query all switch policy spine profile selectors + cisco.aci.aci_access_spine_switch_selector: + host: apic + username: admin + password: SomeSecretPassword + state: query + delegate_to: localhost + +- name: Remove a switch policy spine profile selector + cisco.aci.aci_access_spine_switch_selector: + host: apic + username: admin + password: SomeSecretPassword + spine_switch_profile: sw_name + spine_switch_selector: spine_selector_name + selector_type: range + 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: '' +sent: + description: The actual/minimal configuration pushed to the APIC + returned: info + type: list + sample: + { + "fvTenant": { + "attributes": { + "descr": "Production environment" + } + } + } +previous: + description: The original configuration from the APIC before the module has started + returned: info + type: list + sample: + [ + { + "fvTenant": { + "attributes": { + "descr": "Production", + "dn": "uni/tn-production", + "name": "production", + "nameAlias": "", + "ownerKey": "", + "ownerTag": "" + } + } + } + ] +proposed: + description: The assembled configuration from the user-provided parameters + returned: info + type: dict + sample: + { + "fvTenant": { + "attributes": { + "descr": "Production environment", + "name": "production" + } + } + } +filter_string: + description: The filter string used for the request + returned: failure or debug + type: str + sample: ?rsp-prop-include=config-only +method: + description: The HTTP method used for the request to the APIC + returned: failure or debug + type: str + sample: POST +response: + description: The HTTP response from the APIC + returned: failure or debug + type: str + sample: OK (30 bytes) +status: + description: The HTTP status from the APIC + returned: failure or debug + type: int + sample: 200 +url: + description: The HTTP url used for the request to the APIC + returned: failure or debug + type: str + sample: https://10.11.12.13/api/mo/uni/tn-production.json +""" + +from ansible.module_utils.basic import AnsibleModule +from ansible_collections.cisco.aci.plugins.module_utils.aci import ACIModule, aci_argument_spec, aci_annotation_spec, aci_owner_spec +from ansible_collections.cisco.aci.plugins.module_utils.constants import MATCH_ACCESS_POLICIES_SELECTOR_TYPE + + +def main(): + argument_spec = aci_argument_spec() + argument_spec.update(aci_annotation_spec()) + argument_spec.update(aci_owner_spec()) + argument_spec.update( + spine_switch_profile=dict(type="str", aliases=["spine_switch_profile_name", "switch_profile", "switch_profile_name"]), + spine_switch_selector=dict( + type="str", + aliases=[ + "name", + "spine_switch_selector_name", + "switch_selector", + "switch_selector_name", + "access_port_selector", + "access_port_selector_name", + ], + ), # Not required for querying all objects + description=dict(type="str"), + policy_group=dict(type="str", aliases=["policy_group_name"]), + selector_type=dict(type="str", choices=list(MATCH_ACCESS_POLICIES_SELECTOR_TYPE.keys()), aliases=["type"]), + state=dict(type="str", default="present", choices=["absent", "present", "query"]), + ) + + module = AnsibleModule( + argument_spec=argument_spec, + supports_check_mode=True, + required_if=[ + ["state", "absent", ["spine_switch_profile", "spine_switch_selector", "selector_type"]], + ["state", "present", ["spine_switch_profile", "spine_switch_selector", "selector_type"]], + ], + ) + + spine_switch_profile = module.params.get("spine_switch_profile") + spine_switch_selector = module.params.get("spine_switch_selector") + description = module.params.get("description") + policy_group = module.params.get("policy_group") + selector_type = MATCH_ACCESS_POLICIES_SELECTOR_TYPE.get(module.params.get("selector_type")) + state = module.params.get("state") + + child_configs = [] + if policy_group is not None: + child_configs.append(dict(infraRsSpineAccNodePGrp=dict(attributes=dict(tDn="uni/infra/funcprof/spaccnodepgrp-{0}".format(policy_group))))) + + aci = ACIModule(module) + + aci.construct_url( + root_class=dict( + aci_class="infraInfra", + aci_rn="infra", + ), + subclass_1=dict( + aci_class="infraSpineP", + aci_rn="spprof-{0}".format(spine_switch_profile), + module_object=spine_switch_profile, + target_filter={"name": spine_switch_profile}, + ), + subclass_2=dict( + aci_class="infraSpineS", + aci_rn="spines-{0}-typ-{1}".format(spine_switch_selector, selector_type), + module_object=spine_switch_selector, + target_filter={"name": spine_switch_selector}, + ), + child_classes=["infraRsSpineAccNodePGrp"], + ) + + aci.get_existing() + + if state == "present": + aci.payload( + aci_class="infraSpineS", + class_config=dict( + descr=description, + name=spine_switch_selector, + type=selector_type, + ), + child_configs=child_configs, + ) + + aci.get_diff(aci_class="infraSpineS") + + aci.post_config() + + elif state == "absent": + aci.delete_config() + + aci.exit_json() + + +if __name__ == "__main__": + main() diff --git a/ansible_collections/cisco/aci/plugins/modules/aci_access_sub_port_block_to_access_port.py b/ansible_collections/cisco/aci/plugins/modules/aci_access_sub_port_block_to_access_port.py index 8073c6ca2..a3006ad4c 100644 --- a/ansible_collections/cisco/aci/plugins/modules/aci_access_sub_port_block_to_access_port.py +++ b/ansible_collections/cisco/aci/plugins/modules/aci_access_sub_port_block_to_access_port.py @@ -13,7 +13,7 @@ ANSIBLE_METADATA = {"metadata_version": "1.1", "status": ["preview"], "supported 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) +short_description: Manage sub port blocks of Fabric interface policy leaf profile interface selectors (infra:HPortS and infra:SubPortBlk) description: - Manage sub port blocks of Fabric interface policy leaf profile interface selectors on Cisco ACI fabrics. seealso: diff --git a/ansible_collections/cisco/aci/plugins/modules/aci_access_switch_policy_group.py b/ansible_collections/cisco/aci/plugins/modules/aci_access_switch_policy_group.py new file mode 100644 index 000000000..d1ed40408 --- /dev/null +++ b/ansible_collections/cisco/aci/plugins/modules/aci_access_switch_policy_group.py @@ -0,0 +1,600 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- + +# Copyright: (c) 2023, Tim Cragg (@timcragg) +# Copyright: (c) 2023, Akini Ross (@akinross) +# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) + +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_access_switch_policy_group +short_description: Manage Access Switch Policy Groups (infra:AccNodePGrp and infra:SpineAccNodePGrp). +description: +- Manage Access Switch Policy Groups on Cisco ACI fabrics. +options: + name: + description: + - The name of the access switch policy group. + aliases: [ policy_group ] + type: str + description: + description: + - The description of the access switch policy group. + type: str + switch_type: + description: + - Whether this is a leaf or spine policy group + type: str + choices: [ leaf, spine ] + required: true + spanning_tree_policy: + description: + - The spanning tree policy bound to the access switch policy group. + - Only available in APIC version 5.2 or later. + - Only available when I(switch_type=leaf). + - The APIC defaults to C("") which results in the target DN set to the default policy when unset during creation. + type: str + bfd_ipv4_policy: + description: + - The BFD IPv4 policy bound to the access switch policy group. + - The APIC defaults to C("") which results in the target DN set to the default policy when unset during creation. + type: str + bfd_ipv6_policy: + description: + - The BFD IPv6 policy bound to the access switch policy group. + - The APIC defaults to C("") which results in the target DN set to the default policy when unset during creation. + type: str + bfd_multihop_ipv4_policy: + description: + - The BFD multihop IPv4 policy bound to the access switch policy group. + - Only available in APIC version 5.x or later. + - Only available when I(switch_type=leaf). + - The APIC defaults to C("") which results in the target DN set to the default policy when unset during creation. + type: str + bfd_multihop_ipv6_policy: + description: + - The BFD multihop IPv6 policy bound to the access switch policy group. + - Only available in APIC version 5.x or later. + - Only available when I(switch_type=leaf). + - The APIC defaults to C("") which results in the target DN set to the default policy when unset during creation. + type: str + fibre_channel_node_policy: + description: + - The fibre channel node policy bound to the access switch policy group. + - Only available when I(switch_type=leaf). + - The APIC defaults to C("") which results in the target DN set to the default policy when unset during creation. + type: str + poe_node_policy: + description: + - The PoE node policy bound to the access switch policy group. + - Only available when I(switch_type=leaf). + - The APIC defaults to C("") which results in the target DN set to the default policy when unset during creation. + type: str + fibre_channel_san_policy: + description: + - The fibre channel SAN policy bound to the access switch policy group. + - Only available when I(switch_type=leaf). + - The APIC defaults to C("") which results in the target DN set to the default policy when unset during creation. + type: str + monitoring_policy: + description: + - The monitoring policy bound to the access switch policy group. + - Only available when I(switch_type=leaf). + - The APIC defaults to C("") which results in the target DN set to the default policy when unset during creation. + type: str + netflow_node_policy: + description: + - The netflow node policy bound to the access switch policy group. + - Only available when I(switch_type=leaf). + - The APIC defaults to C("") which results in the target DN set to the default policy when unset during creation. + type: str + copp_policy: + description: + - The CoPP policy bound to the access switch policy group. + - The APIC defaults to C("") which results in the target DN set to the default policy when unset during creation. + type: str + forward_scale_profile_policy: + description: + - The forward scale profile policy bound to the access switch policy group. + - Only available when I(switch_type=leaf). + - The APIC defaults to C("") which results in the target DN set to the default policy when unset during creation. + type: str + fast_link_failover_policy: + description: + - The fast link failover policy bound to the access switch policy group. + - Only available when I(switch_type=leaf). + - The APIC defaults to C("") which results in the target DN set to the default policy when unset during creation. + type: str + node_802_1x_authentication_policy: + description: + - The 802.1x node authentication policy bound to the access switch policy group. + - Only available when I(switch_type=leaf). + - The APIC defaults to C("") which results in the target DN set to the default policy when unset during creation. + type: str + copp_pre_filter_policy: + description: + - The CoPP pre-filter policy bound to the access switch policy group. + - The APIC defaults to C("") which results in the target DN set to the default policy when unset during creation. + type: str + equipment_flash_policy: + description: + - The equipment flash policy bound to the access switch policy group. + - Only available when I(switch_type=leaf). + - The APIC defaults to C("") which results in the target DN set to the default policy when unset during creation. + type: str + cdp_policy: + description: + - The CDP policy bound to the access switch policy group. + - The APIC defaults to C("") which results in the target DN set to the default policy when unset during creation. + type: str + lldp_policy: + description: + - The LLDP policy bound to the access switch policy group. + - The APIC defaults to C("") which results in the target DN set to the default policy when unset during creation. + type: str + sync_e_node_policy: + description: + - The SyncE node policy bound to the access switch policy group. + - Only available in APIC version 5.x or later. + - Only available when I(switch_type=leaf). + - The APIC defaults to C("") which results in the target DN set to the default policy when unset during creation. + type: str + ptp_node_policy: + description: + - The PTP node policy bound to the access switch policy group. + - Only available in APIC version 5.2 or later. + - Only available when I(switch_type=leaf). + - The APIC defaults to C("") which results in the target DN set to the default policy when unset during creation. + type: str + usb_configuration_policy: + description: + - The USB configuration policy bound to the access switch policy group. + - Only available in APIC version 5.2 or later. + - The APIC defaults to C("") which results in the target DN set to the default policy when unset during creation. + type: str + state: + description: + - Use C(present) or C(absent) for adding or removing. + - Use C(query) for listing an object or multiple objects. + type: str + choices: [ absent, present, query ] + default: present +extends_documentation_fragment: +- cisco.aci.aci +- cisco.aci.annotation +- cisco.aci.owner + +seealso: +- name: APIC Management Information Model reference + description: More information about the internal APIC class B(infra:AccNodePGrp) and B(infra:SpineAccNodePGrp). + link: https://developer.cisco.com/docs/apic-mim-ref/ +author: +- Tim Cragg (@timcragg) +- Akini Ross (@akinross) +""" + +EXAMPLES = r""" +- name: Create Leaf Access Switch Policy Group + cisco.aci.aci_access_switch_policy_group: + host: apic + username: admin + password: SomeSecretPassword + name: ansible_pol_grp_spine + switch_type: leaf + spanning_tree_policy: example_spanning_tree_policy + bfd_ipv4_policy: example_bfd_ipv4_policy + bfd_ipv6_policy: example_bfd_ipv6_policy + fibre_channel_node_policy: example_fibre_channel_node_policy + poe_node_policy: example_poe_node_policy + fibre_channel_san_policy: example_fibre_channel_san_policy + monitoring_policy: example_monitoring_policy + copp_policy: example_copp_policy + forward_scale_profile_policy: example_forward_scale_profile_policy + fast_link_failover_policy: example_fast_link_failover_policy + node_802_1x_authentication_policy: example_node_802_1x_authentication_policy + copp_pre_filter_policy: example_copp_pre_filter_policy + equipment_flash_policy: example_equipment_flash_policy + cdp_policy: example_cdp_policy + lldp_policy: example_lldp_policy + state: present + delegate_to: localhost + +- name: Create Spine Access Switch Policy Group + cisco.aci.aci_access_switch_policy_group: + host: apic + username: admin + password: SomeSecretPassword + name: ansible_pol_grp_leaf + switch_type: spine + bfd_ipv4_policy: example_bfd_ipv4_policy + bfd_ipv6_policy: example_bfd_ipv6_policy + copp_policy: example_copp_policy + copp_pre_filter_policy: example_copp_pre_filter_policy + cdp_policy: example_cdp_policy + lldp_policy: example_lldp_policy + state: present + delegate_to: localhost + +- name: Delete Leaf Access Switch Policy Group + cisco.aci.aci_access_switch_policy_group: + host: apic + username: admin + password: SomeSecretPassword + name: ansible_pol_grp_leaf + switch_type: leaf + state: absent + delegate_to: localhost + +- name: Query Leaf Access Switch Policy Group + cisco.aci.aci_access_switch_policy_group: + host: apic + username: admin + password: SomeSecretPassword + name: ansible_pol_grp_leaf + switch_type: leaf + state: query + delegate_to: localhost + register: query_result + +- name: Query All Leaf Access Switch Policy Groups + cisco.aci.aci_access_switch_policy_group: + host: apic + username: admin + password: SomeSecretPassword + switch_type: leaf + state: query + delegate_to: localhost + register: query_result +""" + +RETURN = r""" + current: + description: The existing configuration from the APIC after the module has finished + returned: success + type: list + sample: + [ + { + "fvTenant": { + "attributes": { + "descr": "Production environment", + "dn": "uni/tn-production", + "name": "production", + "nameAlias": "", + "ownerKey": "", + "ownerTag": "" + } + } + } + ] + error: + description: The error information as returned from the APIC + returned: failure + type: dict + sample: + { + "code": "122", + "text": "unknown managed object class foo" + } + raw: + description: The raw output returned by the APIC REST API (xml or json) + returned: parse error + type: str + sample: '' + sent: + description: The actual/minimal configuration pushed to the APIC + returned: info + type: list + sample: + { + "fvTenant": { + "attributes": { + "descr": "Production environment" + } + } + } + previous: + description: The original configuration from the APIC before the module has started + returned: info + type: list + sample: + [ + { + "fvTenant": { + "attributes": { + "descr": "Production", + "dn": "uni/tn-production", + "name": "production", + "nameAlias": "", + "ownerKey": "", + "ownerTag": "" + } + } + } + ] + proposed: + description: The assembled configuration from the user-provided parameters + returned: info + type: dict + sample: + { + "fvTenant": { + "attributes": { + "descr": "Production environment", + "name": "production" + } + } + } + filter_string: + description: The filter string used for the request + returned: failure or debug + type: str + sample: ?rsp-prop-include=config-only + method: + description: The HTTP method used for the request to the APIC + returned: failure or debug + type: str + sample: POST + response: + description: The HTTP response from the APIC + returned: failure or debug + type: str + sample: OK (30 bytes) + status: + description: The HTTP status from the APIC + returned: failure or debug + type: int + sample: 200 + url: + description: The HTTP url used for the request to the APIC + returned: failure or debug + type: str + sample: https://10.11.12.13/api/mo/uni/tn-production.json + """ + +from ansible.module_utils.basic import AnsibleModule +from ansible_collections.cisco.aci.plugins.module_utils.aci import ACIModule, aci_argument_spec, aci_annotation_spec, aci_owner_spec +from ansible_collections.cisco.aci.plugins.module_utils.constants import ACI_ACCESS_SWITCH_POLICY_GROUP_CLASS_MAPPING + + +def main(): + argument_spec = aci_argument_spec() + argument_spec.update(aci_annotation_spec()) + argument_spec.update(aci_owner_spec()) + argument_spec.update( + name=dict(type="str", aliases=["policy_group"]), + description=dict(type="str"), + switch_type=dict(type="str", choices=["leaf", "spine"], required=True), + spanning_tree_policy=dict(type="str"), + bfd_ipv4_policy=dict(type="str"), + bfd_ipv6_policy=dict(type="str"), + bfd_multihop_ipv4_policy=dict(type="str"), + bfd_multihop_ipv6_policy=dict(type="str"), + fibre_channel_node_policy=dict(type="str"), + poe_node_policy=dict(type="str"), + fibre_channel_san_policy=dict(type="str"), + monitoring_policy=dict(type="str"), + netflow_node_policy=dict(type="str"), + copp_policy=dict(type="str"), + forward_scale_profile_policy=dict(type="str"), + fast_link_failover_policy=dict(type="str"), + node_802_1x_authentication_policy=dict(type="str"), + copp_pre_filter_policy=dict(type="str"), + equipment_flash_policy=dict(type="str"), + cdp_policy=dict(type="str"), + lldp_policy=dict(type="str"), + sync_e_node_policy=dict(type="str"), + ptp_node_policy=dict(type="str"), + usb_configuration_policy=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", ["name"]], + ["state", "present", ["name"]], + ], + ) + name = module.params.get("name") + description = module.params.get("description") + switch_type = module.params.get("switch_type") + spanning_tree_policy = module.params.get("spanning_tree_policy") + bfd_ipv4_policy = module.params.get("bfd_ipv4_policy") + bfd_ipv6_policy = module.params.get("bfd_ipv6_policy") + bfd_multihop_ipv4_policy = module.params.get("bfd_multihop_ipv4_policy") + bfd_multihop_ipv6_policy = module.params.get("bfd_multihop_ipv6_policy") + fibre_channel_node_policy = module.params.get("fibre_channel_node_policy") + poe_node_policy = module.params.get("poe_node_policy") + fibre_channel_san_policy = module.params.get("fibre_channel_san_policy") + monitoring_policy = module.params.get("monitoring_policy") + netflow_node_policy = module.params.get("netflow_node_policy") + copp_policy = module.params.get("copp_policy") + forward_scale_profile_policy = module.params.get("forward_scale_profile_policy") + fast_link_failover_policy = module.params.get("fast_link_failover_policy") + node_802_1x_authentication_policy = module.params.get("node_802_1x_authentication_policy") + copp_pre_filter_policy = module.params.get("copp_pre_filter_policy") + equipment_flash_policy = module.params.get("equipment_flash_policy") + cdp_policy = module.params.get("cdp_policy") + lldp_policy = module.params.get("lldp_policy") + sync_e_node_policy = module.params.get("sync_e_node_policy") + ptp_node_policy = module.params.get("ptp_node_policy") + usb_configuration_policy = module.params.get("usb_configuration_policy") + state = module.params.get("state") + + aci = ACIModule(module) + + if switch_type == "spine" and not all( + v is None + for v in [ + spanning_tree_policy, + bfd_multihop_ipv4_policy, + bfd_multihop_ipv6_policy, + fibre_channel_node_policy, + poe_node_policy, + fibre_channel_san_policy, + monitoring_policy, + netflow_node_policy, + forward_scale_profile_policy, + fast_link_failover_policy, + node_802_1x_authentication_policy, + equipment_flash_policy, + sync_e_node_policy, + ptp_node_policy, + ] + ): + aci.fail_json(msg="Unsupported policy provided for spine switch type.") + + class_name = ACI_ACCESS_SWITCH_POLICY_GROUP_CLASS_MAPPING.get(switch_type).get("class_name") + + aci.construct_url( + root_class=dict( + aci_class=class_name, + aci_rn=ACI_ACCESS_SWITCH_POLICY_GROUP_CLASS_MAPPING.get(switch_type).get("rn").format(name), + module_object=name, + target_filter={"name": name}, + ), + rsp_subtree="children", + ) + + aci.get_existing() + + if state == "present": + child_configs = [] + if forward_scale_profile_policy is not None: + child_configs.append({"infraRsTopoctrlFwdScaleProfPol": {"attributes": {"tnTopoctrlFwdScaleProfilePolName": forward_scale_profile_policy}}}) + if usb_configuration_policy is not None: + child_configs.append( + { + ACI_ACCESS_SWITCH_POLICY_GROUP_CLASS_MAPPING.get(switch_type) + .get("usb_configuration_policy") + .get("class_name"): { + "attributes": { + ACI_ACCESS_SWITCH_POLICY_GROUP_CLASS_MAPPING.get(switch_type) + .get("usb_configuration_policy") + .get("tn_name"): usb_configuration_policy + } + } + } + ) + if lldp_policy is not None: + child_configs.append( + { + ACI_ACCESS_SWITCH_POLICY_GROUP_CLASS_MAPPING.get(switch_type) + .get("lldp_policy") + .get("class_name"): { + "attributes": {ACI_ACCESS_SWITCH_POLICY_GROUP_CLASS_MAPPING.get(switch_type).get("lldp_policy").get("tn_name"): lldp_policy} + } + } + ) + if cdp_policy is not None: + child_configs.append( + { + ACI_ACCESS_SWITCH_POLICY_GROUP_CLASS_MAPPING.get(switch_type) + .get("cdp_policy") + .get("class_name"): { + "attributes": {ACI_ACCESS_SWITCH_POLICY_GROUP_CLASS_MAPPING.get(switch_type).get("cdp_policy").get("tn_name"): cdp_policy} + } + } + ) + if bfd_ipv4_policy is not None: + child_configs.append( + { + ACI_ACCESS_SWITCH_POLICY_GROUP_CLASS_MAPPING.get(switch_type) + .get("bfd_ipv4_policy") + .get("class_name"): { + "attributes": {ACI_ACCESS_SWITCH_POLICY_GROUP_CLASS_MAPPING.get(switch_type).get("bfd_ipv4_policy").get("tn_name"): bfd_ipv4_policy} + } + } + ) + if bfd_ipv6_policy is not None: + child_configs.append( + { + ACI_ACCESS_SWITCH_POLICY_GROUP_CLASS_MAPPING.get(switch_type) + .get("bfd_ipv6_policy") + .get("class_name"): { + "attributes": {ACI_ACCESS_SWITCH_POLICY_GROUP_CLASS_MAPPING.get(switch_type).get("bfd_ipv6_policy").get("tn_name"): bfd_ipv6_policy} + } + } + ) + if sync_e_node_policy is not None: + child_configs.append({"infraRsSynceInstPol": {"attributes": {"tnSynceInstPolName": sync_e_node_policy}}}) + if poe_node_policy is not None: + child_configs.append({"infraRsPoeInstPol": {"attributes": {"tnPoeInstPolName": poe_node_policy}}}) + if bfd_multihop_ipv4_policy is not None: + child_configs.append({"infraRsBfdMhIpv4InstPol": {"attributes": {"tnBfdMhIpv4InstPolName": bfd_multihop_ipv4_policy}}}) + if bfd_multihop_ipv6_policy is not None: + child_configs.append({"infraRsBfdMhIpv6InstPol": {"attributes": {"tnBfdMhIpv6InstPolName": bfd_multihop_ipv6_policy}}}) + if equipment_flash_policy is not None: + child_configs.append({"infraRsEquipmentFlashConfigPol": {"attributes": {"tnEquipmentFlashConfigPolName": equipment_flash_policy}}}) + if monitoring_policy is not None: + child_configs.append({"infraRsMonNodeInfraPol": {"attributes": {"tnMonInfraPolName": monitoring_policy}}}) + if fibre_channel_node_policy is not None: + child_configs.append({"infraRsFcInstPol": {"attributes": {"tnFcInstPolName": fibre_channel_node_policy}}}) + if fast_link_failover_policy is not None: + child_configs.append( + {"infraRsTopoctrlFastLinkFailoverInstPol": {"attributes": {"tnTopoctrlFastLinkFailoverInstPolName": fast_link_failover_policy}}} + ) + if spanning_tree_policy is not None: + child_configs.append({"infraRsMstInstPol": {"attributes": {"tnStpInstPolName": spanning_tree_policy}}}) + if fibre_channel_san_policy is not None: + child_configs.append({"infraRsFcFabricPol": {"attributes": {"tnFcFabricPolName": fibre_channel_san_policy}}}) + if copp_policy is not None: + child_configs.append( + { + ACI_ACCESS_SWITCH_POLICY_GROUP_CLASS_MAPPING.get(switch_type) + .get("copp_policy") + .get("class_name"): { + "attributes": {ACI_ACCESS_SWITCH_POLICY_GROUP_CLASS_MAPPING.get(switch_type).get("copp_policy").get("tn_name"): copp_policy} + } + } + ) + if node_802_1x_authentication_policy is not None: + child_configs.append({"infraRsL2NodeAuthPol": {"attributes": {"tnL2NodeAuthPolName": node_802_1x_authentication_policy}}}) + if copp_pre_filter_policy is not None: + child_configs.append( + { + ACI_ACCESS_SWITCH_POLICY_GROUP_CLASS_MAPPING.get(switch_type) + .get("copp_pre_filter_policy") + .get("class_name"): { + "attributes": { + ACI_ACCESS_SWITCH_POLICY_GROUP_CLASS_MAPPING.get(switch_type).get("copp_pre_filter_policy").get("tn_name"): copp_pre_filter_policy + } + } + } + ) + if netflow_node_policy is not None: + child_configs.append({"infraRsNetflowNodePol": {"attributes": {"tnNetflowNodePolName": netflow_node_policy}}}) + if ptp_node_policy is not None: + child_configs.append({"infraRsPtpInstPol": {"attributes": {"tnPtpInstPolName": ptp_node_policy}}}) + + if child_configs == []: + child_configs = None + + aci.payload( + aci_class=class_name, + class_config=dict( + descr=description, + ), + child_configs=child_configs, + ) + + aci.get_diff(aci_class=class_name) + + aci.post_config() + + elif state == "absent": + aci.delete_config() + + aci.exit_json() + + +if __name__ == "__main__": + main() diff --git a/ansible_collections/cisco/aci/plugins/modules/aci_action_rule_additional_communities.py b/ansible_collections/cisco/aci/plugins/modules/aci_action_rule_additional_communities.py new file mode 100644 index 000000000..c6bd998d9 --- /dev/null +++ b/ansible_collections/cisco/aci/plugins/modules/aci_action_rule_additional_communities.py @@ -0,0 +1,304 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- + +# Copyright: (c) 2023, Gaspard Micol (@gmicol) +# 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_action_rule_additional_communities +short_description: Manage Action Rules based on Additional Communities (rtctrl:SetAddComm) +description: +- Set additional communities for the action rule profiles on Cisco ACI fabrics. +options: + tenant: + description: + - The name of the tenant. + type: str + aliases: [ tenant_name ] + action_rule: + description: + - The name of the action rule profile. + type: str + aliases: [ action_rule_name ] + community: + description: + - The community value. + type: str + criteria: + description: + - The community criteria. + - The option to append or replace the community value. + type: str + choices: [ append, replace, none ] + description: + description: + - The description for the action rule 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 +- cisco.aci.annotation + +notes: +- The C(tenant) and the C(action_rule) used must exist before using this module in your playbook. + The M(cisco.aci.aci_tenant) and M(cisco.aci.aci_tenant_action_rule_profile) modules can be used for this. +seealso: +- module: cisco.aci.aci_tenant +- module: cisco.aci.aci_tenant_action_rule_profile +- name: APIC Management Information Model reference + description: More information about the internal APIC class B(rtctrl:SetAddComm). + link: https://developer.cisco.com/docs/apic-mim-ref/ +author: +- Gaspard Micol (@gmicol) +""" + +EXAMPLES = r""" +- name: Create an additional communities action rule + cisco.aci.aci_action_rule_additional_communities: + host: apic + username: admin + password: SomeSecretPassword + action_rule: my_action_rule + tenant: prod + community: no-advertise + criteria: replace + state: present + delegate_to: localhost + +- name: Delete an additional communities action rule + cisco.aci.aci_action_rule_additional_communities: + host: apic + username: admin + password: SomeSecretPassword + action_rule: my_action_rule + tenant: prod + community: no-advertise + state: absent + delegate_to: localhost + +- name: Query all additional communities action rules + cisco.aci.aci_action_rule_additional_communities: + host: apic + username: admin + password: SomeSecretPassword + state: query + delegate_to: localhost + register: query_result + +- name: Query an additional communities action rule + cisco.aci.aci_action_rule_additional_communities: + host: apic + username: admin + password: SomeSecretPassword + action_rule: my_action_rule + tenant: prod + community: no-advertise + state: query + delegate_to: localhost + register: query_result +""" + +RETURN = r""" +current: + description: The existing configuration from the APIC after the module has finished + returned: success + type: list + sample: + [ + { + "fvTenant": { + "attributes": { + "descr": "Production environment", + "dn": "uni/tn-production", + "name": "production", + "nameAlias": "", + "ownerKey": "", + "ownerTag": "" + } + } + } + ] +error: + description: The error information as returned from the APIC + returned: failure + type: dict + sample: + { + "code": "122", + "text": "unknown managed object class foo" + } +raw: + description: The raw output returned by the APIC REST API (xml or json) + returned: parse error + type: str + sample: '' +sent: + description: The actual/minimal configuration pushed to the APIC + returned: info + type: list + sample: + { + "fvTenant": { + "attributes": { + "descr": "Production environment" + } + } + } +previous: + description: The original configuration from the APIC before the module has started + returned: info + type: list + sample: + [ + { + "fvTenant": { + "attributes": { + "descr": "Production", + "dn": "uni/tn-production", + "name": "production", + "nameAlias": "", + "ownerKey": "", + "ownerTag": "" + } + } + } + ] +proposed: + description: The assembled configuration from the user-provided parameters + returned: info + type: dict + sample: + { + "fvTenant": { + "attributes": { + "descr": "Production environment", + "name": "production" + } + } + } +filter_string: + description: The filter string used for the request + returned: failure or debug + type: str + sample: ?rsp-prop-include=config-only +method: + description: The HTTP method used for the request to the APIC + returned: failure or debug + type: str + sample: POST +response: + description: The HTTP response from the APIC + returned: failure or debug + type: str + sample: OK (30 bytes) +status: + description: The HTTP status from the APIC + returned: failure or debug + type: int + sample: 200 +url: + description: The HTTP url used for the request to the APIC + returned: failure or debug + type: str + sample: https://10.11.12.13/api/mo/uni/tn-production.json +""" + +from ansible.module_utils.basic import AnsibleModule +from ansible_collections.cisco.aci.plugins.module_utils.aci import ACIModule, aci_argument_spec, aci_annotation_spec + + +def main(): + argument_spec = aci_argument_spec() + argument_spec.update(aci_annotation_spec()) + argument_spec.update( + tenant=dict(type="str", aliases=["tenant_name"]), # Not required for querying all objects + action_rule=dict(type="str", aliases=["action_rule_name"]), # Not required for querying all objects + community=dict(type="str"), + criteria=dict(type="str", choices=["append", "replace", "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", "absent", ["action_rule", "tenant", "community"]], + ["state", "present", ["action_rule", "tenant", "community"]], + ], + ) + + community = module.params.get("community") + criteria = module.params.get("criteria") + description = module.params.get("description") + state = module.params.get("state") + tenant = module.params.get("tenant") + action_rule = module.params.get("action_rule") + 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}, + ), + subclass_2=dict( + aci_class="rtctrlSetAddComm", + aci_rn="saddcomm-{0}".format(community), + module_object=community, + target_filter={"community": community}, + ), + ) + + aci.get_existing() + + if state == "present": + aci.payload( + aci_class="rtctrlSetAddComm", + class_config=dict( + community=community, + setCriteria=criteria, + descr=description, + nameAlias=name_alias, + ), + ) + + aci.get_diff(aci_class="rtctrlSetAddComm") + + aci.post_config() + + elif state == "absent": + aci.delete_config() + + aci.exit_json() + + +if __name__ == "__main__": + main() diff --git a/ansible_collections/cisco/aci/plugins/modules/aci_action_rule_set_as_path.py b/ansible_collections/cisco/aci/plugins/modules/aci_action_rule_set_as_path.py new file mode 100644 index 000000000..580cc4cff --- /dev/null +++ b/ansible_collections/cisco/aci/plugins/modules/aci_action_rule_set_as_path.py @@ -0,0 +1,304 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- + +# Copyright: (c) 2023, Gaspard Micol (@gmicol) +# 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_action_rule_set_as_path +short_description: Manage the AS Path action rules (rtctrl:SetASPath) +description: +- Set AS path action rule for the action rule profiles on Cisco ACI fabrics. +options: + tenant: + description: + - The name of the tenant. + type: str + aliases: [ tenant_name ] + action_rule: + description: + - The name of the action rule profile. + type: str + aliases: [ action_rule_name ] + last_as: + description: + - The last AS number value. + type: int + aliases: [ last_as_number ] + criteria: + description: + - The option to append the specified AS number or to prepend the last AS numbers to the AS Path. + type: str + choices: [ prepend, prepend-last-as ] + description: + description: + - The description for the action rule 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 +- cisco.aci.annotation + +notes: +- The C(tenant) and the C(action_rule) used must exist before using this module in your playbook. + The M(cisco.aci.aci_tenant) and M(cisco.aci.aci_tenant_action_rule_profile) modules can be used for this. +seealso: +- module: cisco.aci.aci_tenant +- module: cisco.aci.aci_tenant_action_rule_profile +- name: APIC Management Information Model reference + description: More information about the internal APIC class B(rtctrl:SetASPath). + link: https://developer.cisco.com/docs/apic-mim-ref/ +author: +- Gaspard Micol (@gmicol) +""" + +EXAMPLES = r""" +- name: Create a Set AS path action rule + cisco.aci.aci_action_rule_set_as_path: + host: apic + username: admin + password: SomeSecretPassword + action_rule: my_action_rule + tenant: prod + last_as: 0 + criteria: prepend + state: present + delegate_to: localhost + +- name: Delete a Set AS path action rule + cisco.aci.aci_action_rule_set_as_path: + host: apic + username: admin + password: SomeSecretPassword + action_rule: my_action_rule + tenant: prod + criteria: prepend + state: absent + delegate_to: localhost + +- name: Query all Set AS path action rules + cisco.aci.aci_action_rule_set_as_path: + host: apic + username: admin + password: SomeSecretPassword + state: query + delegate_to: localhost + register: query_result + +- name: Query a Set AS path action rule + cisco.aci.aci_action_rule_set_as_path: + host: apic + username: admin + password: SomeSecretPassword + action_rule: my_action_rule + tenant: prod + criteria: prepend + state: query + delegate_to: localhost + register: query_result +""" + +RETURN = r""" +current: + description: The existing configuration from the APIC after the module has finished + returned: success + type: list + sample: + [ + { + "fvTenant": { + "attributes": { + "descr": "Production environment", + "dn": "uni/tn-production", + "name": "production", + "nameAlias": "", + "ownerKey": "", + "ownerTag": "" + } + } + } + ] +error: + description: The error information as returned from the APIC + returned: failure + type: dict + sample: + { + "code": "122", + "text": "unknown managed object class foo" + } +raw: + description: The raw output returned by the APIC REST API (xml or json) + returned: parse error + type: str + sample: '' +sent: + description: The actual/minimal configuration pushed to the APIC + returned: info + type: list + sample: + { + "fvTenant": { + "attributes": { + "descr": "Production environment" + } + } + } +previous: + description: The original configuration from the APIC before the module has started + returned: info + type: list + sample: + [ + { + "fvTenant": { + "attributes": { + "descr": "Production", + "dn": "uni/tn-production", + "name": "production", + "nameAlias": "", + "ownerKey": "", + "ownerTag": "" + } + } + } + ] +proposed: + description: The assembled configuration from the user-provided parameters + returned: info + type: dict + sample: + { + "fvTenant": { + "attributes": { + "descr": "Production environment", + "name": "production" + } + } + } +filter_string: + description: The filter string used for the request + returned: failure or debug + type: str + sample: ?rsp-prop-include=config-only +method: + description: The HTTP method used for the request to the APIC + returned: failure or debug + type: str + sample: POST +response: + description: The HTTP response from the APIC + returned: failure or debug + type: str + sample: OK (30 bytes) +status: + description: The HTTP status from the APIC + returned: failure or debug + type: int + sample: 200 +url: + description: The HTTP url used for the request to the APIC + returned: failure or debug + type: str + sample: https://10.11.12.13/api/mo/uni/tn-production.json +""" + +from ansible.module_utils.basic import AnsibleModule +from ansible_collections.cisco.aci.plugins.module_utils.aci import ACIModule, aci_argument_spec, aci_annotation_spec + + +def main(): + argument_spec = aci_argument_spec() + argument_spec.update(aci_annotation_spec()) + argument_spec.update( + tenant=dict(type="str", aliases=["tenant_name"]), # Not required for querying all objects + action_rule=dict(type="str", aliases=["action_rule_name"]), # Not required for querying all objects + last_as=dict(type="int", aliases=["last_as_number"]), + criteria=dict(type="str", choices=["prepend", "prepend-last-as"]), + 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", "criteria"]], + ["state", "present", ["action_rule", "tenant", "criteria"]], + ], + ) + + last_as = module.params.get("last_as_number") + criteria = module.params.get("criteria") + description = module.params.get("description") + state = module.params.get("state") + tenant = module.params.get("tenant") + action_rule = module.params.get("action_rule") + 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}, + ), + subclass_2=dict( + aci_class="rtctrlSetASPath", + aci_rn="saspath-{0}".format(criteria), + module_object=criteria, + target_filter={"criteria": criteria}, + ), + ) + + aci.get_existing() + + if state == "present": + aci.payload( + aci_class="rtctrlSetASPath", + class_config=dict( + lastnum=last_as, + criteria=criteria, + descr=description, + nameAlias=name_alias, + ), + ) + + aci.get_diff(aci_class="rtctrlSetASPath") + + aci.post_config() + + elif state == "absent": + aci.delete_config() + + aci.exit_json() + + +if __name__ == "__main__": + main() diff --git a/ansible_collections/cisco/aci/plugins/modules/aci_action_rule_set_as_path_asn.py b/ansible_collections/cisco/aci/plugins/modules/aci_action_rule_set_as_path_asn.py new file mode 100644 index 000000000..fdc675ddb --- /dev/null +++ b/ansible_collections/cisco/aci/plugins/modules/aci_action_rule_set_as_path_asn.py @@ -0,0 +1,312 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- + +# Copyright: (c) 2023, Gaspard Micol (@gmicol) +# 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_action_rule_set_as_path_asn +short_description: Manage the AS Path ASN (rtctrl:SetASPathASN) +description: +- Set the ASN for the AS Path action rules on Cisco ACI fabrics. +- Only used if the AS Path action rule is set to C(prepend). +options: + tenant: + description: + - The name of the tenant. + type: str + aliases: [ tenant_name ] + action_rule: + description: + - The name of the action rule profile. + type: str + aliases: [ action_rule_name ] + asn: + description: + - The ASN number. + type: int + order: + description: + - The ASN order. + type: int + description: + description: + - The description for the action rule 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 +- cisco.aci.annotation + +notes: +- The C(tenant) and the C(action_rule) used must exist before using this module in your playbook. + The M(cisco.aci.aci_tenant) and M(cisco.aci.aci_tenant_action_rule_profile) modules can be used for this. +- A Set AS Path action rule with criteria set to C(prepend) must exist before using this module in your playbook. + The M(cisco.aci.aci_action_rule_set_as_path) modules can be used for this. +seealso: +- module: cisco.aci.aci_tenant +- module: cisco.aci.aci_tenant_action_rule_profile +- module: cisco.aci.aci_action_rule_set_as_path +- name: APIC Management Information Model reference + description: More information about the internal APIC class B(rtctrl:SetASPathASN). + link: https://developer.cisco.com/docs/apic-mim-ref/ +author: +- Gaspard Micol (@gmicol) +""" + +EXAMPLES = r""" +- name: Create a Set AS Path ASN action rule + cisco.aci.aci_action_rule_set_as_path_asn: + host: apic + username: admin + password: SomeSecretPassword + action_rule: my_action_rule + tenant: prod + order: 1 + asn: 1 + state: present + delegate_to: localhost + +- name: Delete a Set AS Path ASN action rule + cisco.aci.aci_action_rule_set_as_path_asn: + host: apic + username: admin + password: SomeSecretPassword + action_rule: my_action_rule + tenant: prod + order: 1 + state: absent + delegate_to: localhost + +- name: Query all Set AS Path ASN action rules + cisco.aci.aci_action_rule_set_as_path_asn: + host: apic + username: admin + password: SomeSecretPassword + state: query + delegate_to: localhost + register: query_result + +- name: Query a Set AS Path ASN action rule + cisco.aci.aci_action_rule_set_as_path_asn: + host: apic + username: admin + password: SomeSecretPassword + action_rule: my_action_rule + tenant: prod + order: 1 + state: query + delegate_to: localhost + register: query_result +""" + +RETURN = r""" +current: + description: The existing configuration from the APIC after the module has finished + returned: success + type: list + sample: + [ + { + "fvTenant": { + "attributes": { + "descr": "Production environment", + "dn": "uni/tn-production", + "name": "production", + "nameAlias": "", + "ownerKey": "", + "ownerTag": "" + } + } + } + ] +error: + description: The error information as returned from the APIC + returned: failure + type: dict + sample: + { + "code": "122", + "text": "unknown managed object class foo" + } +raw: + description: The raw output returned by the APIC REST API (xml or json) + returned: parse error + type: str + sample: '' +sent: + description: The actual/minimal configuration pushed to the APIC + returned: info + type: list + sample: + { + "fvTenant": { + "attributes": { + "descr": "Production environment" + } + } + } +previous: + description: The original configuration from the APIC before the module has started + returned: info + type: list + sample: + [ + { + "fvTenant": { + "attributes": { + "descr": "Production", + "dn": "uni/tn-production", + "name": "production", + "nameAlias": "", + "ownerKey": "", + "ownerTag": "" + } + } + } + ] +proposed: + description: The assembled configuration from the user-provided parameters + returned: info + type: dict + sample: + { + "fvTenant": { + "attributes": { + "descr": "Production environment", + "name": "production" + } + } + } +filter_string: + description: The filter string used for the request + returned: failure or debug + type: str + sample: ?rsp-prop-include=config-only +method: + description: The HTTP method used for the request to the APIC + returned: failure or debug + type: str + sample: POST +response: + description: The HTTP response from the APIC + returned: failure or debug + type: str + sample: OK (30 bytes) +status: + description: The HTTP status from the APIC + returned: failure or debug + type: int + sample: 200 +url: + description: The HTTP url used for the request to the APIC + returned: failure or debug + type: str + sample: https://10.11.12.13/api/mo/uni/tn-production.json +""" + +from ansible.module_utils.basic import AnsibleModule +from ansible_collections.cisco.aci.plugins.module_utils.aci import ACIModule, aci_argument_spec, aci_annotation_spec + + +def main(): + argument_spec = aci_argument_spec() + argument_spec.update(aci_annotation_spec()) + argument_spec.update( + tenant=dict(type="str", aliases=["tenant_name"]), # Not required for querying all objects + action_rule=dict(type="str", aliases=["action_rule_name"]), # Not required for querying all objects + asn=dict(type="int"), + order=dict(type="int"), + 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", "order"]], + ["state", "present", ["action_rule", "tenant", "order"]], + ], + ) + + asn = module.params.get("asn") + order = module.params.get("order") + description = module.params.get("description") + state = module.params.get("state") + tenant = module.params.get("tenant") + action_rule = module.params.get("action_rule") + 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}, + ), + subclass_2=dict( + aci_class="rtctrlSetASPath", + aci_rn="saspath-prepend", + module_object="prepend", + target_filter={"criteria": "prepend"}, + ), + subclass_3=dict( + aci_class="rtctrlSetASPathASN", + aci_rn="asn-{0}".format(order), + module_object=order, + target_filter={"asn": order}, + ), + ) + + aci.get_existing() + + if state == "present": + aci.payload( + aci_class="rtctrlSetASPathASN", + class_config=dict( + asn=asn, + order=order, + descr=description, + nameAlias=name_alias, + ), + ) + + aci.get_diff(aci_class="rtctrlSetASPathASN") + + aci.post_config() + + elif state == "absent": + aci.delete_config() + + aci.exit_json() + + +if __name__ == "__main__": + main() diff --git a/ansible_collections/cisco/aci/plugins/modules/aci_aep.py b/ansible_collections/cisco/aci/plugins/modules/aci_aep.py index aa77d8f4f..04ecf58f6 100644 --- a/ansible_collections/cisco/aci/plugins/modules/aci_aep.py +++ b/ansible_collections/cisco/aci/plugins/modules/aci_aep.py @@ -13,7 +13,7 @@ ANSIBLE_METADATA = {"metadata_version": "1.1", "status": ["preview"], "supported DOCUMENTATION = r""" --- module: aci_aep -short_description: Manage attachable Access Entity Profile (AEP) objects (infra:AttEntityP, infra:ProvAcc) +short_description: Manage attachable Access Entity Profile (AEP) objects (infra:AttEntityP and infra:ProvAcc) description: - Connect to external virtual and physical domains by using attachable Access Entity Profiles (AEP) on Cisco ACI fabrics. diff --git a/ansible_collections/cisco/aci/plugins/modules/aci_aep_to_epg.py b/ansible_collections/cisco/aci/plugins/modules/aci_aep_to_epg.py index c77417073..2bba28c5b 100644 --- a/ansible_collections/cisco/aci/plugins/modules/aci_aep_to_epg.py +++ b/ansible_collections/cisco/aci/plugins/modules/aci_aep_to_epg.py @@ -12,7 +12,7 @@ ANSIBLE_METADATA = {"metadata_version": "1.1", "status": ["preview"], "supported DOCUMENTATION = r""" --- module: aci_aep_to_epg -short_description: Bind EPG to AEP (infra:RsFuncToEpg). +short_description: Bind EPG to AEP (infra:RsFuncToEpg) description: - Bind EPG to AEP. options: diff --git a/ansible_collections/cisco/aci/plugins/modules/aci_bd.py b/ansible_collections/cisco/aci/plugins/modules/aci_bd.py index 13d9d1938..d01304cb7 100644 --- a/ansible_collections/cisco/aci/plugins/modules/aci_bd.py +++ b/ansible_collections/cisco/aci/plugins/modules/aci_bd.py @@ -1,6 +1,8 @@ #!/usr/bin/python # -*- coding: utf-8 -*- +# Copyright: (c) 2017, Jacob McGill (@jmcgill298) +# Copyright: (c) 2024, Samita Bhattacharjee (@samitab) # 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 @@ -147,6 +149,103 @@ options: description: - The L3 Out that contains the associated Route Profile. type: str + host_based_routing: + description: + - Enables advertising host routes (/32 prefixes) out of the L3OUT(s) that are associated to this BD. + - The APIC defaults to C(false) when unset during creation. + type: bool + aliases: [ advertise_host_routes ] + enable_rogue_except_mac: + description: + - Rogue exception MAC wildcard support for Bridge Domains. + - Only available in APIC version 6.0 or later. + - The APIC defaults to C(false) when unset during creation. + type: bool + allow_intersite_bum_traffic: + description: + - Control whether BUM traffic is allowed between sites. + - The APIC defaults to C(false) when unset during creation. + type: bool + aliases: [allow_bum_traffic] + allow_intersite_l2_stretch: + description: + - Allow L2 Stretch between sites. + - The APIC defaults to C(false) when unset during creation. + type: bool + aliases: [allow_l2_stretch] + allow_ipv6_multicast: + description: + - Flag to indicate if ipv6 multicast is enabled. + - The APIC defaults to C(false) when unset during creation. + type: bool + aliases: [ ipv6_multicast, ipv6_mcast, allow_ipv6_mcast] + link_local_address: + description: + - The override of the system generated IPv6 link-local address. + type: str + aliases: [ ll_addr_ipv6, ll_addr, link_local] + multicast_arp_drop: + description: + - Enable BD rogue multicast ARP packet drop. + - Only available in APIC version 6.0 or later. + - The APIC defaults to C(true) when unset during creation. + type: bool + aliases: [ mcast_arp_drop ] + vmac: + description: + - Virtual MAC address of the BD/SVI. This is used when the BD is extended to multiple sites using L2 Outside. + type: str + optimize_wan_bandwidth: + description: + - Optimize WAN Bandwidth improves the network application experience at the branch and makes better use of limited network resources. + - The APIC defaults to C(false) when unset during creation. + type: bool + aliases: [wan_optimization, opt_bandwidth] + mld_snoop_policy: + description: + - The name of the Multicast Listener Discovery (MLD) Snooping Policy the Bridge Domain should use when overriding the default MLD Snooping Policy. + - To delete this attribute, pass an empty string. + type: str + aliases: [mld_snoop, mld_policy] + igmp_policy: + description: + - The name of the IGMP Interface Policy the Bridge Domain should use when overriding the default IGMP Interface Policy. + - To delete this attribute, pass an empty string. + type: str + aliases: [igmp] + vlan: + description: + - The selected VLAN for bridge domain access port encapsulation. + - To delete this attribute, pass an empty string. + type: str + aliases: [encap] + monitoring_policy: + description: + - The name of the Monitoring Policy to apply to the Bridge Domain. + - To delete this attribute, pass an empty string. + type: str + aliases: [mon_pol, monitoring_pol] + first_hop_security_policy: + description: + - The name of the First Hop Security Policy to apply to the Bridge Domain. + - To delete this attribute, pass an empty string. + type: str + aliases: [fhsp, fhs_pol, fhsp_name] + pim_source_filter: + description: + - The name of the PIM Source Filter to apply to the Bridge Domain. + - To delete this attribute, pass an empty string. + - Only available in APIC version 5.2 or later. + type: str + aliases: [pim_source] + pim_destination_filter: + description: + - The name of the PIM Destination Filter to apply to the Bridge Domain. + - To delete this attribute, pass an empty string. + - Only available in APIC version 5.2 or later. + type: str + aliases: [pim_dest, pim_destination] + extends_documentation_fragment: - cisco.aci.aci - cisco.aci.annotation @@ -162,6 +261,7 @@ seealso: link: https://developer.cisco.com/docs/apic-mim-ref/ author: - Jacob McGill (@jmcgill298) +- Samita Bhattacharjee (@samitab) """ EXAMPLES = r""" @@ -175,6 +275,19 @@ EXAMPLES = r""" bd: web_servers mac_address: 00:22:BD:F8:19:FE vrf: prod_vrf + host_based_routing: true + allow_intersite_bum_traffic: true + allow_intersite_l2_stretch: true + allow_ipv6_mcast: true + ll_addr: "fe80::1322:33ff:fe44:5566" + vmac: "00:AA:BB:CC:DD:03" + optimize_wan_bandwidth: true + vlan: vlan-101 + igmp_policy: web_servers_igmp_pol + monitoring_policy: web_servers_monitoring_pol + igmp_snoop_policy: web_servers_igmp_snoop + mld_snoop_policy: web_servers_mld_snoop + first_hop_security_policy: web_servers_fhs state: present delegate_to: localhost @@ -205,6 +318,21 @@ EXAMPLES = r""" state: present delegate_to: localhost +- name: Modify a Bridge Domain to remove mld_snoop_policy and first_hop_security_policy + cisco.aci.aci_bd: + host: "{{ inventory_hostname }}" + username: "{{ username }}" + password: "{{ password }}" + validate_certs: true + tenant: prod + bd: web_servers + arp_flooding: true + l2_unknown_unicast: flood + mld_snoop_policy: "" + first_hop_security_policy: "" + state: present + delegate_to: localhost + - name: Query All Bridge Domains cisco.aci.aci_bd: host: "{{ inventory_hostname }}" @@ -378,6 +506,22 @@ def main(): route_profile=dict(type="str"), route_profile_l3out=dict(type="str"), name_alias=dict(type="str"), + host_based_routing=dict(type="bool", aliases=["advertise_host_routes"]), + enable_rogue_except_mac=dict(type="bool"), + allow_intersite_bum_traffic=dict(type="bool", aliases=["allow_bum_traffic"]), + allow_intersite_l2_stretch=dict(type="bool", aliases=["allow_l2_stretch"]), + allow_ipv6_multicast=dict(type="bool", aliases=["ipv6_multicast", "ipv6_mcast", "allow_ipv6_mcast"]), + link_local_address=dict(type="str", aliases=["ll_addr_ipv6", "ll_addr", "link_local"]), + multicast_arp_drop=dict(type="bool", aliases=["mcast_arp_drop"]), + vmac=dict(type="str"), + optimize_wan_bandwidth=dict(type="bool", aliases=["wan_optimization", "opt_bandwidth"]), + mld_snoop_policy=dict(type="str", aliases=["mld_snoop", "mld_policy"]), + igmp_policy=dict(type="str", aliases=["igmp"]), + vlan=dict(type="str", aliases=["encap"]), + monitoring_policy=dict(type="str", aliases=["mon_pol", "monitoring_pol"]), + first_hop_security_policy=dict(type="str", aliases=["fhsp", "fhs_pol", "fhsp_name"]), + pim_source_filter=dict(type="str", aliases=["pim_source"]), + pim_destination_filter=dict(type="str", aliases=["pim_dest", "pim_destination"]), ) module = AnsibleModule( @@ -422,7 +566,47 @@ def main(): route_profile = module.params.get("route_profile") route_profile_l3out = module.params.get("route_profile_l3out") name_alias = module.params.get("name_alias") + host_based_routing = aci.boolean(module.params.get("host_based_routing")) + enable_rogue_except_mac = aci.boolean(module.params.get("enable_rogue_except_mac")) + allow_intersite_bum_traffic = aci.boolean(module.params.get("allow_intersite_bum_traffic")) + allow_intersite_l2_stretch = aci.boolean(module.params.get("allow_intersite_l2_stretch")) + allow_ipv6_multicast = aci.boolean(module.params.get("allow_ipv6_multicast")) + link_local_address = module.params.get("link_local_address") + multicast_arp_drop = aci.boolean(module.params.get("multicast_arp_drop")) + vmac = module.params.get("vmac") + optimize_wan_bandwidth = aci.boolean(module.params.get("optimize_wan_bandwidth")) + mld_snoop_policy = module.params.get("mld_snoop_policy") + igmp_policy = module.params.get("igmp_policy") + vlan = module.params.get("vlan") + monitoring_policy = module.params.get("monitoring_policy") + first_hop_security_policy = module.params.get("first_hop_security_policy") + pim_source_filter = module.params.get("pim_source_filter") + pim_destination_filter = module.params.get("pim_destination_filter") + child_classes = [ + "fvRsCtx", + "fvRsIgmpsn", + "fvRsBDToNdP", + "fvRsBdToEpRet", + "fvRsBDToProfile", + "fvRsMldsn", + "igmpIfP", + "igmpRsIfPol", + "fvAccP", + "fvRsABDPolMonPol", + "fvRsBDToFhs", + ] + if pim_source_filter is not None or pim_destination_filter is not None: + # Only valid for APIC verion 5.2+ + child_classes.extend( + [ + "pimBDP", + "pimBDFilterPol", + "pimBDSrcFilterPol", + "pimBDDestFilterPol", + "rtdmcRsFilterToRtMapPol", + ] + ) aci.construct_url( root_class=dict( aci_class="fvTenant", @@ -436,7 +620,7 @@ def main(): module_object=bd, target_filter={"name": bd}, ), - child_classes=["fvRsCtx", "fvRsIgmpsn", "fvRsBDToNdP", "fvRsBdToEpRet", "fvRsBDToProfile"], + child_classes=child_classes, ) aci.get_existing() @@ -458,22 +642,52 @@ def main(): unkMacUcastAct=l2_unknown_unicast, unkMcastAct=l3_unknown_multicast, nameAlias=name_alias, + enableRogueExceptMac=enable_rogue_except_mac, + hostBasedRouting=host_based_routing, + intersiteBumTrafficAllow=allow_intersite_bum_traffic, + intersiteL2Stretch=allow_intersite_l2_stretch, + ipv6McastAllow=allow_ipv6_multicast, + llAddr=link_local_address, + mcastARPDrop=multicast_arp_drop, + vmac=vmac, + OptimizeWanBandwidth=optimize_wan_bandwidth, ) if ipv6_l3_unknown_multicast is not None: class_config["v6unkMcastAct"] = ipv6_l3_unknown_multicast - aci.payload( - aci_class="fvBD", - class_config=class_config, - 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}}}, - {"fvRsBDToProfile": {"attributes": {"tnL3extOutName": route_profile_l3out, "tnRtctrlProfileName": route_profile}}}, - ], - ) + child_configs = [ + {"fvRsCtx": {"attributes": {"tnFvCtxName": vrf}}}, + {"fvRsIgmpsn": {"attributes": {"tnIgmpSnoopPolName": igmp_snoop_policy}}}, + {"fvRsMldsn": {"attributes": {"tnMldSnoopPolName": mld_snoop_policy}}}, + {"fvRsBDToNdP": {"attributes": {"tnNdIfPolName": ipv6_nd_policy}}}, + {"fvRsBdToEpRet": {"attributes": {"resolveAct": endpoint_retention_action, "tnFvEpRetPolName": endpoint_retention_policy}}}, + {"fvRsBDToProfile": {"attributes": {"tnL3extOutName": route_profile_l3out, "tnRtctrlProfileName": route_profile}}}, + {"fvRsBDToFhs": {"attributes": {"tnFhsBDPolName": first_hop_security_policy}}}, + {"fvAccP": {"attributes": {"encap": vlan}}}, + {"fvRsABDPolMonPol": {"attributes": {"tnMonEPGPolName": monitoring_policy}}}, + ] + + if igmp_policy is not None: + igmp_policy_tdn = "" if igmp_policy == "" else "uni/tn-{0}/igmpIfPol-{1}".format(tenant, igmp_policy) + child_configs.append({"igmpIfP": {"attributes": {}, "children": [{"igmpRsIfPol": {"attributes": {"tDn": igmp_policy_tdn}}}]}}) + if pim_source_filter is not None or pim_destination_filter is not None: + pim_bd = {"pimBDP": {"attributes": {}, "children": []}} + pim_filter_pol = {"pimBDFilterPol": {"attributes": {}, "children": []}} + if pim_source_filter is not None: + pim_source_filter_tdn = "" if pim_source_filter == "" else "uni/tn-{0}/rtmap-{1}".format(tenant, pim_source_filter) + pim_filter_pol["pimBDFilterPol"]["children"].append( + {"pimBDSrcFilterPol": {"attributes": {}, "children": [{"rtdmcRsFilterToRtMapPol": {"attributes": {"tDn": pim_source_filter_tdn}}}]}} + ) + if pim_destination_filter is not None: + pim_destination_filter_tdn = "" if pim_destination_filter == "" else "uni/tn-{0}/rtmap-{1}".format(tenant, pim_destination_filter) + pim_filter_pol["pimBDFilterPol"]["children"].append( + {"pimBDDestFilterPol": {"attributes": {}, "children": [{"rtdmcRsFilterToRtMapPol": {"attributes": {"tDn": pim_destination_filter_tdn}}}]}} + ) + pim_bd["pimBDP"]["children"].append(pim_filter_pol) + child_configs.append(pim_bd) + + aci.payload(aci_class="fvBD", class_config=class_config, child_configs=child_configs) aci.get_diff(aci_class="fvBD") diff --git a/ansible_collections/cisco/aci/plugins/modules/aci_bd_rogue_exception_mac.py b/ansible_collections/cisco/aci/plugins/modules/aci_bd_rogue_exception_mac.py new file mode 100644 index 000000000..8174f00db --- /dev/null +++ b/ansible_collections/cisco/aci/plugins/modules/aci_bd_rogue_exception_mac.py @@ -0,0 +1,299 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- + +# Copyright: (c) 2024, Samita Bhattacharjee (@samitab) +# 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_rogue_exception_mac +short_description: Manage Rogue Exception MAC (fv:RogueExceptionMac) +description: +- Manage Rogue Exception MACs in BD's on Cisco ACI fabrics. +- Only available in APIC version 5.2 or later. +options: + bd: + description: + - The name of the Bridge Domain. + type: str + aliases: [ bd_name, bridge_domain ] + tenant: + description: + - The name of the Tenant. + type: str + aliases: [ tenant_name ] + mac: + description: + - MAC address to except from Rogue processing. + type: str + description: + description: + - The description for the Rogue Exception MAC. + 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 +extends_documentation_fragment: +- cisco.aci.aci +- cisco.aci.annotation + +notes: +- 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:RogueExceptionMac). + link: https://developer.cisco.com/docs/apic-mim-ref/ +author: +- Samita Bhattacharjee (@samitab) +""" + +EXAMPLES = r""" +- name: Create a Rogue Exception MAC + cisco.aci.aci_bd_rogue_exception_mac: + host: apic + username: admin + password: SomeSecretPassword + tenant: production + bd: database + mac: "AA:BB:CC:DD:EE:11" + description: 1st MAC + state: present + delegate_to: localhost + +- name: Get all Rogue Exception MACs + cisco.aci.aci_bd_rogue_exception_mac: + host: apic + username: admin + password: SomeSecretPassword + state: query + delegate_to: localhost + +- name: Get all Rogue Exception MACs in specified Tenant + cisco.aci.aci_bd_rogue_exception_mac: + host: apic + username: admin + password: SomeSecretPassword + tenant: production + state: query + delegate_to: localhost + register: query_result + +- name: Get specific Rogue Exception MAC + cisco.aci.aci_bd_rogue_exception_mac: + host: apic + username: admin + password: SomeSecretPassword + tenant: production + bd: database + mac: "AA:BB:CC:DD:EE:11" + state: query + delegate_to: localhost + register: query_result + +- name: Remove a Rogue Exception MAC from a Bridge Domain + cisco.aci.aci_bd_rogue_exception_mac: + host: apic + username: admin + password: SomeSecretPassword + tenant: production + bd: database + mac: "AA:BB:CC:DD:EE:11" + 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: '' +sent: + description: The actual/minimal configuration pushed to the APIC + returned: info + type: list + sample: + { + "fvTenant": { + "attributes": { + "descr": "Production environment" + } + } + } +previous: + description: The original configuration from the APIC before the module has started + returned: info + type: list + sample: + [ + { + "fvTenant": { + "attributes": { + "descr": "Production", + "dn": "uni/tn-production", + "name": "production", + "nameAlias": "", + "ownerKey": "", + "ownerTag": "" + } + } + } + ] +proposed: + description: The assembled configuration from the user-provided parameters + returned: info + type: dict + sample: + { + "fvTenant": { + "attributes": { + "descr": "Production environment", + "name": "production" + } + } + } +filter_string: + description: The filter string used for the request + returned: failure or debug + type: str + sample: ?rsp-prop-include=config-only +method: + description: The HTTP method used for the request to the APIC + returned: failure or debug + type: str + sample: POST +response: + description: The HTTP response from the APIC + returned: failure or debug + type: str + sample: OK (30 bytes) +status: + description: The HTTP status from the APIC + returned: failure or debug + type: int + sample: 200 +url: + description: The HTTP url used for the request to the APIC + returned: failure or debug + type: str + sample: https://10.11.12.13/api/mo/uni/tn-production.json +""" + +from ansible.module_utils.basic import AnsibleModule +from ansible_collections.cisco.aci.plugins.module_utils.aci import ACIModule, aci_argument_spec, aci_annotation_spec + + +def main(): + argument_spec = aci_argument_spec() + argument_spec.update(aci_annotation_spec()) + argument_spec.update( + bd=dict(type="str", aliases=["bd_name", "bridge_domain"]), # Not required for querying all objects + tenant=dict(type="str", aliases=["tenant_name"]), # Not required for querying all objects + mac=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"]), + ) + + module = AnsibleModule( + argument_spec=argument_spec, + supports_check_mode=True, + required_if=[ + ["state", "present", ["bd", "mac", "tenant"]], + ["state", "absent", ["bd", "mac", "tenant"]], + ], + ) + + aci = ACIModule(module) + + description = module.params.get("description") + tenant = module.params.get("tenant") + bd = module.params.get("bd") + mac = module.params.get("mac") + state = module.params.get("state") + + 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="fvRogueExceptionMac", + aci_rn="rgexpmac-{0}".format(mac), + module_object=mac, + target_filter={"mac": mac}, + ), + ) + + aci.get_existing() + + if state == "present": + aci.payload( + aci_class="fvRogueExceptionMac", + class_config=dict( + descr=description, + mac=mac, + ), + ) + + aci.get_diff(aci_class="fvRogueExceptionMac") + + aci.post_config() + + elif state == "absent": + aci.delete_config() + + aci.exit_json() + + +if __name__ == "__main__": + main() diff --git a/ansible_collections/cisco/aci/plugins/modules/aci_bd_to_netflow_monitor_policy.py b/ansible_collections/cisco/aci/plugins/modules/aci_bd_to_netflow_monitor_policy.py new file mode 100644 index 000000000..5e79a072c --- /dev/null +++ b/ansible_collections/cisco/aci/plugins/modules/aci_bd_to_netflow_monitor_policy.py @@ -0,0 +1,292 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- + +# Copyright: (c) 2024, Samita Bhattacharjee (@samitab) +# 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_netflow_monitor_policy +short_description: Bind Bridge Domain to Netflow Monitor Policy (fv:RsBDToNetflowMonitorPol) +description: +- Bind Bridge Domain to Netflow Monitor Policy on Cisco ACI fabrics. +options: + bd: + description: + - The name of the Bridge Domain. + type: str + aliases: [ bd_name, bridge_domain ] + tenant: + description: + - The name of the Tenant. + type: str + aliases: [ tenant_name ] + netflow_monitor_policy: + description: + - The name of the Netflow Monitor Policy. + type: str + aliases: [ netflow_monitor, netflow_monitor_name, name ] + filter_type: + description: + - Choice of filter type while setting NetFlow Monitor Policies. + type: str + choices: [ce, ipv4, ipv6, unspecified] + aliases: [ filter, 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 +extends_documentation_fragment: +- cisco.aci.aci +- cisco.aci.annotation + +notes: +- The C(bd) and C(netflow_monitor_policy) parameters should exist before using this module. + The M(cisco.aci.aci_bd) and C(aci_netflow_monitor_policy) can be used for this. +seealso: +- module: cisco.aci.aci_bd +- module: cisco.aci.aci_netflow_monitor_policy +- name: APIC Management Information Model reference + description: More information about the internal APIC class B(fv:RsBDToNetflowMonitorPol). + link: https://developer.cisco.com/docs/apic-mim-ref/ +author: +- Samita Bhattacharjee (@samitab) +""" + +EXAMPLES = r""" +- name: Bind Bridge Domain to Netflow Monitor Policy + cisco.aci.aci_bd_to_netflow_monitor_policy: + host: apic + username: admin + password: SomeSecretPassword + validate_certs: false + bd: web_servers + netflow_monitor_policy: prod_netflow_monitor_policy + tenant: prod + filter_type: ipv4 + state: present + delegate_to: localhost + +- name: Query all Bridge Domains bound to Netflow Monitor Policy + cisco.aci.aci_bd_to_netflow_monitor_policy: + host: apic + username: admin + password: SomeSecretPassword + validate_certs: true + state: query + delegate_to: localhost + register: query_result + +- name: Query specific Bridge Domain(s) bound to an Netflow Monitor Policy + cisco.aci.aci_bd_to_netflow_monitor_policy: + host: apic + username: admin + password: SomeSecretPassword + validate_certs: true + bd: web_servers + netflow_monitor_policy: prod_netflow_monitor_policy + tenant: prod + state: query + delegate_to: localhost + register: query_result + +- name: Unbind Bridge Domain from Netflow Monitor Policy + cisco.aci.aci_bd_to_netflow_monitor_policy: + host: apic + username: admin + password: SomeSecretPassword + validate_certs: true + bd: web_servers + netflow_monitor_policy: prod_netflow_monitor_policy + tenant: prod + filter_type: ipv4 + 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: '' +sent: + description: The actual/minimal configuration pushed to the APIC + returned: info + type: list + sample: + { + "fvTenant": { + "attributes": { + "descr": "Production environment" + } + } + } +previous: + description: The original configuration from the APIC before the module has started + returned: info + type: list + sample: + [ + { + "fvTenant": { + "attributes": { + "descr": "Production", + "dn": "uni/tn-production", + "name": "production", + "nameAlias": "", + "ownerKey": "", + "ownerTag": "" + } + } + } + ] +proposed: + description: The assembled configuration from the user-provided parameters + returned: info + type: dict + sample: + { + "fvTenant": { + "attributes": { + "descr": "Production environment", + "name": "production" + } + } + } +filter_string: + description: The filter string used for the request + returned: failure or debug + type: str + sample: ?rsp-prop-include=config-only +method: + description: The HTTP method used for the request to the APIC + returned: failure or debug + type: str + sample: POST +response: + description: The HTTP response from the APIC + returned: failure or debug + type: str + sample: OK (30 bytes) +status: + description: The HTTP status from the APIC + returned: failure or debug + type: int + sample: 200 +url: + description: The HTTP url used for the request to the APIC + returned: failure or debug + type: str + sample: https://10.11.12.13/api/mo/uni/tn-production.json +""" + +from ansible.module_utils.basic import AnsibleModule +from ansible_collections.cisco.aci.plugins.module_utils.aci import ACIModule, aci_argument_spec, aci_annotation_spec + + +def main(): + argument_spec = aci_argument_spec() + argument_spec.update(aci_annotation_spec()) + argument_spec.update( + bd=dict(type="str", aliases=["bd_name", "bridge_domain"]), # Not required for querying all objects + netflow_monitor_policy=dict(type="str", aliases=["netflow_monitor", "netflow_monitor_name", "name"]), # Not required for querying all objects + filter_type=dict(type="str", choices=["ce", "ipv4", "ipv6", "unspecified"], aliases=["filter", "type"]), # 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", "netflow_monitor_policy", "tenant", "filter_type"]], + ["state", "absent", ["bd", "netflow_monitor_policy", "tenant", "filter_type"]], + ], + ) + + bd = module.params.get("bd") + netflow_monitor_policy = module.params.get("netflow_monitor_policy") + filter_type = module.params.get("filter_type") + 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="fvRsBDToNetflowMonitorPol", + aci_rn="rsBDToNetflowMonitorPol-[{0}]-{1}".format(netflow_monitor_policy, filter_type), + module_object=netflow_monitor_policy, + target_filter={"tnNetflowMonitorPolName": netflow_monitor_policy}, + ), + ) + + aci.get_existing() + + if state == "present": + aci.payload( + aci_class="fvRsBDToNetflowMonitorPol", + class_config=dict(tnNetflowMonitorPolName=netflow_monitor_policy, fltType=filter_type), + ) + + aci.get_diff(aci_class="fvRsBDToNetflowMonitorPol") + + aci.post_config() + + elif state == "absent": + aci.delete_config() + + aci.exit_json() + + +if __name__ == "__main__": + main() diff --git a/ansible_collections/cisco/aci/plugins/modules/aci_bfd_multihop_node_policy.py b/ansible_collections/cisco/aci/plugins/modules/aci_bfd_multihop_node_policy.py new file mode 100644 index 000000000..f684ba15d --- /dev/null +++ b/ansible_collections/cisco/aci/plugins/modules/aci_bfd_multihop_node_policy.py @@ -0,0 +1,320 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- + +# Copyright: (c) 2023, Anvitha Jain (@anvjain) +# 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_bfd_multihop_node_policy +short_description: Manage BFD Multihop Node policies (bfd:MhNodePol) +description: +- Manage BFD Multihop Node policy configuration on Cisco ACI fabrics. +- Only available in APIC version 5.2 or later. +options: + tenant: + description: + - Name of an existing tenant + type: str + name: + description: + - Name of the BFD Multihop Node policy + type: str + aliases: [ bfd_multihop_node_policy ] + description: + description: + - Description of the BFD Multihop Node policy + type: str + admin_state: + description: + - Admin state of the BFD Multihop Node policy + - APIC sets the default value to enabled + type: str + choices: [ enabled, disabled ] + detection_multiplier: + description: + - Detection multiplier of the BFD Multihop Node policy + - APIC sets the default value to 3 + - Allowed range is 1-50 + type: int + min_transmit_interval: + description: + - Minimum transmit (Tx) interval of the BFD Multihop Node policy + - APIC sets the default value to 250 + - Allowed range is 250-999 + type: int + min_receive_interval: + description: + - Minimum receive (Rx) interval of the BFD Multihop Node policy + - APIC sets the default value to 250 + - Allowed range is 250-999 + 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 +- cisco.aci.annotation + +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(bfd:MhNodePol) + link: https://developer.cisco.com/docs/apic-mim-ref/ +- module: cisco.aci.aci_tenant +author: +- Anvitha Jain (@anvjain) +""" + +EXAMPLES = r""" +- name: Add a new BFD Multihop Node policy + cisco.aci.aci_bfd_multihop_node_policy: + host: apic + username: admin + password: SomeSecretPassword + tenant: ansible_tenant + name: ansible_bfd_multihop_node_policy + description: Ansible BFD Multihop Node Policy + state: present + delegate_to: localhost + +- name: Remove a BFD Multihop Node policy + cisco.aci.aci_bfd_multihop_node_policy: + host: apic + username: admin + password: SomeSecretPassword + tenant: ansible_tenant + name: ansible_bfd_multihop_node_policy + state: absent + delegate_to: localhost + +- name: Query a BFD Multihop Node policy + cisco.aci.aci_bfd_multihop_node_policy: + host: apic + username: admin + password: SomeSecretPassword + tenant: ansible_tenant + name: my_dhcp_relay + state: query + delegate_to: localhost + register: query_result + +- name: Query all BFD Multihop Node policies in a specific tenant + cisco.aci.aci_bfd_multihop_node_policy: + host: apic + username: admin + password: SomeSecretPassword + tenant: ansible_tenant + state: query + delegate_to: localhost + register: query_result +""" + +RETURN = r""" + current: + description: The existing configuration from the APIC after the module has finished + returned: success + type: list + sample: + [ + { + "fvTenant": { + "attributes": { + "descr": "Production environment", + "dn": "uni/tn-production", + "name": "production", + "nameAlias": "", + "ownerKey": "", + "ownerTag": "" + } + } + } + ] + error: + description: The error information as returned from the APIC + returned: failure + type: dict + sample: + { + "code": "122", + "text": "unknown managed object class foo" + } + raw: + description: The raw output returned by the APIC REST API (xml or json) + returned: parse error + type: str + sample: '' + sent: + description: The actual/minimal configuration pushed to the APIC + returned: info + type: list + sample: + { + "fvTenant": { + "attributes": { + "descr": "Production environment" + } + } + } + previous: + description: The original configuration from the APIC before the module has started + returned: info + type: list + sample: + [ + { + "fvTenant": { + "attributes": { + "descr": "Production", + "dn": "uni/tn-production", + "name": "production", + "nameAlias": "", + "ownerKey": "", + "ownerTag": "" + } + } + } + ] + proposed: + description: The assembled configuration from the user-provided parameters + returned: info + type: dict + sample: + { + "fvTenant": { + "attributes": { + "descr": "Production environment", + "name": "production" + } + } + } + filter_string: + description: The filter string used for the request + returned: failure or debug + type: str + sample: ?rsp-prop-include=config-only + method: + description: The HTTP method used for the request to the APIC + returned: failure or debug + type: str + sample: POST + response: + description: The HTTP response from the APIC + returned: failure or debug + type: str + sample: OK (30 bytes) + status: + description: The HTTP status from the APIC + returned: failure or debug + type: int + sample: 200 + url: + description: The HTTP url used for the request to the APIC + returned: failure or debug + type: str + sample: https://10.11.12.13/api/mo/uni/tn-production.json + """ + +from ansible.module_utils.basic import AnsibleModule +from ansible_collections.cisco.aci.plugins.module_utils.aci import ACIModule, aci_argument_spec, aci_annotation_spec + + +def main(): + argument_spec = aci_argument_spec() + argument_spec.update(aci_annotation_spec()) + argument_spec.update( + name=dict(type="str", aliases=["bfd_multihop_node_policy"]), + description=dict(type="str"), + admin_state=dict(type="str", choices=["enabled", "disabled"]), + detection_multiplier=dict(type="int"), + min_transmit_interval=dict(type="int"), + min_receive_interval=dict(type="int"), + state=dict(type="str", default="present", choices=["absent", "present", "query"]), + tenant=dict(type="str"), + ) + + module = AnsibleModule( + argument_spec=argument_spec, + supports_check_mode=True, + required_if=[ + ["state", "absent", ["name", "tenant"]], + ["state", "present", ["name", "tenant"]], + ], + ) + + name = module.params.get("name") + description = module.params.get("description") + state = module.params.get("state") + tenant = module.params.get("tenant") + admin_state = module.params.get("admin_state") + detection_multiplier = module.params.get("detection_multiplier") + min_transmit_interval = module.params.get("min_transmit_interval") + min_receive_interval = module.params.get("min_receive_interval") + + 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="bfdMhNodePol", + aci_rn="bfdMhNodePol-{0}".format(name), + module_object=name, + target_filter={"name": name}, + ), + ) + + aci.get_existing() + + if state == "present": + class_config = dict( + name=name, + descr=description, + adminSt=admin_state, + ) + + if detection_multiplier and detection_multiplier not in range(1, 50): + aci.fail_json(msg='The "detection_multiplier" must be a value between 1 and 50') + else: + class_config["detectMult"] = detection_multiplier + if min_transmit_interval and min_transmit_interval not in range(250, 999): + aci.fail_json(msg='The "min_transmit_interval" must be a value between 250 and 999') + else: + class_config["minTxIntvl"] = min_transmit_interval + if min_receive_interval and min_receive_interval not in range(250, 999): + aci.fail_json(msg='The "min_receive_interval" must be a value between 250 and 999') + else: + class_config["minRxIntvl"] = min_receive_interval + + aci.payload( + aci_class="bfdMhNodePol", + class_config=class_config, + ) + + aci.get_diff(aci_class="bfdMhNodePol") + + aci.post_config() + + elif state == "absent": + aci.delete_config() + + aci.exit_json() + + +if __name__ == "__main__": + main() diff --git a/ansible_collections/cisco/aci/plugins/modules/aci_bgp_address_family_context_policy.py b/ansible_collections/cisco/aci/plugins/modules/aci_bgp_address_family_context_policy.py new file mode 100644 index 000000000..1d69de6f6 --- /dev/null +++ b/ansible_collections/cisco/aci/plugins/modules/aci_bgp_address_family_context_policy.py @@ -0,0 +1,382 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- + +# Copyright: (c) 2023, Gaspard Micol (@gmicol) +# 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_bgp_address_family_context_policy +short_description: Manage BGP address family context policy (bgp:CtxAfPol) +description: +- Manage BGP address family context policies for the Tenants on Cisco ACI fabrics. +options: + tenant: + description: + - The name of an existing tenant. + type: str + aliases: [ tenant_name ] + address_family_context_policy: + description: + - The name of the BGP address family context policy. + type: str + aliases: [ address_family_context_name, name ] + host_route_leak: + description: + - The control state. + - The option to enable/disable host route leak. + - The APIC defaults to C(false) when unset during creation. + type: bool + ebgp_distance: + description: + - The administrative distance of eBGP routes. + - The APIC defaults to C(20) when unset during creation. + type: int + ibgp_distance: + description: + - The administrative distance of iBGP routes. + - The APIC defaults to C(200) when unset during creation. + type: int + local_distance: + description: + - The administrative distance of local routes. + - The APIC defaults to C(220) when unset during creation. + type: int + ebgp_max_ecmp: + description: + - The eBGP max-path. + - The APIC defaults to C(16) when unset during creation. + type: int + ibgp_max_ecmp: + description: + - The iBGP max-path. + - The APIC defaults to C(16) when unset during creation. + type: int + local_max_ecmp: + description: + - The maximum number of equal-cost local paths for redist. + - The APIC defaults to C(0) when unset during creation. + - Can not be configured for APIC version 4.2(7s) and prior. + type: int + bgp_add_path_capability: + description: + - The neighbor system capability. + - To delete this attribute, pass an empty string. + - Can not be configured for APIC version 6.0(2h) and prior. + type: str + choices: [ receive, send, "" ] + description: + description: + - Description for the BGP protocol 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 +- cisco.aci.annotation +- cisco.aci.owner + +notes: +- The C(tenant) used must exist before using this module in your playbook. + The M(cisco.aci.aci_tenant) module can be used for this. +seealso: +- module: cisco.aci.aci_tenant +- name: APIC Management Information Model reference + description: More information about the internal APIC class B(bgp:CtxAfPol). + link: https://developer.cisco.com/docs/apic-mim-ref/ +author: +- Gaspard Micol (@gmicol) +""" + +EXAMPLES = r""" +- name: Create a BGP address family context policy + cisco.aci.aci_bgp_address_family_context_policy: + host: apic + username: admin + password: SomeSecretPassword + bgp_address_family_context_policy: my_bgp_address_family_context_policy + host_route_leak: true + ebgp_distance: 40 + ibgp_distance: 210 + local_distance: 215 + ebgp_max_ecmp: 32 + ibgp_max_ecmp: 32 + local_max_ecmp: 1 + bgp_add_path_capability: receive + tenant: production + state: present + delegate_to: localhost + +- name: Delete BGP address family context policy's child + cisco.aci.aci_bgp_address_family_context_policy: + host: apic + username: admin + password: SomeSecretPassword + bgp_address_family_context_policy: my_bgp_address_family_context_policy + bgp_add_path_capability: "" + tenant: production + state: absent + delegate_to: localhost + +- name: Delete a BGP address family context policy + cisco.aci.aci_bgp_address_family_context_policy: + host: apic + username: admin + password: SomeSecretPassword + bgp_address_family_context_policy: my_bgp_address_family_context_policy + tenant: production + state: absent + delegate_to: localhost + +- name: Query all BGP address family context policies + cisco.aci.aci_bgp_address_family_context_policy: + host: apic + username: admin + password: SomeSecretPassword + state: query + delegate_to: localhost + register: query_result + +- name: Query a specific BGP address family context policy + cisco.aci.aci_bgp_address_family_context_policy: + host: apic + username: admin + password: SomeSecretPassword + bgp_address_family_context_policy: my_bgp_address_family_context_policy + 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: '' +sent: + description: The actual/minimal configuration pushed to the APIC + returned: info + type: list + sample: + { + "fvTenant": { + "attributes": { + "descr": "Production environment" + } + } + } +previous: + description: The original configuration from the APIC before the module has started + returned: info + type: list + sample: + [ + { + "fvTenant": { + "attributes": { + "descr": "Production", + "dn": "uni/tn-production", + "name": "production", + "nameAlias": "", + "ownerKey": "", + "ownerTag": "" + } + } + } + ] +proposed: + description: The assembled configuration from the user-provided parameters + returned: info + type: dict + sample: + { + "fvTenant": { + "attributes": { + "descr": "Production environment", + "name": "production" + } + } + } +filter_string: + description: The filter string used for the request + returned: failure or debug + type: str + sample: ?rsp-prop-include=config-only +method: + description: The HTTP method used for the request to the APIC + returned: failure or debug + type: str + sample: POST +response: + description: The HTTP response from the APIC + returned: failure or debug + type: str + sample: OK (30 bytes) +status: + description: The HTTP status from the APIC + returned: failure or debug + type: int + sample: 200 +url: + description: The HTTP url used for the request to the APIC + returned: failure or debug + type: str + sample: https://10.11.12.13/api/mo/uni/tn-production.json +""" + +from ansible.module_utils.basic import AnsibleModule +from ansible_collections.cisco.aci.plugins.module_utils.aci import ACIModule, aci_argument_spec, aci_annotation_spec, aci_owner_spec + + +def main(): + argument_spec = aci_argument_spec() + argument_spec.update(aci_annotation_spec()) + argument_spec.update(aci_owner_spec()) + argument_spec.update( + tenant=dict(type="str", aliases=["tenant_name"]), # Not required for querying all objects + address_family_context_policy=dict(type="str", aliases=["address_family_context_name", "name"]), # Not required for querying all objects + host_route_leak=dict(type="bool"), + ebgp_distance=dict(type="int"), + ibgp_distance=dict(type="int"), + local_distance=dict(type="int"), + ebgp_max_ecmp=dict(type="int"), + ibgp_max_ecmp=dict(type="int"), + local_max_ecmp=dict(type="int"), + bgp_add_path_capability=dict(type="str", choices=["receive", "send", ""]), + 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", ["address_family_context_policy", "tenant"]], + ["state", "present", ["address_family_context_policy", "tenant"]], + ], + ) + + aci = ACIModule(module) + + address_family_context_policy = module.params.get("address_family_context_policy") + host_route_leak = aci.boolean(module.params.get("host_route_leak"), "host-rt-leak", "") + ebgp_distance = module.params.get("ebgp_distance") + ibgp_distance = module.params.get("ibgp_distance") + local_distance = module.params.get("local_distance") + ebgp_max_ecmp = module.params.get("ebgp_max_ecmp") + ibgp_max_ecmp = module.params.get("ibgp_max_ecmp") + local_max_ecmp = module.params.get("local_max_ecmp") + bgp_add_path_capability = module.params.get("bgp_add_path_capability") + description = module.params.get("description") + state = module.params.get("state") + tenant = module.params.get("tenant") + name_alias = module.params.get("name_alias") + + child_classes = [] + if bgp_add_path_capability is not None: + child_classes.append("bgpCtxAddlPathPol") + + 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="bgpCtxAfPol", + aci_rn="bgpCtxAfP-{0}".format(address_family_context_policy), + module_object=address_family_context_policy, + target_filter={"name": address_family_context_policy}, + ), + child_classes=child_classes, + ) + + aci.get_existing() + + if state == "present": + child_configs = [] + if bgp_add_path_capability is not None: + if bgp_add_path_capability == "" and isinstance(aci.existing, list) and len(aci.existing) > 0: + for child in aci.existing[0].get("bgpCtxAfPol", {}).get("children", {}): + if child.get("bgpCtxAddlPathPol"): + child_configs.append(dict(bgpCtxAddlPathPol=dict(attributes=dict(status="deleted")))) + elif bgp_add_path_capability != "": + child_configs.append(dict(bgpCtxAddlPathPol=dict(attributes=dict(capability=bgp_add_path_capability)))) + + aci.payload( + aci_class="bgpCtxAfPol", + class_config=dict( + name=address_family_context_policy, + ctrl=host_route_leak, + eDist=ebgp_distance, + iDist=ibgp_distance, + localDist=local_distance, + maxEcmp=ebgp_max_ecmp, + maxEcmpIbgp=ibgp_max_ecmp, + maxLocalEcmp=local_max_ecmp, + descr=description, + nameAlias=name_alias, + ), + child_configs=child_configs, + ) + + aci.get_diff(aci_class="bgpCtxAfPol") + + aci.post_config() + + elif state == "absent": + aci.delete_config() + + aci.exit_json() + + +if __name__ == "__main__": + main() diff --git a/ansible_collections/cisco/aci/plugins/modules/aci_bgp_best_path_policy.py b/ansible_collections/cisco/aci/plugins/modules/aci_bgp_best_path_policy.py index a8b5c0a6a..936442aaa 100644 --- a/ansible_collections/cisco/aci/plugins/modules/aci_bgp_best_path_policy.py +++ b/ansible_collections/cisco/aci/plugins/modules/aci_bgp_best_path_policy.py @@ -15,7 +15,7 @@ DOCUMENTATION = r""" module: aci_bgp_best_path_policy short_description: Manage BGP Best Path policy (bgp:BestPathCtrlPol) description: -- Manage BGP Best Path policies for Tenants on Cisco ACI fabrics. +- Manage BGP Best Path policies for the Tenants on Cisco ACI fabrics. options: tenant: description: @@ -24,7 +24,7 @@ options: aliases: [ tenant_name ] bgp_best_path_policy: description: - - The name of the best path policy. + - The name of the BGP best path policy. type: str aliases: [ bgp_best_path_policy_name, name ] best_path_control: @@ -37,7 +37,7 @@ options: aliases: [as_path_control] description: description: - - Description for the bgp protocol profile. + - Description for the BGP best path policy. type: str aliases: [ descr ] state: @@ -74,7 +74,7 @@ EXAMPLES = r""" host: apic username: admin password: SomeSecretPassword - bgp_protocol_profile: my_bgp_best_path_policy + bgp_best_path_policy: my_bgp_best_path_policy best_path_control: enable tenant: production state: present @@ -85,7 +85,7 @@ EXAMPLES = r""" host: apic username: admin password: SomeSecretPassword - bgp_protocol_profile: my_bgp_best_path_policy + bgp_best_path_policy: my_bgp_best_path_policy tenant: production state: absent delegate_to: localhost @@ -104,7 +104,7 @@ EXAMPLES = r""" host: apic username: admin password: SomeSecretPassword - bgp_protocol_profile: my_bgp_best_path_policy + bgp_best_path_policy: my_bgp_best_path_policy tenant: production state: query delegate_to: localhost diff --git a/ansible_collections/cisco/aci/plugins/modules/aci_bgp_peer_prefix_policy.py b/ansible_collections/cisco/aci/plugins/modules/aci_bgp_peer_prefix_policy.py new file mode 100644 index 000000000..7719fff7a --- /dev/null +++ b/ansible_collections/cisco/aci/plugins/modules/aci_bgp_peer_prefix_policy.py @@ -0,0 +1,322 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- + +# Copyright: (c) 2023, Gaspard Micol (@gmicol) +# 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_bgp_peer_prefix_policy +short_description: Manage BGP peer prefix policy (bgp:PeerPfxPol) +description: +- Manage BGP peer prefix policies for the Tenants on Cisco ACI fabrics. +options: + tenant: + description: + - The name of an existing tenant. + type: str + aliases: [ tenant_name ] + peer_prefix_policy: + description: + - The name of the BGP peer prefix policy. + type: str + aliases: [ peer_prefix_policy_name, name ] + action: + description: + - The action to be performed when the maximum prefix limit is reached. + - The APIC defaults to C(reject) when unset during creation. + type: str + choices: [ log, reject, restart, shut ] + maximum_number_prefix: + description: + - The maximum number of prefixes allowed from the peer. + - The APIC defaults to C(20000) when unset during creation. + type: int + aliases: [ max_prefix, max_num_prefix ] + restart_time: + description: + - The period of time in minutes before restarting the peer when the prefix limit is reached. + - Used only if C(action) is set to C(restart). + - The APIC defaults to C(infinite) when unset during creation. + type: str + threshold: + description: + - The threshold percentage of the maximum number of prefixes before a warning is issued. + - For example, if the maximum number of prefixes is 10 and the threshold is 70%, a warning is issued when the number of prefixes exceeds 7 (70%). + - The APIC defaults to C(75) when unset during creation. + type: int + aliases: [ thresh ] + description: + description: + - Description for the BGP peer prefix 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 +- cisco.aci.annotation +- cisco.aci.owner + +notes: +- The C(tenant) used must exist before using this module in your playbook. + The M(cisco.aci.aci_tenant) module can be used for this. +seealso: +- module: cisco.aci.aci_tenant +- name: APIC Management Information Model reference + description: More information about the internal APIC class B(bgp:PeerPfxPol). + link: https://developer.cisco.com/docs/apic-mim-ref/ +author: +- Gaspard Micol (@gmicol) +""" + +EXAMPLES = r""" +- name: Create a BGP peer prefix policy + cisco.aci.aci_bgp_peer_prefix_policy: + host: apic + username: admin + password: SomeSecretPassword + peer_prefix_policy: my_bgp_peer_prefix_policy + action: restart + restart_time: 10 + max_prefix: 10000 + threshold: 80 + tenant: production + state: present + delegate_to: localhost + +- name: Delete a BGP peer prefix policy + cisco.aci.aci_bgp_peer_prefix_policy: + host: apic + username: admin + password: SomeSecretPassword + peer_prefix_policy: my_bgp_peer_prefix_policy + tenant: production + state: absent + delegate_to: localhost + +- name: Query all BGP peer prefix policies + cisco.aci.aci_bgp_peer_prefix_policy: + host: apic + username: admin + password: SomeSecretPassword + state: query + delegate_to: localhost + register: query_result + +- name: Query a specific BGP peer prefix policy + cisco.aci.aci_bgp_peer_prefix_policy: + host: apic + username: admin + password: SomeSecretPassword + peer_prefix_policy: my_bgp_peer_prefix_policy + 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: '' +sent: + description: The actual/minimal configuration pushed to the APIC + returned: info + type: list + sample: + { + "fvTenant": { + "attributes": { + "descr": "Production environment" + } + } + } +previous: + description: The original configuration from the APIC before the module has started + returned: info + type: list + sample: + [ + { + "fvTenant": { + "attributes": { + "descr": "Production", + "dn": "uni/tn-production", + "name": "production", + "nameAlias": "", + "ownerKey": "", + "ownerTag": "" + } + } + } + ] +proposed: + description: The assembled configuration from the user-provided parameters + returned: info + type: dict + sample: + { + "fvTenant": { + "attributes": { + "descr": "Production environment", + "name": "production" + } + } + } +filter_string: + description: The filter string used for the request + returned: failure or debug + type: str + sample: ?rsp-prop-include=config-only +method: + description: The HTTP method used for the request to the APIC + returned: failure or debug + type: str + sample: POST +response: + description: The HTTP response from the APIC + returned: failure or debug + type: str + sample: OK (30 bytes) +status: + description: The HTTP status from the APIC + returned: failure or debug + type: int + sample: 200 +url: + description: The HTTP url used for the request to the APIC + returned: failure or debug + type: str + sample: https://10.11.12.13/api/mo/uni/tn-production.json +""" + +from ansible.module_utils.basic import AnsibleModule +from ansible_collections.cisco.aci.plugins.module_utils.aci import ACIModule, aci_argument_spec, aci_annotation_spec, aci_owner_spec + + +def main(): + argument_spec = aci_argument_spec() + argument_spec.update(aci_annotation_spec()) + argument_spec.update(aci_owner_spec()) + argument_spec.update( + tenant=dict(type="str", aliases=["tenant_name"]), # Not required for querying all objects + peer_prefix_policy=dict(type="str", aliases=["peer_prefix_policy_name", "name"]), # Not required for querying all objects + action=dict(type="str", choices=["log", "reject", "restart", "shut"]), + maximum_number_prefix=dict(type="int", aliases=["max_prefix", "max_num_prefix"]), + restart_time=dict(type="str"), + threshold=dict(type="int", aliases=["thresh"]), + 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", ["peer_prefix_policy", "tenant"]], + ["state", "present", ["peer_prefix_policy", "tenant"]], + ], + ) + + peer_prefix_policy = module.params.get("peer_prefix_policy") + action = module.params.get("action") + maximum_number_prefix = module.params.get("maximum_number_prefix") + restart_time = module.params.get("restart_time") + threshold = module.params.get("threshold") + 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="bgpPeerPfxPol", + aci_rn="bgpPfxP-{0}".format(peer_prefix_policy), + module_object=peer_prefix_policy, + target_filter={"name": peer_prefix_policy}, + ), + ) + + aci.get_existing() + + if state == "present": + aci.payload( + aci_class="bgpPeerPfxPol", + class_config=dict( + name=peer_prefix_policy, + action=action, + maxPfx=maximum_number_prefix, + restartTime=restart_time, + thresh=threshold, + descr=description, + nameAlias=name_alias, + ), + ) + + aci.get_diff(aci_class="bgpPeerPfxPol") + + aci.post_config() + + elif state == "absent": + aci.delete_config() + + aci.exit_json() + + +if __name__ == "__main__": + main() diff --git a/ansible_collections/cisco/aci/plugins/modules/aci_bgp_route_summarization_policy.py b/ansible_collections/cisco/aci/plugins/modules/aci_bgp_route_summarization_policy.py new file mode 100644 index 000000000..6e10e92c6 --- /dev/null +++ b/ansible_collections/cisco/aci/plugins/modules/aci_bgp_route_summarization_policy.py @@ -0,0 +1,310 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- + +# Copyright: (c) 2023, Gaspard Micol (@gmicol) +# 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_bgp_route_summarization_policy +short_description: Manage BGP route summarization policy (bgp:RtSummPol) +description: +- Manage BGP route summarization policies for the Tenants on Cisco ACI fabrics. +options: + tenant: + description: + - The name of an existing tenant. + type: str + aliases: [ tenant_name ] + route_summarization_policy: + description: + - The name of the BGP route summarization policy. + type: str + aliases: [ route_summarization_policy_name, name ] + address_type_af_control: + description: + - The Ucast/Mcast address type AF control. + - The APIC defaults to C(af-ucast) when unset during creation. + - Can not be configured for APIC version 4.2(7s) or prior. + type: list + elements: str + choices: [ af-label-ucast, af-ucast, af-mcast ] + aliases: [ address_type_control ] + control_state: + description: + - The summary control. + - The C(summary_only) option can not be configured for APIC version 4.2(7s) or prior. + type: list + elements: str + choices: [ as-set, summary-only ] + aliases: [ summary_control, control ] + description: + description: + - Description for the BGP route summarization 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 +- cisco.aci.annotation +- cisco.aci.owner + +notes: +- The C(tenant) used must exist before using this module in your playbook. + The M(cisco.aci.aci_tenant) module can be used for this. +seealso: +- module: cisco.aci.aci_tenant +- name: APIC Management Information Model reference + description: More information about the internal APIC class B(bgp:RtSummPol). + link: https://developer.cisco.com/docs/apic-mim-ref/ +author: +- Gaspard Micol (@gmicol) +""" + +EXAMPLES = r""" +- name: Create a BGP route summarization policy + cisco.aci.aci_bgp_route_summarization_policy: + host: apic + username: admin + password: SomeSecretPassword + route_summarization_policy: my_route_summarization_policy + address_type_af_control: [af-mcast, af-ucast] + control_state: [as-set, summary-only] + tenant: production + state: present + delegate_to: localhost + +- name: Delete a BGP route summarization policy + cisco.aci.aci_bgp_route_summarization_policy: + host: apic + username: admin + password: SomeSecretPassword + route_summarization_policy: my_route_summarization_policy + tenant: production + state: absent + delegate_to: localhost + +- name: Query all BGP route summarization policies + cisco.aci.aci_bgp_route_summarization_policy: + host: apic + username: admin + password: SomeSecretPassword + state: query + delegate_to: localhost + register: query_result + +- name: Query a specific BGP route summarization policy + cisco.aci.aci_bgp_route_summarization_policy: + host: apic + username: admin + password: SomeSecretPassword + route_summarization_policy: my_route_summarization_policy + 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: '' +sent: + description: The actual/minimal configuration pushed to the APIC + returned: info + type: list + sample: + { + "fvTenant": { + "attributes": { + "descr": "Production environment" + } + } + } +previous: + description: The original configuration from the APIC before the module has started + returned: info + type: list + sample: + [ + { + "fvTenant": { + "attributes": { + "descr": "Production", + "dn": "uni/tn-production", + "name": "production", + "nameAlias": "", + "ownerKey": "", + "ownerTag": "" + } + } + } + ] +proposed: + description: The assembled configuration from the user-provided parameters + returned: info + type: dict + sample: + { + "fvTenant": { + "attributes": { + "descr": "Production environment", + "name": "production" + } + } + } +filter_string: + description: The filter string used for the request + returned: failure or debug + type: str + sample: ?rsp-prop-include=config-only +method: + description: The HTTP method used for the request to the APIC + returned: failure or debug + type: str + sample: POST +response: + description: The HTTP response from the APIC + returned: failure or debug + type: str + sample: OK (30 bytes) +status: + description: The HTTP status from the APIC + returned: failure or debug + type: int + sample: 200 +url: + description: The HTTP url used for the request to the APIC + returned: failure or debug + type: str + sample: https://10.11.12.13/api/mo/uni/tn-production.json +""" + +from ansible.module_utils.basic import AnsibleModule +from ansible_collections.cisco.aci.plugins.module_utils.aci import ACIModule, aci_argument_spec, aci_annotation_spec, aci_owner_spec + + +def main(): + argument_spec = aci_argument_spec() + argument_spec.update(aci_annotation_spec()) + argument_spec.update(aci_owner_spec()) + argument_spec.update( + tenant=dict(type="str", aliases=["tenant_name"]), # Not required for querying all objects + route_summarization_policy=dict(type="str", aliases=["route_summarization_policy_name", "name"]), # Not required for querying all objects + address_type_af_control=dict(type="list", elements="str", choices=["af-label-ucast", "af-ucast", "af-mcast"], aliases=["address_type_control"]), + control_state=dict(type="list", elements="str", choices=["as-set", "summary-only"], aliases=["summary_control", "control"]), + 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", ["route_summarization_policy", "tenant"]], + ["state", "present", ["route_summarization_policy", "tenant"]], + ], + ) + + route_summarization_policy = module.params.get("route_summarization_policy") + address_type_af_control = ",".join(module.params.get("address_type_af_control")) if module.params.get("address_type_af_control") else None + control_state = ",".join(module.params.get("control_state")) if module.params.get("control_state") else None + 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="bgpRtSummPol", + aci_rn="bgprtsum-{0}".format(route_summarization_policy), + module_object=route_summarization_policy, + target_filter={"name": route_summarization_policy}, + ), + ) + + aci.get_existing() + + if state == "present": + class_config = dict( + name=route_summarization_policy, + ctrl=control_state, + descr=description, + nameAlias=name_alias, + ) + + if address_type_af_control is not None: + class_config.update(dict(addrTCtrl=address_type_af_control)) + + aci.payload( + aci_class="bgpRtSummPol", + class_config=class_config, + ) + + aci.get_diff(aci_class="bgpRtSummPol") + + aci.post_config() + + elif state == "absent": + aci.delete_config() + + aci.exit_json() + + +if __name__ == "__main__": + main() diff --git a/ansible_collections/cisco/aci/plugins/modules/aci_bgp_rr_asn.py b/ansible_collections/cisco/aci/plugins/modules/aci_bgp_rr_asn.py index 4eae25e3d..e728e41b6 100644 --- a/ansible_collections/cisco/aci/plugins/modules/aci_bgp_rr_asn.py +++ b/ansible_collections/cisco/aci/plugins/modules/aci_bgp_rr_asn.py @@ -13,9 +13,9 @@ ANSIBLE_METADATA = {"metadata_version": "1.1", "status": ["preview"], "supported DOCUMENTATION = r""" --- module: aci_bgp_rr_asn -short_description: Manage BGP Route Reflector ASN. +short_description: Manage BGP Route Reflector ASN (bgp:AsP) description: -- Manage the BGP Autonomous System Number of the fabric (bgpAsP). +- Manage the BGP Autonomous System Number of the fabric. - This module is specifically for fabric BGP, for L3Out BGP use the aci_l3out_bgp_peer module options: asn: @@ -35,7 +35,7 @@ extends_documentation_fragment: seealso: - name: APIC Management Information Model reference - description: More information about the internal APIC class B(bgpAsP). + description: More information about the internal APIC class B(bgp:AsP). link: https://developer.cisco.com/docs/apic-mim-ref/ author: - Tim Cragg (@timcragg) diff --git a/ansible_collections/cisco/aci/plugins/modules/aci_bgp_rr_node.py b/ansible_collections/cisco/aci/plugins/modules/aci_bgp_rr_node.py index 1f37b769c..90139b026 100644 --- a/ansible_collections/cisco/aci/plugins/modules/aci_bgp_rr_node.py +++ b/ansible_collections/cisco/aci/plugins/modules/aci_bgp_rr_node.py @@ -13,9 +13,9 @@ ANSIBLE_METADATA = {"metadata_version": "1.1", "status": ["preview"], "supported DOCUMENTATION = r""" --- module: aci_bgp_rr_node -short_description: Manage BGP Route Reflector objects. +short_description: Manage BGP Route Reflector objects (bgp:RRNodePEp) description: -- Manage ACI BGP Route Reflector Nodes (bgpRRNodePEp). +- Manage ACI BGP Route Reflector Nodes. options: node_id: description: @@ -42,7 +42,7 @@ extends_documentation_fragment: seealso: - name: APIC Management Information Model reference - description: More information about the internal APIC class B(bgpRRNodePEp). + description: More information about the internal APIC class B(bgp:RRNodePEp). link: https://developer.cisco.com/docs/apic-mim-ref/ author: - Tim Cragg (@timcragg) diff --git a/ansible_collections/cisco/aci/plugins/modules/aci_bgp_timers_policy.py b/ansible_collections/cisco/aci/plugins/modules/aci_bgp_timers_policy.py index c8d6c54b0..9a62a8d4f 100644 --- a/ansible_collections/cisco/aci/plugins/modules/aci_bgp_timers_policy.py +++ b/ansible_collections/cisco/aci/plugins/modules/aci_bgp_timers_policy.py @@ -15,7 +15,7 @@ DOCUMENTATION = r""" module: aci_bgp_timers_policy short_description: Manage BGP timers policy (bgp:CtxPol) description: -- Manage BGP timers policies for Tenants on Cisco ACI fabrics. +- Manage BGP timers policies for the Tenants on Cisco ACI fabrics. options: tenant: description: @@ -24,7 +24,7 @@ options: aliases: [ tenant_name ] bgp_timers_policy: description: - - The name of the bgp timers policy. + - The name of the BGP timers policy. type: str aliases: [ bgp_timers_policy_name, name ] graceful_restart_controls: @@ -57,7 +57,7 @@ options: type: int description: description: - - Description for the bgp protocol profile. + - Description for the BGP timers policy. type: str aliases: [ descr ] state: @@ -94,7 +94,7 @@ EXAMPLES = r""" host: apic username: admin password: SomeSecretPassword - bgp_protocol_profile: my_bgp_timers_policy + bgp_timers_policy: my_bgp_timers_policy graceful_restart_controls: complete hold_interval: 360 keepalive_interval: 120 @@ -109,7 +109,7 @@ EXAMPLES = r""" host: apic username: admin password: SomeSecretPassword - bgp_protocol_profile: my_bgp_timers_policy + bgp_timers_policy: my_bgp_timers_policy tenant: production state: absent delegate_to: localhost @@ -128,7 +128,7 @@ EXAMPLES = r""" host: apic username: admin password: SomeSecretPassword - bgp_protocol_profile: my_bgp_timers_policy + bgp_timers_policy: my_bgp_timers_policy tenant: production state: query delegate_to: localhost diff --git a/ansible_collections/cisco/aci/plugins/modules/aci_cloud_subnet.py b/ansible_collections/cisco/aci/plugins/modules/aci_cloud_subnet.py index 31845f629..bfdad0a33 100644 --- a/ansible_collections/cisco/aci/plugins/modules/aci_cloud_subnet.py +++ b/ansible_collections/cisco/aci/plugins/modules/aci_cloud_subnet.py @@ -3,6 +3,7 @@ # Copyright: (c) 2020, nkatarmal-crest # Copyright: (c) 2020, Cindy Zhao +# Copyright: (c) 2024, Samita Bhattacharjee # 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 @@ -21,6 +22,7 @@ notes: author: - Nirav (@nirav) - Cindy Zhao (@cizhao) +- Samita Bhattacharjee (@samitab) options: name: description: @@ -54,17 +56,24 @@ options: - Address of cloud cidr. type: str required: true - availability_zone: + aws_availability_zone: description: - The cloud zone which is attached to the given cloud context profile. - - Only used when it is an aws cloud apic. + - Only used when it is an AWS Cloud APIC. type: str + aliases: [availability_zone, av_zone, zone] vnet_gateway: description: - Determine if a vNet Gateway Router will be deployed or not. - - Only used when it is an azure cloud apic. + - Only used when it is an Azure Cloud APIC. type: bool default: false + azure_region: + description: + - The Azure cloud region to attach this subnet to. + - Only used when it is an Azure Cloud APIC. + type: str + aliases: [az_region] state: description: - Use C(present) or C(absent) for adding or removing. @@ -78,7 +87,7 @@ extends_documentation_fragment: """ EXAMPLES = r""" -- name: Create aci cloud subnet +- name: Create AWS aci cloud subnet cisco.aci.aci_cloud_subnet: host: apic username: userName @@ -87,7 +96,21 @@ EXAMPLES = r""" tenant: anstest cloud_context_profile: aws_cloudCtxProfile cidr: '10.10.0.0/16' - availability_zone: us-west-1a + aws_availability_zone: us-west-1a + address: 10.10.0.1 + delegate_to: localhost + +- name: Create Azure aci cloud subnet + cisco.aci.aci_cloud_subnet: + host: apic + username: userName + password: somePassword + validate_certs: false + tenant: anstest + cloud_context_profile: azure_cloudCtxProfile + cidr: '10.10.0.0/16' + azure_region: westus2 + vnet_gateway: true address: 10.10.0.1 delegate_to: localhost @@ -239,16 +262,18 @@ def main(): 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"), + aws_availability_zone=dict(type="str", aliases=["availability_zone", "av_zone", "zone"]), + azure_region=dict(type="str", aliases=["az_region"]), ) module = AnsibleModule( argument_spec=argument_spec, supports_check_mode=True, required_if=[ - ["state", "absent", ["address"]], - ["state", "present", ["address"]], + ["state", "absent", ["tenant", "cloud_context_profile", "cidr", "address"]], + ["state", "present", ["tenant", "cloud_context_profile", "cidr", "address"]], ], + mutually_exclusive=[("aws_availability_zone", "azure_region")], ) name = module.params.get("name") @@ -260,7 +285,8 @@ def main(): 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") + aws_availability_zone = module.params.get("aws_availability_zone") + azure_region = module.params.get("azure_region") child_configs = [] aci = ACIModule(module) @@ -283,11 +309,14 @@ def main(): 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) + if aws_availability_zone: + region = aws_availability_zone[:-1] + tDn = "uni/clouddomp/provp-aws/region-{0}/zone-{1}".format(region, aws_availability_zone) child_configs.append({"cloudRsZoneAttach": {"attributes": {"tDn": tDn}}}) # in azure cloud apic + if azure_region: + tDn = "uni/clouddomp/provp-azure/region-{0}/zone-default".format(azure_region) + child_configs.append({"cloudRsZoneAttach": {"attributes": {"tDn": tDn}}}) if vnet_gateway: usage = "gateway" else: diff --git a/ansible_collections/cisco/aci/plugins/modules/aci_config_snapshot.py b/ansible_collections/cisco/aci/plugins/modules/aci_config_snapshot.py index bc36a5e62..2022c2df9 100644 --- a/ansible_collections/cisco/aci/plugins/modules/aci_config_snapshot.py +++ b/ansible_collections/cisco/aci/plugins/modules/aci_config_snapshot.py @@ -12,7 +12,7 @@ ANSIBLE_METADATA = {"metadata_version": "1.1", "status": ["preview"], "supported DOCUMENTATION = r""" --- module: aci_config_snapshot -short_description: Manage Config Snapshots (config:Snapshot, config:ExportP) +short_description: Manage Config Snapshots (config:Snapshot and config:ExportP) description: - Manage Config Snapshots on Cisco ACI fabrics. - Creating new Snapshots is done using the configExportP class. diff --git a/ansible_collections/cisco/aci/plugins/modules/aci_contract_subject_to_service_graph.py b/ansible_collections/cisco/aci/plugins/modules/aci_contract_subject_to_service_graph.py index eb8f9fa32..f50790bb3 100644 --- a/ansible_collections/cisco/aci/plugins/modules/aci_contract_subject_to_service_graph.py +++ b/ansible_collections/cisco/aci/plugins/modules/aci_contract_subject_to_service_graph.py @@ -12,7 +12,7 @@ ANSIBLE_METADATA = {"metadata_version": "1.1", "status": ["preview"], "supported DOCUMENTATION = r""" --- module: aci_contract_subject_to_service_graph -short_description: Bind contract subject to service graph (vz:RsSubjGraphAtt). +short_description: Bind contract subject to service graph (vz:RsSubjGraphAtt) description: - Bind contract subject to service graph. options: diff --git a/ansible_collections/cisco/aci/plugins/modules/aci_dhcp_option.py b/ansible_collections/cisco/aci/plugins/modules/aci_dhcp_option.py new file mode 100644 index 000000000..1253f85d6 --- /dev/null +++ b/ansible_collections/cisco/aci/plugins/modules/aci_dhcp_option.py @@ -0,0 +1,306 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- + +# Copyright: (c) 2023, Gaspard Micol (@gmicol) +# 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_dhcp_option +short_description: Manage DHCP Option (dhcp:Option) +description: +- Manage DHCP Options for DHCP Option Policies on Cisco ACI fabrics. +- The DHCP option is used to supply DHCP clients with configuration parameters such as a domain, name server, subnet, and network address. + DHCP provides a framework for passing configuration information to clients on a TCP/IP network. + The configuration parameters, and other control information, are carried in tagged data items that are stored in the options field of a DHCP message. + The data items themselves are also called options. You can view, set, unset, and edit DHCP option values. + When you set an option value, the DHCP server replaces any existing value or creates a new one as needed for the given option name. +options: + tenant: + description: + - The name of an existing tenant. + type: str + aliases: [ tenant_name ] + dhcp_option_policy: + description: + - The name of an existing DHCP Option Policy. + type: str + aliases: [ dhcp_option_policy_name ] + dhcp_option: + description: + - The name of the DHCP Option. + type: str + aliases: [ dhcp_option_name, name ] + data: + description: + - The value of the DHCP Option. + type: str + id: + description: + - The DHCP Option ID. + 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 +- cisco.aci.annotation +- cisco.aci.owner + +notes: +- The C(tenant) must exist before using this module in your playbook. + The M(cisco.aci.aci_tenant) can be used for this. +seealso: +- module: cisco.aci.aci_tenant +- name: APIC Management Information Model reference + description: More information about the internal APIC classes + link: https://developer.cisco.com/docs/apic-mim-ref/ +author: +- Gaspard Micol (@gmicol) +""" + +EXAMPLES = r""" +- name: Add a new DHCP Option + cisco.aci.aci_dhcp_option: + host: apic + username: admin + password: SomeSecretPassword + tenant: my_tenant + dhcp_option_policy: my_dhcp_option_policy + dhcp_option: my_dhcp_option + id: 1 + data: 82 + state: present + delegate_to: localhost + +- name: Delete an DHCP Option + cisco.aci.aci_dhcp_option: + host: apic + username: admin + password: SomeSecretPassword + tenant: my_tenant + dhcp_option_policy: my_dhcp_option_policy + dhcp_option: my_dhcp_option + state: absent + delegate_to: localhost + +- name: Query a DHCP Option + cisco.aci.aci_dhcp_option: + host: apic + username: admin + password: SomeSecretPassword + tenant: my_tenant + dhcp_option_policy: my_dhcp_option_policy + dhcp_option: my_dhcp_option + state: query + delegate_to: localhost + register: query_result + +- name: Query all DHCP Options in my_dhcp_option_policy + cisco.aci.aci_dhcp_option: + host: apic + username: admin + password: SomeSecretPassword + tenant: my_tenant + dhcp_option_policy: my_dhcp_option_policy + state: query + delegate_to: localhost + register: query_result +""" + +RETURN = r""" +current: + description: The existing configuration from the APIC after the module has finished + returned: success + type: list + sample: + [ + { + "fvTenant": { + "attributes": { + "descr": "Production environment", + "dn": "uni/tn-production", + "name": "production", + "nameAlias": "", + "ownerKey": "", + "ownerTag": "" + } + } + } + ] +error: + description: The error information as returned from the APIC + returned: failure + type: dict + sample: + { + "code": "122", + "text": "unknown managed object class foo" + } +raw: + description: The raw output returned by the APIC REST API (xml or json) + returned: parse error + type: str + sample: '' +sent: + description: The actual/minimal configuration pushed to the APIC + returned: info + type: list + sample: + { + "fvTenant": { + "attributes": { + "descr": "Production environment" + } + } + } +previous: + description: The original configuration from the APIC before the module has started + returned: info + type: list + sample: + [ + { + "fvTenant": { + "attributes": { + "descr": "Production", + "dn": "uni/tn-production", + "name": "production", + "nameAlias": "", + "ownerKey": "", + "ownerTag": "" + } + } + } + ] +proposed: + description: The assembled configuration from the user-provided parameters + returned: info + type: dict + sample: + { + "fvTenant": { + "attributes": { + "descr": "Production environment", + "name": "production" + } + } + } +filter_string: + description: The filter string used for the request + returned: failure or debug + type: str + sample: ?rsp-prop-include=config-only +method: + description: The HTTP method used for the request to the APIC + returned: failure or debug + type: str + sample: POST +response: + description: The HTTP response from the APIC + returned: failure or debug + type: str + sample: OK (30 bytes) +status: + description: The HTTP status from the APIC + returned: failure or debug + type: int + sample: 200 +url: + description: The HTTP url used for the request to the APIC + returned: failure or debug + type: str + sample: https://10.11.12.13/api/mo/uni/tn-production.json +""" + + +from ansible.module_utils.basic import AnsibleModule +from ansible_collections.cisco.aci.plugins.module_utils.aci import ACIModule, aci_argument_spec, aci_annotation_spec, aci_owner_spec + + +def main(): + argument_spec = aci_argument_spec() + argument_spec.update(aci_annotation_spec()) + argument_spec.update(aci_owner_spec()) + argument_spec.update( + tenant=dict(type="str", aliases=["tenant_name"]), + dhcp_option_policy=dict(type="str", aliases=["dhcp_option_policy_name"]), + dhcp_option=dict(type="str", aliases=["dhcp_option_name", "name"]), + data=dict(type="str"), + id=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=[ + ["state", "absent", ["tenant", "dhcp_option_policy", "dhcp_option"]], + ["state", "present", ["tenant", "dhcp_option_policy", "dhcp_option"]], + ], + ) + + tenant = module.params.get("tenant") + dhcp_option_policy = module.params.get("dhcp_option_policy") + dhcp_option = module.params.get("dhcp_option") + data = module.params.get("data") + id = module.params.get("id") + 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="dhcpOptionPol", + aci_rn="dhcpoptpol-{0}".format(dhcp_option_policy), + module_object=dhcp_option_policy, + target_filter={"name": dhcp_option_policy}, + ), + subclass_2=dict( + aci_class="dhcpOption", + aci_rn="opt-{0}".format(dhcp_option), + module_object=dhcp_option, + target_filter={"name": dhcp_option}, + ), + ) + + aci.get_existing() + + if state == "present": + aci.payload( + aci_class="dhcpOption", + class_config=dict( + name=dhcp_option, + data=data, + id=id, + ), + ) + + aci.get_diff(aci_class="dhcpOption") + + aci.post_config() + + elif state == "absent": + aci.delete_config() + + aci.exit_json() + + +if __name__ == "__main__": + main() diff --git a/ansible_collections/cisco/aci/plugins/modules/aci_dhcp_option_policy.py b/ansible_collections/cisco/aci/plugins/modules/aci_dhcp_option_policy.py new file mode 100644 index 000000000..9e7bd7738 --- /dev/null +++ b/ansible_collections/cisco/aci/plugins/modules/aci_dhcp_option_policy.py @@ -0,0 +1,276 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- + +# Copyright: (c) 2023, Gaspard Micol (@gmicol) +# 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_dhcp_option_policy +short_description: Manage DHCP Option Policy (dhcp:OptionPol) +description: +- Manage DHCP Option Policy for tenants on Cisco ACI fabrics. +options: + tenant: + description: + - The name of an existing tenant. + type: str + aliases: [ tenant_name ] + dhcp_option_policy: + description: + - The name of the DHCP Option Policy. + type: str + aliases: [ dhcp_option_policy_name, name ] + description: + description: + - The description for the DHCP Option 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 +extends_documentation_fragment: +- cisco.aci.aci +- cisco.aci.annotation +- cisco.aci.owner + +notes: +- The C(tenant) must exist before using this module in your playbook. + The M(cisco.aci.aci_tenant) can be used for this. +seealso: +- module: cisco.aci.aci_tenant +- name: APIC Management Information Model reference + description: More information about the internal APIC classes + link: https://developer.cisco.com/docs/apic-mim-ref/ +author: +- Gaspard Micol (@gmicol) +""" + +EXAMPLES = r""" +- name: Add a new DHCP Option Policy + cisco.aci.aci_dhcp_option_policy: + host: apic + username: admin + password: SomeSecretPassword + tenant: my_tenant + dhcp_option_policy: my_dhcp_option_policy + state: present + delegate_to: localhost + +- name: Delete an DHCP Option Policy + cisco.aci.aci_dhcp_option_policy: + host: apic + username: admin + password: SomeSecretPassword + tenant: my_tenant + dhcp_option_policy: my_dhcp_option_policy + state: absent + delegate_to: localhost + +- name: Query a DHCP Option Policy + cisco.aci.aci_dhcp_option_policy: + host: apic + username: admin + password: SomeSecretPassword + tenant: my_tenant + dhcp_option_policy: my_dhcp_option_policy + state: query + delegate_to: localhost + register: query_result + +- name: Query all DHCP Option Policies in my_tenant + cisco.aci.aci_dhcp_option_policy: + host: apic + username: admin + password: SomeSecretPassword + tenant: my_tenant + state: query + delegate_to: localhost + register: query_result +""" + +RETURN = r""" +current: + description: The existing configuration from the APIC after the module has finished + returned: success + type: list + sample: + [ + { + "fvTenant": { + "attributes": { + "descr": "Production environment", + "dn": "uni/tn-production", + "name": "production", + "nameAlias": "", + "ownerKey": "", + "ownerTag": "" + } + } + } + ] +error: + description: The error information as returned from the APIC + returned: failure + type: dict + sample: + { + "code": "122", + "text": "unknown managed object class foo" + } +raw: + description: The raw output returned by the APIC REST API (xml or json) + returned: parse error + type: str + sample: '' +sent: + description: The actual/minimal configuration pushed to the APIC + returned: info + type: list + sample: + { + "fvTenant": { + "attributes": { + "descr": "Production environment" + } + } + } +previous: + description: The original configuration from the APIC before the module has started + returned: info + type: list + sample: + [ + { + "fvTenant": { + "attributes": { + "descr": "Production", + "dn": "uni/tn-production", + "name": "production", + "nameAlias": "", + "ownerKey": "", + "ownerTag": "" + } + } + } + ] +proposed: + description: The assembled configuration from the user-provided parameters + returned: info + type: dict + sample: + { + "fvTenant": { + "attributes": { + "descr": "Production environment", + "name": "production" + } + } + } +filter_string: + description: The filter string used for the request + returned: failure or debug + type: str + sample: ?rsp-prop-include=config-only +method: + description: The HTTP method used for the request to the APIC + returned: failure or debug + type: str + sample: POST +response: + description: The HTTP response from the APIC + returned: failure or debug + type: str + sample: OK (30 bytes) +status: + description: The HTTP status from the APIC + returned: failure or debug + type: int + sample: 200 +url: + description: The HTTP url used for the request to the APIC + returned: failure or debug + type: str + sample: https://10.11.12.13/api/mo/uni/tn-production.json +""" + + +from ansible.module_utils.basic import AnsibleModule +from ansible_collections.cisco.aci.plugins.module_utils.aci import ACIModule, aci_argument_spec, aci_annotation_spec, aci_owner_spec + + +def main(): + argument_spec = aci_argument_spec() + argument_spec.update(aci_annotation_spec()) + argument_spec.update(aci_owner_spec()) + argument_spec.update( + tenant=dict(type="str", aliases=["tenant_name"]), + dhcp_option_policy=dict(type="str", aliases=["dhcp_option_policy_name", "name"]), + description=dict(type="str", aliases=["descr"]), + state=dict(type="str", default="present", choices=["absent", "present", "query"]), + ) + + module = AnsibleModule( + argument_spec=argument_spec, + supports_check_mode=True, + required_if=[ + ["state", "absent", ["tenant", "dhcp_option_policy"]], + ["state", "present", ["tenant", "dhcp_option_policy"]], + ], + ) + + tenant = module.params.get("tenant") + description = module.params.get("description") + dhcp_option_policy = module.params.get("dhcp_option_policy") + 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="dhcpOptionPol", + aci_rn="dhcpoptpol-{0}".format(dhcp_option_policy), + module_object=dhcp_option_policy, + target_filter={"name": dhcp_option_policy}, + ), + ) + + aci.get_existing() + + if state == "present": + aci.payload( + aci_class="dhcpOptionPol", + class_config=dict( + name=dhcp_option_policy, + descr=description, + ), + ) + + aci.get_diff(aci_class="dhcpOptionPol") + + aci.post_config() + + elif state == "absent": + aci.delete_config() + + aci.exit_json() + + +if __name__ == "__main__": + main() diff --git a/ansible_collections/cisco/aci/plugins/modules/aci_dhcp_relay.py b/ansible_collections/cisco/aci/plugins/modules/aci_dhcp_relay.py index 9bb8267dd..39351b4aa 100644 --- a/ansible_collections/cisco/aci/plugins/modules/aci_dhcp_relay.py +++ b/ansible_collections/cisco/aci/plugins/modules/aci_dhcp_relay.py @@ -14,9 +14,9 @@ ANSIBLE_METADATA = {"metadata_version": "1.1", "status": ["preview"], "supported DOCUMENTATION = r""" --- module: aci_dhcp_relay -short_description: Manage DHCP relay policies. +short_description: Manage DHCP relay policies (dhcp:RelayP) description: -- Manage DHCP relay policy (dhcpRelayP) configuration on Cisco ACI fabrics. +- Manage DHCP relay policy configuration on Cisco ACI fabrics. options: tenant: description: @@ -48,7 +48,7 @@ notes: 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(dhcpRelayP). + description: More information about the internal APIC class B(dhcp:RelayP). link: https://developer.cisco.com/docs/apic-mim-ref/ author: - Tim Cragg (@timcragg) diff --git a/ansible_collections/cisco/aci/plugins/modules/aci_dhcp_relay_provider.py b/ansible_collections/cisco/aci/plugins/modules/aci_dhcp_relay_provider.py index efb9e8e54..2d3dcaf50 100644 --- a/ansible_collections/cisco/aci/plugins/modules/aci_dhcp_relay_provider.py +++ b/ansible_collections/cisco/aci/plugins/modules/aci_dhcp_relay_provider.py @@ -14,9 +14,9 @@ ANSIBLE_METADATA = {"metadata_version": "1.1", "status": ["preview"], "supported DOCUMENTATION = r""" --- module: aci_dhcp_relay_provider -short_description: Manage DHCP relay policy providers. +short_description: Manage DHCP relay policy providers (dhcp:RsProv) description: -- Manage DHCP relay policy providers (dhcpRsProv) configuration on Cisco ACI fabrics. +- Manage DHCP relay policy providers configuration on Cisco ACI fabrics. options: tenant: description: @@ -91,7 +91,7 @@ notes: The M(cisco.aci.aci_tenant) and C(cisco.aci.aci_dhcp_relay) modules can be used for this. seealso: - name: APIC Management Information Model reference - description: More information about the internal APIC class B(dhcpRsProv). + description: More information about the internal APIC class B(dhcp:RsProv). link: https://developer.cisco.com/docs/apic-mim-ref/ author: - Tim Cragg (@timcragg) diff --git a/ansible_collections/cisco/aci/plugins/modules/aci_dns_domain.py b/ansible_collections/cisco/aci/plugins/modules/aci_dns_domain.py index 4325c7513..11ef520fa 100644 --- a/ansible_collections/cisco/aci/plugins/modules/aci_dns_domain.py +++ b/ansible_collections/cisco/aci/plugins/modules/aci_dns_domain.py @@ -13,7 +13,7 @@ ANSIBLE_METADATA = {"metadata_version": "1.1", "status": ["preview"], "supported DOCUMENTATION = r""" --- module: aci_dns_domain -short_description: Manage DNS Provider (dnsDomain) objects. +short_description: Manage DNS Provider objects (dns:Domain) description: - Manage DNS Domain configuration on Cisco ACI fabrics. options: @@ -49,7 +49,7 @@ notes: seealso: - name: APIC Management Information Model reference - description: More information about the internal APIC class B(dnsDomain). + description: More information about the internal APIC class B(dns:Domain). link: https://developer.cisco.com/docs/apic-mim-ref/ author: - Tim Cragg (@timcragg) diff --git a/ansible_collections/cisco/aci/plugins/modules/aci_dns_profile.py b/ansible_collections/cisco/aci/plugins/modules/aci_dns_profile.py index 47efb62c4..a4a535a73 100644 --- a/ansible_collections/cisco/aci/plugins/modules/aci_dns_profile.py +++ b/ansible_collections/cisco/aci/plugins/modules/aci_dns_profile.py @@ -13,7 +13,7 @@ ANSIBLE_METADATA = {"metadata_version": "1.1", "status": ["preview"], "supported DOCUMENTATION = r""" --- module: aci_dns_profile -short_description: Manage DNS Profile (dnsProfile) objects. +short_description: Manage DNS Profile objects (dns:Profile) description: - Manage DNS Profile configuration on Cisco ACI fabrics. options: @@ -35,7 +35,7 @@ extends_documentation_fragment: seealso: - name: APIC Management Information Model reference - description: More information about the internal APIC class B(dnsProfile). + description: More information about the internal APIC class B(dns:Profile). link: https://developer.cisco.com/docs/apic-mim-ref/ author: - Tim Cragg (@timcragg) diff --git a/ansible_collections/cisco/aci/plugins/modules/aci_dns_provider.py b/ansible_collections/cisco/aci/plugins/modules/aci_dns_provider.py index 1fe2c2e60..7b74bd2b6 100644 --- a/ansible_collections/cisco/aci/plugins/modules/aci_dns_provider.py +++ b/ansible_collections/cisco/aci/plugins/modules/aci_dns_provider.py @@ -13,7 +13,7 @@ ANSIBLE_METADATA = {"metadata_version": "1.1", "status": ["preview"], "supported DOCUMENTATION = r""" --- module: aci_dns_provider -short_description: Manage DNS Provider (dnsProv) objects. +short_description: Manage DNS Provider objects (dns:Prov) description: - Manage DNS Provider configuration on Cisco ACI fabrics. options: diff --git a/ansible_collections/cisco/aci/plugins/modules/aci_domain.py b/ansible_collections/cisco/aci/plugins/modules/aci_domain.py index 75509b0ef..ea65805b8 100644 --- a/ansible_collections/cisco/aci/plugins/modules/aci_domain.py +++ b/ansible_collections/cisco/aci/plugins/modules/aci_domain.py @@ -12,7 +12,7 @@ ANSIBLE_METADATA = {"metadata_version": "1.1", "status": ["preview"], "supported 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) +short_description: Manage physical, virtual, bridged, routed or FC domain profiles (phys:DomP, vmm:DomP, l2ext:DomP, l3ext:DomP, and fc:DomP) description: - Manage physical, virtual, bridged, routed or FC domain profiles on Cisco ACI fabrics. options: diff --git a/ansible_collections/cisco/aci/plugins/modules/aci_encap_pool.py b/ansible_collections/cisco/aci/plugins/modules/aci_encap_pool.py index 5d5ed7833..360e84c3f 100644 --- a/ansible_collections/cisco/aci/plugins/modules/aci_encap_pool.py +++ b/ansible_collections/cisco/aci/plugins/modules/aci_encap_pool.py @@ -12,7 +12,7 @@ ANSIBLE_METADATA = {"metadata_version": "1.1", "status": ["preview"], "supported DOCUMENTATION = r""" --- module: aci_encap_pool -short_description: Manage encap pools (fvns:VlanInstP, fvns:VxlanInstP, fvns:VsanInstP) +short_description: Manage encap pools (fvns:VlanInstP, fvns:VxlanInstP, and fvns:VsanInstP) description: - Manage vlan, vxlan, and vsan pools on Cisco ACI fabrics. options: diff --git a/ansible_collections/cisco/aci/plugins/modules/aci_encap_pool_range.py b/ansible_collections/cisco/aci/plugins/modules/aci_encap_pool_range.py index 43d34e78d..29da16a7d 100644 --- a/ansible_collections/cisco/aci/plugins/modules/aci_encap_pool_range.py +++ b/ansible_collections/cisco/aci/plugins/modules/aci_encap_pool_range.py @@ -12,7 +12,7 @@ ANSIBLE_METADATA = {"metadata_version": "1.1", "status": ["preview"], "supported DOCUMENTATION = r""" --- module: aci_encap_pool_range -short_description: Manage encap ranges assigned to pools (fvns:EncapBlk, fvns:VsanEncapBlk) +short_description: Manage encap ranges assigned to pools (fvns:EncapBlk and fvns:VsanEncapBlk) description: - Manage vlan, vxlan, and vsan ranges that are assigned to pools on Cisco ACI fabrics. options: diff --git a/ansible_collections/cisco/aci/plugins/modules/aci_epg.py b/ansible_collections/cisco/aci/plugins/modules/aci_epg.py index 9f0eb671a..b9faec64e 100644 --- a/ansible_collections/cisco/aci/plugins/modules/aci_epg.py +++ b/ansible_collections/cisco/aci/plugins/modules/aci_epg.py @@ -1,6 +1,8 @@ #!/usr/bin/python # -*- coding: utf-8 -*- +# Copyright: (c) 2023, Christian Kolrep +# Copyright: (c) 2024, Akini Ross # GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) from __future__ import absolute_import, division, print_function @@ -78,6 +80,17 @@ options: - Use C(yes) to create uSeg EPG and C(no) is used to create Application EPG. type: str choices: [ 'yes', 'no' ] + match: + description: + - The match type of the default Block Statement (fv:Crtrn). + - The APIC defaults to C(any) when unset during creation. + type: str + choices: [ any, all ] + precedence: + description: + - The Block Statement(fv:Crtrn) Precedence to resolve equal matches between micro segmented EPGs. + - The APIC defaults to C(0) when unset during creation. + type: int state: description: - Use C(present) or C(absent) for adding or removing. @@ -105,6 +118,8 @@ seealso: author: - Swetha Chunduri (@schunduri) - Shreyas Srish (@shrsr) +- Christian Kolrep (@Christian-Kolrep) +- Akini Ross (@akinross) """ EXAMPLES = r""" @@ -123,25 +138,6 @@ EXAMPLES = r""" 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: Add a new uSeg EPG cisco.aci.aci_epg: host: apic @@ -158,17 +154,22 @@ EXAMPLES = r""" state: present delegate_to: localhost -- name: Remove an EPG +- name: Add a uSeg EPG with block statement match and precedence cisco.aci.aci_epg: host: apic username: admin password: SomeSecretPassword - validate_certs: false tenant: production - app_profile: intranet + ap: intranet epg: web_epg + description: Web Intranet EPG + bd: prod_bd monitoring_policy: default - state: absent + preferred_group: true + useg: 'yes' + match: all + precedence: 1 + state: present delegate_to: localhost - name: Query an EPG @@ -213,6 +214,19 @@ EXAMPLES = r""" state: query delegate_to: localhost register: query_result + +- name: Remove an EPG + cisco.aci.aci_epg: + host: apic + username: admin + password: SomeSecretPassword + validate_certs: false + tenant: production + app_profile: intranet + epg: web_epg + monitoring_policy: default + state: absent + delegate_to: localhost """ RETURN = r""" @@ -342,6 +356,8 @@ def main(): monitoring_policy=dict(type="str"), custom_qos_policy=dict(type="str"), useg=dict(type="str", choices=["yes", "no"]), + match=dict(type="str", choices=["all", "any"]), + precedence=dict(type="int"), ) module = AnsibleModule( @@ -369,6 +385,8 @@ def main(): monitoring_policy = module.params.get("monitoring_policy") custom_qos_policy = module.params.get("custom_qos_policy") useg = module.params.get("useg") + match = module.params.get("match") + precedence = module.params.get("precedence") child_configs = [dict(fvRsBd=dict(attributes=dict(tnFvBDName=bd))), dict(fvRsAEPgMonPol=dict(attributes=dict(tnMonEPGPolName=monitoring_policy)))] @@ -394,12 +412,17 @@ def main(): module_object=epg, target_filter={"name": epg}, ), - child_classes=["fvRsBd", "fvRsAEPgMonPol", "fvRsCustQosPol"], + child_classes=["fvRsBd", "fvRsAEPgMonPol", "fvRsCustQosPol", "fvCrtrn"], ) aci.get_existing() if state == "present": + if useg is not None and aci.existing and aci.existing[0]["fvAEPg"]["attributes"]["isAttrBasedEPg"] != useg: + module.fail_json(msg="Changing attribute useg on existing EPG is not supported.") + if useg == "yes": + child_configs.append(dict(fvCrtrn=dict(attributes=dict(name="default", match=match, prec=precedence)))) + aci.payload( aci_class="fvAEPg", class_config=dict( diff --git a/ansible_collections/cisco/aci/plugins/modules/aci_epg_to_contract.py b/ansible_collections/cisco/aci/plugins/modules/aci_epg_to_contract.py index fe09945a3..9faf882c8 100644 --- a/ansible_collections/cisco/aci/plugins/modules/aci_epg_to_contract.py +++ b/ansible_collections/cisco/aci/plugins/modules/aci_epg_to_contract.py @@ -1,6 +1,8 @@ #!/usr/bin/python # -*- coding: utf-8 -*- +# Copyright: (c) 2017, Jacob McGill (@jmcgill298) +# Copyright: (c) 2023, Akini Ross (@akinross) # GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) from __future__ import absolute_import, division, print_function @@ -12,7 +14,7 @@ ANSIBLE_METADATA = {"metadata_version": "1.1", "status": ["preview"], "supported DOCUMENTATION = r""" --- module: aci_epg_to_contract -short_description: Bind EPGs to Contracts (fv:RsCons, fv:RsProv) +short_description: Bind EPGs to Contracts (fv:RsCons, fv:RsProv, fv:RsProtBy, fv:RsConsIf, and fv:RsIntraEpg) description: - Bind EPGs to Contracts on Cisco ACI fabrics. notes: @@ -26,15 +28,15 @@ options: aliases: [ app_profile, app_profile_name ] contract: description: - - The name of the contract. + - The name of the contract or contract interface. type: str - aliases: [ contract_name ] + aliases: [ contract_name, contract_interface ] contract_type: description: - - Determines if the EPG should Provide or Consume the Contract. + - Determines the type of the Contract. type: str required: true - choices: [ consumer, provider ] + choices: [ consumer, provider, taboo, interface, intra_epg ] epg: description: - The name of the end point group. @@ -81,10 +83,11 @@ seealso: - 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). + description: More information about the internal APIC classes B(fv:RsCons), B(fv:RsProv), B(fv:RsProtBy), B(fv:RsConsIf), and B(fv:RsIntraEpg). link: https://developer.cisco.com/docs/apic-mim-ref/ author: - Jacob McGill (@jmcgill298) +- Akini Ross (@akinross) """ EXAMPLES = r""" @@ -248,44 +251,17 @@ url: from ansible.module_utils.basic import AnsibleModule from ansible_collections.cisco.aci.plugins.module_utils.aci import ACIModule, aci_argument_spec, aci_annotation_spec - -ACI_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", -) - -CONTRACT_LABEL_MAPPING = dict( - consumer="vzConsLbl", - provider="vzProvLbl", -) - -SUBJ_LABEL_MAPPING = dict( - consumer="vzConsSubjLbl", - provider="vzProvSubjLbl", -) +from ansible_collections.cisco.aci.plugins.module_utils.constants import ACI_CLASS_MAPPING, CONTRACT_LABEL_MAPPING, PROVIDER_MATCH_MAPPING, SUBJ_LABEL_MAPPING def main(): argument_spec = aci_argument_spec() argument_spec.update(aci_annotation_spec()) argument_spec.update( - contract_type=dict(type="str", required=True, choices=["consumer", "provider"]), + contract_type=dict(type="str", required=True, choices=["consumer", "provider", "taboo", "interface", "intra_epg"]), 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 + contract=dict(type="str", aliases=["contract_name", "contract_interface"]), # Not required for querying all objects priority=dict(type="str", choices=["level1", "level2", "level3", "level4", "level5", "level6", "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"]), @@ -318,13 +294,19 @@ def main(): aci_class = ACI_CLASS_MAPPING[contract_type]["class"] aci_rn = ACI_CLASS_MAPPING[contract_type]["rn"] - contract_label_class = CONTRACT_LABEL_MAPPING[contract_type] - subject_label_class = SUBJ_LABEL_MAPPING[contract_type] + aci_name = ACI_CLASS_MAPPING[contract_type]["name"] + child_classes = [] - if contract_type == "consumer" and provider_match is not None: + if contract_type != "provider" and provider_match is not None: module.fail_json(msg="the 'provider_match' is only configurable for Provided Contracts") - child_classes = [subject_label_class, contract_label_class] + if contract_type in ["taboo", "interface", "intra_epg"] and (contract_label is not None or subject_label is not None): + module.fail_json(msg="the 'contract_label' and 'subject_label' are not configurable for {0} contracts".format(contract_type)) + + if contract_type not in ["taboo", "interface", "intra_epg"]: + contract_label_class = CONTRACT_LABEL_MAPPING.get(contract_type) + subject_label_class = SUBJ_LABEL_MAPPING.get(contract_type) + child_classes = [subject_label_class, contract_label_class] aci = ACIModule(module) aci.construct_url( @@ -350,7 +332,7 @@ def main(): aci_class=aci_class, aci_rn="{0}{1}".format(aci_rn, contract), module_object=contract, - target_filter={"tnVzBrCPName": contract}, + target_filter={aci_name: contract}, ), child_classes=child_classes, ) @@ -359,17 +341,13 @@ def main(): if state == "present": child_configs = [] - if contract_label: + if contract_label is not None: child_configs.append({contract_label_class: {"attributes": {"name": contract_label}}}) - if subject_label: + if subject_label is not None: child_configs.append({subject_label_class: {"attributes": {"name": subject_label}}}) aci.payload( aci_class=aci_class, - class_config=dict( - matchT=provider_match, - prio=priority, - tnVzBrCPName=contract, - ), + class_config={"matchT": provider_match, "prio": priority, aci_name: contract}, child_configs=child_configs, ) diff --git a/ansible_collections/cisco/aci/plugins/modules/aci_epg_to_contract_interface.py b/ansible_collections/cisco/aci/plugins/modules/aci_epg_to_contract_interface.py index bc0ed04fa..ff3a7908c 100644 --- a/ansible_collections/cisco/aci/plugins/modules/aci_epg_to_contract_interface.py +++ b/ansible_collections/cisco/aci/plugins/modules/aci_epg_to_contract_interface.py @@ -13,7 +13,7 @@ ANSIBLE_METADATA = {"metadata_version": "1.1", "status": ["preview"], "supported DOCUMENTATION = r""" --- module: aci_epg_to_contract_interface -short_description: Bind EPGs to Consumed Contracts Interface (fv:RsConsIf). +short_description: Bind EPGs to Consumed Contracts Interface (fv:RsConsIf) description: - Bind EPGs to Consumed Contracts Interface on Cisco ACI fabrics. diff --git a/ansible_collections/cisco/aci/plugins/modules/aci_epg_to_domain.py b/ansible_collections/cisco/aci/plugins/modules/aci_epg_to_domain.py index 90f34cc29..1b82f9361 100644 --- a/ansible_collections/cisco/aci/plugins/modules/aci_epg_to_domain.py +++ b/ansible_collections/cisco/aci/plugins/modules/aci_epg_to_domain.py @@ -137,7 +137,7 @@ options: description: - The delimiter. type: str - choices: [ "|", "~", "!", "@", "^", "+", "=" ] + choices: [ "|", "~", "!", "@", "^", "+", "=", "_" ] untagged_vlan: description: - The access vlan is untagged. @@ -384,7 +384,7 @@ def main(): vm_provider=dict(type="str", choices=["cloudfoundry", "kubernetes", "microsoft", "openshift", "openstack", "redhat", "vmware"]), promiscuous=dict(type="str", default="reject", choices=["accept", "reject"]), custom_epg_name=dict(type="str"), - delimiter=dict(type="str", choices=["|", "~", "!", "@", "^", "+", "="]), + delimiter=dict(type="str", choices=["|", "~", "!", "@", "^", "+", "=", "_"]), untagged_vlan=dict(type="bool"), port_binding=dict(type="str", choices=["dynamic", "ephemeral", "static"]), port_allocation=dict(type="str", choices=["elastic", "fixed"]), diff --git a/ansible_collections/cisco/aci/plugins/modules/aci_epg_useg_attribute_block_statement.py b/ansible_collections/cisco/aci/plugins/modules/aci_epg_useg_attribute_block_statement.py new file mode 100644 index 000000000..9664b4640 --- /dev/null +++ b/ansible_collections/cisco/aci/plugins/modules/aci_epg_useg_attribute_block_statement.py @@ -0,0 +1,348 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- + +# Copyright: (c) 2024, Akini Ross +# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) + +from __future__ import absolute_import, division, print_function + +__metaclass__ = type + +ANSIBLE_METADATA = {"metadata_version": "1.1", "status": ["preview"], "supported_by": "certified"} + +DOCUMENTATION = r""" +--- +module: aci_epg_useg_attribute_block_statement +short_description: Manage EPG useg Attributes Block Statements (fv:SCrtrn) +description: +- Manage EPG useg Attributes Block Statements +options: + tenant: + description: + - The name of an existing tenant. + type: str + aliases: [ tenant_name ] + ap: + description: + - The name of an existing application network profile. + type: str + aliases: [ app_profile, app_profile_name ] + epg: + description: + - The name of an existing end point group. + type: str + aliases: [ epg_name ] + parent_block_statements: + description: + - The list of parent block statements. + - The order of the provided list matters, assuming the list ["A", "B"]. + - The block statement "A" will be the parent of "B" + - The block statement "A" will be a child of the default block statement. + - The maximum amount of parent block statements is 2. + type: list + elements: str + aliases: [ blocks, parent_blocks ] + name: + description: + - The name of the block statement. + type: str + aliases: [ block_statement, block_statement_name ] + match: + description: + - The match type of the Block Statement. + - The APIC defaults to C(any) when unset during creation. + type: str + choices: [ any, all ] + state: + description: + - Use C(present) or C(absent) for adding or removing. + - Use C(query) for listing an object or multiple objects. + type: str + choices: [ absent, present, query ] + default: present +extends_documentation_fragment: +- cisco.aci.aci +- cisco.aci.annotation + +notes: +- The I(tenant), I(ap) and I(epg) used must exist before using this module in your playbook. + The M(cisco.aci.aci_tenant), M(cisco.aci.aci_ap) and 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:SCrtrn). + link: https://developer.cisco.com/docs/apic-mim-ref/ +author: +- Akini Ross (@akinross)) +""" + +EXAMPLES = r""" +- name: Add a new block statement + cisco.aci.aci_epg_useg_attribute_block_statement: + host: apic + username: admin + password: SomeSecretPassword + tenant: anstest + ap: anstest + epg: anstest + name: block_a + state: present + delegate_to: localhost + +- name: Add a new nested block statement + cisco.aci.aci_epg_useg_attribute_block_statement: + host: apic + username: admin + password: SomeSecretPassword + tenant: anstest + ap: anstest + epg: anstest + parent_block_statements: + - block_a + - block_b + name: block_c + match: any + state: present + delegate_to: localhost + +- name: Query a block statement + cisco.aci.aci_epg_useg_attribute_block_statement: + host: apic + username: admin + password: SomeSecretPassword + tenant: anstest + ap: anstest + epg: anstest + name: block_a + state: query + delegate_to: localhost + register: query_result + +- name: Query all block statements + cisco.aci.aci_epg_useg_attribute_block_statement: + host: apic + username: admin + password: SomeSecretPassword + state: query + delegate_to: localhost + register: query_result + +- name: Remove an existing block statement + cisco.aci.aci_epg_useg_attribute_block_statement: + host: apic + username: admin + password: SomeSecretPassword + tenant: anstest + ap: anstest + epg: anstest + name: block_a + 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: '' +sent: + description: The actual/minimal configuration pushed to the APIC + returned: info + type: list + sample: + { + "fvTenant": { + "attributes": { + "descr": "Production environment" + } + } + } +previous: + description: The original configuration from the APIC before the module has started + returned: info + type: list + sample: + [ + { + "fvTenant": { + "attributes": { + "descr": "Production", + "dn": "uni/tn-production", + "name": "production", + "nameAlias": "", + "ownerKey": "", + "ownerTag": "" + } + } + } + ] +proposed: + description: The assembled configuration from the user-provided parameters + returned: info + type: dict + sample: + { + "fvTenant": { + "attributes": { + "descr": "Production environment", + "name": "production" + } + } + } +filter_string: + description: The filter string used for the request + returned: failure or debug + type: str + sample: ?rsp-prop-include=config-only +method: + description: The HTTP method used for the request to the APIC + returned: failure or debug + type: str + sample: POST +response: + description: The HTTP response from the APIC + returned: failure or debug + type: str + sample: OK (30 bytes) +status: + description: The HTTP status from the APIC + returned: failure or debug + type: int + sample: 200 +url: + description: The HTTP url used for the request to the APIC + returned: failure or debug + type: str + sample: https://10.11.12.13/api/mo/uni/tn-production.json +""" + +from ansible.module_utils.basic import AnsibleModule +from ansible_collections.cisco.aci.plugins.module_utils.aci import ACIModule, aci_argument_spec, aci_annotation_spec + + +def main(): + argument_spec = aci_argument_spec() + argument_spec.update(aci_annotation_spec()) + argument_spec.update( + 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 + state=dict(type="str", default="present", choices=["absent", "present", "query"]), + tenant=dict(type="str", aliases=["tenant_name"]), # Not required for querying all objects + parent_block_statements=dict(type="list", elements="str", aliases=["parent_blocks", "blocks"]), + name=dict(type="str", aliases=["block_statement", "block_statement_name"]), + match=dict(type="str", choices=["any", "all"]), + ) + + module = AnsibleModule( + argument_spec=argument_spec, + supports_check_mode=True, + required_if=[ + ["state", "absent", ["ap", "epg", "tenant", "name"]], + ["state", "present", ["ap", "epg", "tenant", "name"]], + ], + ) + + aci = ACIModule(module) + + ap = module.params.get("ap") + epg = module.params.get("epg") + state = module.params.get("state") + tenant = module.params.get("tenant") + blocks = module.params.get("parent_block_statements") + name = module.params.get("name") + match = module.params.get("match") + + block_statement_class = "fvSCrtrn" + + if blocks: + if len(blocks) > 2: + module.fail_json(msg="{0} block statements are provided but the maximum amount of parent_block_statements is 2".format(len(blocks))) + parent_blocks_class = block_statement_class + parent_blocks_rn = "crtrn/crtrn-{0}".format("/crtrn-".join(blocks)) + parent_blocks_name = blocks[-1] + else: + parent_blocks_class = "fvCrtrn" + parent_blocks_rn = "crtrn" + parent_blocks_name = "default" + + aci.construct_url( + root_class=dict( + 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=parent_blocks_class, + aci_rn=parent_blocks_rn, + module_object=parent_blocks_name, + target_filter={"name": parent_blocks_name}, + ), + subclass_4=dict( + aci_class=block_statement_class, + aci_rn="crtrn-{0}".format(name), + module_object=name, + target_filter={"name": name}, + ), + ) + + aci.get_existing() + + if state == "present": + aci.payload(aci_class=block_statement_class, class_config=dict(name=name, match=match)) + + aci.get_diff(aci_class=block_statement_class) + + aci.post_config() + + elif state == "absent": + aci.delete_config() + + aci.exit_json() + + +if __name__ == "__main__": + main() diff --git a/ansible_collections/cisco/aci/plugins/modules/aci_epg_useg_attribute_simple_statement.py b/ansible_collections/cisco/aci/plugins/modules/aci_epg_useg_attribute_simple_statement.py new file mode 100644 index 000000000..462a7fcaa --- /dev/null +++ b/ansible_collections/cisco/aci/plugins/modules/aci_epg_useg_attribute_simple_statement.py @@ -0,0 +1,436 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- + +# Copyright: (c) 2023, Christian Kolrep +# Copyright: (c) 2024, Akini Ross +# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) + +from __future__ import absolute_import, division, print_function + +__metaclass__ = type + +ANSIBLE_METADATA = {"metadata_version": "1.1", "status": ["preview"], "supported_by": "certified"} + +DOCUMENTATION = r""" +--- +module: aci_epg_useg_attribute_simple_statement +short_description: Manage EPG useg Attributes Simple Statements (fv:DnsAttr, fv:IdGroupAttr, fv:IpAttr, fv:MacAttr, and fv:VmAttr) +description: +- Manage EPG useg Attributes Simple Statements +options: + tenant: + description: + - The name of an existing tenant. + type: str + aliases: [ tenant_name ] + ap: + description: + - The name of an existing application network profile. + type: str + aliases: [ app_profile, app_profile_name ] + epg: + description: + - The name of an existing end point group. + type: str + aliases: [ epg_name ] + parent_block_statements: + description: + - The list of parent block statements. + - The order of the provided list matters, assuming the list ["A", "B", "C"]. + - The block statement "A" will be the parent of "B" + - The block statement "A" will be a child of the default block statement. + - The maximum amount of parent block statements is 3. + type: list + elements: str + aliases: [ blocks, parent_blocks ] + name: + description: + - The name of the EPG useg attribute. + type: str + aliases: [ useg_attribute_name ] + type: + description: + - The type of the EPG useg attribute + type: str + required: true + choices: + - ip + - mac + - dns + - ad_group + - vm_custom_attr + - vm_vmm_domain + - vm_operating_system + - vm_hypervisor_id + - vm_datacenter + - vm_id + - vm_name + - vm_folder + - vm_folder_path + - vm_vnic + - vm_tag + aliases: [ useg_attribute_type ] + operator: + description: + - The operator of the EPG useg attribute. + type: str + choices: [ equals, contains, starts_with, ends_with ] + category: + description: + - The name of the vmware tag category or vmware custom attribute. + type: str + aliases: [ custom_attribute ] + use_subnet: + description: + - Whether to use the EPG subnet definition for ip. + type: bool + value: + description: + - The value of the EPG useg attribute. + type: str + state: + description: + - Use C(present) or C(absent) for adding or removing. + - Use C(query) for listing an object or multiple objects. + type: str + choices: [ absent, present, query ] + default: present +extends_documentation_fragment: +- cisco.aci.aci +- cisco.aci.annotation + +notes: +- The I(tenant), I(ap) and I(epg) used must exist before using this module in your playbook. + The M(cisco.aci.aci_tenant), M(cisco.aci.aci_ap) and 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:DnsAttr), B(fv:IdGroupAttr), B(fv:IpAttr), B(fv:MacAttr), and B(fv:VmAttr). + link: https://developer.cisco.com/docs/apic-mim-ref/ +author: +- Christian Kolrep (@Christian-Kolrep) +- Akini Ross (@akinross) +""" + +EXAMPLES = r""" +- name: Add a new vmtag useg attribute in default block statement + cisco.aci.aci_epg_useg_attribute_simple_statement: + host: apic + username: admin + password: SomeSecretPassword + tenant: anstest + ap: anstest + epg: anstest + name: vmtagprod + type: vmtag + category: Environment + operator: equals + value: Production + state: present + delegate_to: localhost + +- name: Add a new vmtag useg attribute in nested block statement + cisco.aci.aci_epg_useg_attribute_simple_statement: + host: apic + username: admin + password: SomeSecretPassword + tenant: anstest + ap: anstest + epg: anstest + name: vmtagprod + parent_block_statements: + - block_a + - block_b + type: vmtag + category: Environment + operator: equals + value: Production + state: present + delegate_to: localhost + +- name: Query a specific vmtag useg attribute in default block statement + cisco.aci.aci_epg_useg_attribute_simple_statement: + host: apic + username: admin + password: SomeSecretPassword + tenant: anstest + ap: anstest + epg: anstest + name: vmtagprod + type: vmtag + state: query + delegate_to: localhost + register: query_result + +- name: Query all vmtag useg attributes + cisco.aci.aci_epg_useg_attribute_simple_statement: + host: apic + username: admin + password: SomeSecretPassword + state: query + type: vmtag + delegate_to: localhost + register: query_result + +- name: Remove an existing vmtag useg attribute from default block statement + cisco.aci.aci_epg_useg_attribute_simple_statement: + host: apic + username: admin + password: SomeSecretPassword + tenant: anstest + ap: anstest + epg: anstest + name: vmtagprod + type: vmtag + 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: '' +sent: + description: The actual/minimal configuration pushed to the APIC + returned: info + type: list + sample: + { + "fvTenant": { + "attributes": { + "descr": "Production environment" + } + } + } +previous: + description: The original configuration from the APIC before the module has started + returned: info + type: list + sample: + [ + { + "fvTenant": { + "attributes": { + "descr": "Production", + "dn": "uni/tn-production", + "name": "production", + "nameAlias": "", + "ownerKey": "", + "ownerTag": "" + } + } + } + ] +proposed: + description: The assembled configuration from the user-provided parameters + returned: info + type: dict + sample: + { + "fvTenant": { + "attributes": { + "descr": "Production environment", + "name": "production" + } + } + } +filter_string: + description: The filter string used for the request + returned: failure or debug + type: str + sample: ?rsp-prop-include=config-only +method: + description: The HTTP method used for the request to the APIC + returned: failure or debug + type: str + sample: POST +response: + description: The HTTP response from the APIC + returned: failure or debug + type: str + sample: OK (30 bytes) +status: + description: The HTTP status from the APIC + returned: failure or debug + type: int + sample: 200 +url: + description: The HTTP url used for the request to the APIC + returned: failure or debug + type: str + sample: https://10.11.12.13/api/mo/uni/tn-production.json +""" + +from ansible.module_utils.basic import AnsibleModule +from ansible_collections.cisco.aci.plugins.module_utils.aci import ACIModule, aci_argument_spec, aci_annotation_spec +from ansible_collections.cisco.aci.plugins.module_utils.constants import USEG_ATTRIBUTE_MAPPING, OPERATOR_MAPPING + + +def main(): + argument_spec = aci_argument_spec() + argument_spec.update(aci_annotation_spec()) + argument_spec.update( + 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 + state=dict(type="str", default="present", choices=["absent", "present", "query"]), + tenant=dict(type="str", aliases=["tenant_name"]), # Not required for querying all objects + parent_block_statements=dict(type="list", elements="str", aliases=["parent_blocks", "blocks"]), + name=dict(type="str", aliases=["useg_attribute_name"]), + type=dict(type="str", required=True, choices=list(USEG_ATTRIBUTE_MAPPING.keys()), aliases=["useg_attribute_type"]), + operator=dict(type="str", choices=list(OPERATOR_MAPPING.keys())), + category=dict(type="str", aliases=["custom_attribute"]), + value=dict(type="str"), + use_subnet=dict(type="bool"), + ) + + module = AnsibleModule( + argument_spec=argument_spec, + supports_check_mode=True, + required_if=[ + ["state", "absent", ["ap", "epg", "tenant", "name"]], + ["state", "present", ["ap", "epg", "tenant", "name"]], + ], + ) + + aci = ACIModule(module) + + ap = module.params.get("ap") + epg = module.params.get("epg") + state = module.params.get("state") + tenant = module.params.get("tenant") + blocks = module.params.get("parent_block_statements") + name = module.params.get("name") + attribute_type = module.params.get("type") + value = module.params.get("value") + operator = module.params.get("operator") + category = module.params.get("category") + use_subnet = aci.boolean(module.params.get("use_subnet")) + + # Excluding below classes from the module: + # fvProtoAttr: + # Was used in AVS, but it is not longer in use. + # fvUsegBDCont: + # Was part of a feature that allowed uSeg attributes to be applied at VRF (instead of BD) level. + # It has been since deprecated and we no longer allow setting the scope at fvCtrn to scope-vrf. + # This type of functionality has been replaced by the ESG feature. + attribute_class = USEG_ATTRIBUTE_MAPPING[attribute_type]["attribute_class"] + attribute_rn = USEG_ATTRIBUTE_MAPPING[attribute_type]["rn_format"].format(name) + attribute_type = USEG_ATTRIBUTE_MAPPING[attribute_type]["attribute_type"] + + if blocks: + if len(blocks) > 3: + module.fail_json(msg="{0} block statements are provided but the maximum amount of parent_block_statements is 3".format(len(blocks))) + parent_blocks_class = "fvSCrtrn" + parent_blocks_rn = "crtrn/crtrn-{0}".format("/crtrn-".join(blocks)) + parent_blocks_name = blocks[-1] + else: + parent_blocks_class = "fvCrtrn" + parent_blocks_rn = "crtrn" + parent_blocks_name = "default" + + aci.construct_url( + root_class=dict( + 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=parent_blocks_class, + aci_rn=parent_blocks_rn, + module_object=parent_blocks_name, + target_filter={"name": parent_blocks_name}, + ), + subclass_4=dict( + aci_class=attribute_class, + aci_rn=attribute_rn, + module_object=name, + target_filter={"name": name}, + ), + ) + + aci.get_existing() + + if state == "present": + class_config = dict(name=name) + + if attribute_class == "fvVmAttr": + class_config.update(type=attribute_type) + class_config.update(operator=OPERATOR_MAPPING.get(operator)) + class_config.update(value=value) + if attribute_type == "tag": + class_config.update(category=category) + elif attribute_type == "custom-label": + class_config.update(labelName=category) + + elif attribute_class == "fvIpAttr": + class_config.update(usefvSubnet=use_subnet) + class_config.update(ip=value) + + elif attribute_class == "fvMacAttr": + class_config.update(mac=value.upper()) + + elif attribute_class == "fvDnsAttr": + class_config.update(filter=value) + + elif attribute_class == "fvIdGroupAttr": + class_config.update(selector=value) + + aci.payload(aci_class=attribute_class, class_config=class_config) + + aci.get_diff(aci_class=attribute_class) + + aci.post_config() + + elif state == "absent": + aci.delete_config() + + aci.exit_json() + + +if __name__ == "__main__": + main() diff --git a/ansible_collections/cisco/aci/plugins/modules/aci_esg_ip_subnet_selector.py b/ansible_collections/cisco/aci/plugins/modules/aci_esg_ip_subnet_selector.py index 368f9e6dc..b8632ec6a 100644 --- a/ansible_collections/cisco/aci/plugins/modules/aci_esg_ip_subnet_selector.py +++ b/ansible_collections/cisco/aci/plugins/modules/aci_esg_ip_subnet_selector.py @@ -14,7 +14,7 @@ ANSIBLE_METADATA = {"metadata_version": "1.1", "status": ["preview"], "supported DOCUMENTATION = r""" --- module: aci_esg_ip_subnet_selector -short_description: Manage ESG IP Subnet selector(fv:EPSelector) +short_description: Manage ESG IP Subnet selector (fv:EPSelector) description: - Manage Endpoint Security Groups (ESG) IP Subnet selector on Cisco ACI fabrics. diff --git a/ansible_collections/cisco/aci/plugins/modules/aci_fabric_external_connection_profile.py b/ansible_collections/cisco/aci/plugins/modules/aci_fabric_external_connection_profile.py new file mode 100644 index 000000000..efea05338 --- /dev/null +++ b/ansible_collections/cisco/aci/plugins/modules/aci_fabric_external_connection_profile.py @@ -0,0 +1,311 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- +# Copyright: (c) 2024, Samita Bhattacharjee (@samitab) + +# 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_external_connection_profile +short_description: Manage Fabric External Connection Profiles (fv:FabricExtConnP). +description: +- Manage Fabric External Connection Profiles (Intrasite/Intersite profiles) on Cisco ACI fabrics. +options: + description: + description: + - Specifies a description of the profile definition. + type: str + aliases: [ descr ] + fabric_id: + description: + - The fabric identifier of the Fabric External Connection Profile. + type: int + aliases: [ id, fabric ] + name: + description: + - The name of the Fabric External Connection Profile. + type: str + aliases: [ profile_name ] + community: + description: + - Global EVPN Route Target of the Fabric External Connection Profile. + - eg. extended:as2-nn4:5:16 + type: str + aliases: [ rt, route_target ] + site_id: + description: + - The site identifier of the Fabric External Connection Profile. + type: int + aliases: [ sid, site, s_id ] + peering_type: + description: + - The BGP EVPN Peering Type. Use either C(automatic_with_full_mesh) or C(automatic_with_rr). + type: str + choices: [ automatic_with_full_mesh, automatic_with_rr ] + aliases: [ p_type, peer, peer_t ] + peering_password: + description: + - The BGP EVPN Peering Password. Used for setting automatic peering sessions. + type: str + aliases: [ peer_password, peer_pwd ] + state: + description: + - Use C(present) or C(absent) for adding or removing. + - Use C(query) for listing an object or multiple objects. + type: str + choices: [ absent, present, query ] + default: present +extends_documentation_fragment: +- cisco.aci.aci +- cisco.aci.annotation +- cisco.aci.owner + +seealso: +- name: APIC Management Information Model reference + description: More information about the internal APIC class B(fv:FabricExtConnP). + link: https://developer.cisco.com/docs/apic-mim-ref/ +author: +- Samita Bhattacharjee (@samitab) +""" + +EXAMPLES = r""" +- name: Add a new Fabric External Connection Profile + cisco.aci.aci_fabric_external_connection_profile: + host: apic + username: admin + password: SomeSecretPassword + fabric_id: 1 + name: ansible_fabric_ext_conn_profile + description: Fabric External Connection Profile + community: extended:as2-nn4:5:16 + site_id: 1 + peering_type: automatic_with_rr + peering_password: SomeSecretPeeringPassword + state: present + delegate_to: localhost + +- name: Query a Fabric External Connection Profile + cisco.aci.aci_fabric_external_connection_profile: + host: apic + username: admin + password: SomeSecretPassword + fabric_id: 1 + state: query + delegate_to: localhost + register: query_result + +- name: Query all Fabric External Connection Profiles + cisco.aci.aci_fabric_external_connection_profile: + host: apic + username: admin + password: SomeSecretPassword + state: query + delegate_to: localhost + register: query_result + +- name: Remove a Fabric External Connection Profile + cisco.aci.aci_fabric_external_connection_profile: + host: apic + username: admin + password: SomeSecretPassword + fabric_id: 1 + 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: '' +sent: + description: The actual/minimal configuration pushed to the APIC + returned: info + type: list + sample: + { + "fvTenant": { + "attributes": { + "descr": "Production environment" + } + } + } +previous: + description: The original configuration from the APIC before the module has started + returned: info + type: list + sample: + [ + { + "fvTenant": { + "attributes": { + "descr": "Production", + "dn": "uni/tn-production", + "name": "production", + "nameAlias": "", + "ownerKey": "", + "ownerTag": "" + } + } + } + ] +proposed: + description: The assembled configuration from the user-provided parameters + returned: info + type: dict + sample: + { + "fvTenant": { + "attributes": { + "descr": "Production environment", + "name": "production" + } + } + } +filter_string: + description: The filter string used for the request + returned: failure or debug + type: str + sample: ?rsp-prop-include=config-only +method: + description: The HTTP method used for the request to the APIC + returned: failure or debug + type: str + sample: POST +response: + description: The HTTP response from the APIC + returned: failure or debug + type: str + sample: OK (30 bytes) +status: + description: The HTTP status from the APIC + returned: failure or debug + type: int + sample: 200 +url: + description: The HTTP url used for the request to the APIC + returned: failure or debug + type: str + sample: https://10.11.12.13/api/mo/uni/tn-production.json +""" + +from ansible.module_utils.basic import AnsibleModule +from ansible_collections.cisco.aci.plugins.module_utils.aci import ACIModule, aci_argument_spec, aci_annotation_spec, aci_owner_spec + + +def main(): + argument_spec = aci_argument_spec() + argument_spec.update(aci_annotation_spec()) + argument_spec.update(aci_owner_spec()) + argument_spec.update( + description=dict(type="str", aliases=["descr"]), + fabric_id=dict(type="int", aliases=["id", "fabric"]), + name=dict(type="str", aliases=["profile_name"]), + community=dict(type="str", aliases=["rt", "route_target"]), + site_id=dict(type="int", aliases=["sid", "site", "s_id"]), + peering_type=dict(type="str", aliases=["p_type", "peer", "peer_t"], choices=["automatic_with_full_mesh", "automatic_with_rr"]), + peering_password=dict(type="str", aliases=["peer_password", "peer_pwd"], no_log=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", ["fabric_id"]], + ["state", "present", ["fabric_id"]], + ], + ) + + aci = ACIModule(module) + + description = module.params.get("description") + fabric_id = module.params.get("fabric_id") + name = module.params.get("name") + community = module.params.get("community") + peering_type = module.params.get("peering_type") + peering_password = module.params.get("peering_password") + site_id = module.params.get("site_id") + state = module.params.get("state") + + aci.construct_url( + root_class=dict( + aci_class="fvFabricExtConnP", + aci_rn="tn-infra/fabricExtConnP-{0}".format(fabric_id), + module_object=fabric_id, + target_filter={"id": fabric_id}, + ), + child_classes=["fvPeeringP"], + ) + + aci.get_existing() + + if state == "present": + child_configs = None + if peering_type is not None or peering_password is not None: + peering_p = {"fvPeeringP": {"attributes": {}}} + if peering_type is not None: + peering_p["fvPeeringP"]["attributes"]["type"] = peering_type + if peering_password is not None: + peering_p["fvPeeringP"]["attributes"]["password"] = peering_password + child_configs = [peering_p] + + aci.payload( + aci_class="fvFabricExtConnP", + class_config=dict( + descr=description, + id=fabric_id, + name=name, + rt=community, + siteId=site_id, + ), + child_configs=child_configs, + ) + + aci.get_diff(aci_class="fvFabricExtConnP") + + aci.post_config() + + elif state == "absent": + aci.delete_config() + + aci.exit_json() + + +if __name__ == "__main__": + main() diff --git a/ansible_collections/cisco/aci/plugins/modules/aci_fabric_external_routing_profile.py b/ansible_collections/cisco/aci/plugins/modules/aci_fabric_external_routing_profile.py new file mode 100644 index 000000000..539705def --- /dev/null +++ b/ansible_collections/cisco/aci/plugins/modules/aci_fabric_external_routing_profile.py @@ -0,0 +1,315 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- +# Copyright: (c) 2024, Samita Bhattacharjee (@samitab) + +# 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_external_routing_profile +short_description: Manage Fabric External Routing Profiles (l3ext:FabricExtRoutingP) +description: +- Manage Fabric External Routing Profiles on Cisco ACI fabrics. +options: + name: + description: + - The name of the Fabric External Routing Profile. + type: str + aliases: [ routing_profile, profile ] + fabric_id: + description: + - The Fabric ID associated with the Fabric External Routing Profile. + type: int + aliases: [ fabric, fid] + description: + description: + - The description of the Fabric External Routing Profile. + type: str + aliases: [ descr ] + subnets: + description: + - The list of external subnet IP addresses. + - Duplicate subnet IP addresses are not valid and would be ignored. + type: list + elements: str + aliases: [ ip_addresses, ips ] + state: + description: + - Use C(present) or C(absent) for adding or removing. + - Use C(query) for listing an object or multiple objects. + type: str + choices: [ absent, present, query ] + default: present +extends_documentation_fragment: +- cisco.aci.aci +- cisco.aci.annotation +- cisco.aci.owner + +notes: +- This module requires an existing I(fabric_external_connection_profile). + The module M(cisco.aci.aci_fabric_external_connection_profile) can be used for this. +seealso: +- name: APIC Management Information Model reference + description: More information about the internal APIC class B(l3ext:FabricExtRoutingP). + link: https://developer.cisco.com/docs/apic-mim-ref/ +author: +- Samita Bhattacharjee (@samitab) +""" + +# TODO EXAMPLES +EXAMPLES = r""" +- name: Add an External Routing Profile + cisco.aci.aci_fabric_external_routing_profile: + host: apic + username: admin + password: SomeSecretPassword + fabric_id: "1" + description: "Fabric external routing profile" + name: "ansible_fabric_ext_routing_profile" + subnets: + - 1.2.3.4/24 + - 5.6.7.8/24 + state: present + delegate_to: localhost + +- name: Query an External Routing Profile + cisco.aci.aci_fabric_external_routing_profile: + host: apic + username: admin + password: SomeSecretPassword + fabric_id: 1 + name: ansible_fabric_ext_routing_profile + state: query + delegate_to: localhost + register: query_result + +- name: Query all External Routing Profiles + cisco.aci.aci_fabric_external_routing_profile: + host: apic + username: admin + password: SomeSecretPassword + state: query + delegate_to: localhost + register: query_result + +- name: Remove an External Routing Profile + cisco.aci.aci_fabric_external_routing_profile: + host: apic + username: admin + password: SomeSecretPassword + fabric_id: 1 + name: ansible_fabric_ext_routing_profile + 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: '' +sent: + description: The actual/minimal configuration pushed to the APIC + returned: info + type: list + sample: + { + "fvTenant": { + "attributes": { + "descr": "Production environment" + } + } + } +previous: + description: The original configuration from the APIC before the module has started + returned: info + type: list + sample: + [ + { + "fvTenant": { + "attributes": { + "descr": "Production", + "dn": "uni/tn-production", + "name": "production", + "nameAlias": "", + "ownerKey": "", + "ownerTag": "" + } + } + } + ] +proposed: + description: The assembled configuration from the user-provided parameters + returned: info + type: dict + sample: + { + "fvTenant": { + "attributes": { + "descr": "Production environment", + "name": "production" + } + } + } +filter_string: + description: The filter string used for the request + returned: failure or debug + type: str + sample: ?rsp-prop-include=config-only +method: + description: The HTTP method used for the request to the APIC + returned: failure or debug + type: str + sample: POST +response: + description: The HTTP response from the APIC + returned: failure or debug + type: str + sample: OK (30 bytes) +status: + description: The HTTP status from the APIC + returned: failure or debug + type: int + sample: 200 +url: + description: The HTTP url used for the request to the APIC + returned: failure or debug + type: str + sample: https://10.11.12.13/api/mo/uni/tn-production.json +""" + +from ansible.module_utils.basic import AnsibleModule +from ansible_collections.cisco.aci.plugins.module_utils.aci import ACIModule, aci_argument_spec, aci_annotation_spec, aci_owner_spec + + +def main(): + argument_spec = aci_argument_spec() + argument_spec.update(aci_annotation_spec()) + argument_spec.update(aci_owner_spec()) + argument_spec.update( + name=dict(type="str", aliases=["routing_profile", "profile"]), + fabric_id=dict(type="int", aliases=["fabric", "fid"]), + description=dict(type="str", aliases=["descr"]), + subnets=dict(type="list", elements="str", aliases=["ip_addresses", "ips"]), + state=dict(type="str", default="present", choices=["absent", "present", "query"]), + ) + + module = AnsibleModule( + argument_spec=argument_spec, + supports_check_mode=True, + required_if=[ + ["state", "absent", ["fabric_id", "name"]], + ["state", "present", ["fabric_id", "name"]], + ], + ) + + aci = ACIModule(module) + + name = module.params.get("name") + fabric_id = module.params.get("fabric_id") + description = module.params.get("description") + subnets = module.params.get("subnets") + state = module.params.get("state") + + # Remove duplicate subnets + if isinstance(subnets, list): + subnets = list(dict.fromkeys(subnets)) + + aci.construct_url( + root_class=dict( + aci_class="fvFabricExtConnP", + aci_rn="tn-infra/fabricExtConnP-{0}".format(fabric_id), + module_object=fabric_id, + target_filter={"id": fabric_id}, + ), + subclass_1=dict( + aci_class="l3extFabricExtRoutingP", + aci_rn="fabricExtRoutingP-{0}".format(name), + module_object=name, + target_filter={"name": name}, + ), + child_classes=["l3extSubnet"], + ) + + aci.get_existing() + + if state == "present": + child_configs = [] + + # Validate if existing and remove subnet objects when the config does not match the provided config. + if isinstance(aci.existing, list) and len(aci.existing) > 0: + subnets = [] if subnets is None else subnets + for child in aci.existing[0].get("l3extFabricExtRoutingP", {}).get("children", {}): + if child.get("l3extSubnet") and child.get("l3extSubnet").get("attributes").get("ip") not in subnets: + child_configs.append( + { + "l3extSubnet": { + "attributes": { + "ip": child.get("l3extSubnet").get("attributes").get("ip"), + "status": "deleted", + } + } + } + ) + + if subnets is not None: + for subnet in subnets: + child_configs.append({"l3extSubnet": {"attributes": {"ip": subnet}}}) + + aci.payload( + aci_class="l3extFabricExtRoutingP", + class_config=dict( + name=name, + descr=description, + ), + child_configs=child_configs, + ) + + aci.get_diff(aci_class="l3extFabricExtRoutingP") + + aci.post_config() + + elif state == "absent": + aci.delete_config() + + aci.exit_json() + + +if __name__ == "__main__": + main() diff --git a/ansible_collections/cisco/aci/plugins/modules/aci_fabric_interface_policy_group.py b/ansible_collections/cisco/aci/plugins/modules/aci_fabric_interface_policy_group.py index 4048187db..a6a62b3da 100644 --- a/ansible_collections/cisco/aci/plugins/modules/aci_fabric_interface_policy_group.py +++ b/ansible_collections/cisco/aci/plugins/modules/aci_fabric_interface_policy_group.py @@ -13,7 +13,7 @@ ANSIBLE_METADATA = {"metadata_version": "1.1", "status": ["preview"], "supported DOCUMENTATION = r""" --- module: aci_fabric_interface_policy_group -short_description: Manage Fabric Interface Policy Groups (fabric:LePortPGrp, fabric:SpPortPGrp) +short_description: Manage Fabric Interface Policy Groups (fabric:LePortPGrp and fabric:SpPortPGrp) description: - Manage Fabric Interface Policy Groups on Cisco ACI fabrics. options: diff --git a/ansible_collections/cisco/aci/plugins/modules/aci_fabric_leaf_profile.py b/ansible_collections/cisco/aci/plugins/modules/aci_fabric_leaf_profile.py index 09c87a387..590fbd7ba 100644 --- a/ansible_collections/cisco/aci/plugins/modules/aci_fabric_leaf_profile.py +++ b/ansible_collections/cisco/aci/plugins/modules/aci_fabric_leaf_profile.py @@ -12,7 +12,7 @@ ANSIBLE_METADATA = {"metadata_version": "1.1", "status": ["preview"], "supported DOCUMENTATION = r""" --- module: aci_fabric_leaf_profile -short_description: Manage fabric leaf profiles (fabric:LeafP). +short_description: Manage fabric leaf profiles (fabric:LeafP) description: - Manage fabric leaf switch profiles in an ACI fabric. options: diff --git a/ansible_collections/cisco/aci/plugins/modules/aci_fabric_management_access.py b/ansible_collections/cisco/aci/plugins/modules/aci_fabric_management_access.py new file mode 100644 index 000000000..493de3947 --- /dev/null +++ b/ansible_collections/cisco/aci/plugins/modules/aci_fabric_management_access.py @@ -0,0 +1,700 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- + +# Copyright: (c) 2024, Akini Ross (@akinross) +# 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_management_access +short_description: Manage Fabric Management Access (comm:Pol) +description: +- Manage Fabric Management Access on Cisco ACI fabrics. +options: + name: + description: + - The name of the Fabric Management Access policy. + type: str + aliases: [ fabric_management_access_policy_name ] + description: + description: + - The description of the Fabric Management Access policy. + type: str + aliases: [ descr ] + name_alias: + description: + - The name alias of the Fabric Management Access policy. + - This relates to the nameAlias property in ACI. + type: str + http: + description: + - Parameters for HTTP configuration (comm:Http). + type: dict + suboptions: + admin_state: + description: + - The admin state of the HTTP connection. + - The APIC defaults to C(disabled) when unset during creation. + type: str + choices: [ enabled, disabled ] + port: + description: + - The port for the HTTP connection. + - The APIC defaults to C(80) when unset during creation. + type: int + redirect: + description: + - The state of the HTTP to HTTPS redirect service. + - The APIC defaults to C(disabled) when unset during creation. + type: str + choices: [ enabled, disabled, tested ] + allow_origins: + description: + - The allowed origins for the HTTP connection. + - 'Example format: http://127.0.0.1:8000' + type: str + allow_credentials: + description: + - The state of the allow credential for the HTTP connection. + - The APIC defaults to C(disabled) when unset during creation. + type: str + choices: [ enabled, disabled ] + throttle: + description: + - The state of the request throttle for the HTTP connection. + - The APIC defaults to C(disabled) when unset during creation. + type: str + choices: [ enabled, disabled ] + throttle_rate: + description: + - The rate of the request throttle. + - The APIC defaults to C(10000) when unset during creation. + type: int + throttle_unit: + description: + - The unit of the request throttle rate. + - The APIC defaults to C(requests_per_second) when unset during creation. + type: str + choices: [ requests_per_second, requests_per_minute ] + https: + description: + - Parameters for HTTPS configuration (comm:Https). + type: dict + suboptions: + admin_state: + description: + - The admin state of the HTTPS connection. + - The APIC defaults to C(enabled) when unset during creation. + type: str + choices: [ enabled, disabled ] + port: + description: + - The port for the HTTPS connection. + - The APIC defaults to C(443) when unset during creation. + type: int + allow_origins: + description: + - The allowed origins for the HTTPS connection. + - 'Example format: http://127.0.0.1:8000' + type: str + allow_credentials: + description: + - The state of the allow credential for the HTTPS connection. + - The APIC defaults to C(disabled) when unset during creation. + type: str + choices: [ enabled, disabled ] + ssl: + description: + - The SSL protocol(s) for the HTTPS connection. + - The APIC defaults to C(tls_v1.1) and C(tls_v1.2) set when unset during creation. + type: list + elements: str + choices: [ tls_v1.0, tls_v1.1, tls_v1.2, tls_v1.3 ] + aliases: [ ssl_protocols ] + dh_param: + description: + - The Diffie-Hellman parameter for the HTTPS connection. + - The APIC defaults to C(none) when unset during creation. + type: str + choices: [ '1024', '2048', '4096', none ] + throttle: + description: + - The state of the request throttle for the HTTPS connection. + - The APIC defaults to C(disabled) when unset during creation. + type: str + choices: [ enabled, disabled ] + throttle_rate: + description: + - The rate of the request throttle. + - The APIC defaults to C(10000) when unset during creation. + type: int + throttle_unit: + description: + - The unit of the request throttle rate. + - The APIC defaults to C(requests_per_second) when unset during creation. + type: str + choices: [ requests_per_second, requests_per_minute ] + admin_key_ring: + description: + - The admin key ring for the HTTPS connection. + - The APIC defaults to C(default) when unset during creation. + type: str + client_certificate_trustpoint: + description: + - The client certificate trustpoint for the HTTPS connection. + type: str + aliases: [ trustpoint ] + client_certificate_authentication_state: + description: + - The client certificate authentication state for the HTTPS connection. + - The APIC defaults to C(disabled) when unset during creation. + - The C(enabled) state requires a C(client_certificate_trustpoint) to be set. + type: str + choices: [ enabled, disabled ] + aliases: [ client_certificate_auth_state, auth_state, authentication_state ] + telnet: + description: + - Parameters for telnet configuration (comm:Telnet). + type: dict + suboptions: + admin_state: + description: + - The admin state of the telnet connection. + - The APIC defaults to C(disabled) when unset during creation. + type: str + choices: [ enabled, disabled ] + port: + description: + - The port for the telnet connection. + - The APIC defaults to C(23) when unset during creation. + type: int + ssh: + description: + - Parameters for SSH configuration (comm:Ssh). + type: dict + suboptions: + admin_state: + description: + - The admin state of the SSH connection. + - The APIC defaults to C(enabled) when unset during creation. + type: str + choices: [ enabled, disabled ] + password_auth_state: + description: + - The password authentication state of the SSH connection. + - The APIC defaults to C(enabled) when unset during creation. + type: str + choices: [ enabled, disabled ] + port: + description: + - The port for the SSH connection. + - The APIC defaults to C(22) when unset during creation. + type: int + ciphers: + description: + - The ciphers of the SSH connection. + - The APIC defaults to all options set when unset during creation. + type: list + elements: str + choices: [ aes128_ctr, aes192_ctr, aes256_ctr, aes128_gcm, aes256_gcm, chacha20 ] + kex: + description: + - The KEX algorithms of the SSH connection. + - The APIC defaults to all options set when unset during creation. + type: list + elements: str + choices: [ dh_sha1, dh_sha256, dh_sha512, curve_sha256, curve_sha256_libssh, ecdh_256, ecdh_384, ecdh_521 ] + macs: + description: + - The MACs of the SSH connection. + - The APIC defaults to all options set when unset during creation. + type: list + elements: str + choices: [ sha1, sha2_256, sha2_512, sha2_256_etm, sha2_512_etm ] + ssh_web: + description: + - Parameters for SSH access via WEB configuration (comm:Shellinabox). + type: dict + suboptions: + admin_state: + description: + - The admin state of the SSH access via WEB connection. + - The APIC defaults to C(disabled) when unset during creation. + type: str + choices: [ enabled, disabled ] + state: + description: + - Use C(present) for updating configuration. + - Use C(query) for showing current configuration. + type: str + choices: [ absent, present, query ] + default: present +extends_documentation_fragment: +- cisco.aci.aci +- cisco.aci.annotation +- cisco.aci.owner + +seealso: +- name: APIC Management Information Model reference + description: More information about the internal APIC class B(comm:Pol). + link: https://developer.cisco.com/docs/apic-mim-ref/ +author: +- Akini Ross (@akinross) +""" + +EXAMPLES = r""" +- name: Create a Fabric Management Access policy + cisco.aci.aci_fabric_management_access: + host: apic + username: admin + password: SomeSecretPassword + name: fabric_management_access_policy_1 + description: "This is a example Fabric Management Access policy." + state: present + delegate_to: localhost + +- name: Create a Fabric Management Access policy with telnet enabled + cisco.aci.aci_fabric_management_access: + host: apic + username: admin + password: SomeSecretPassword + name: fabric_management_access_policy_1 + description: "This is a example Fabric Management Access policy." + telnet: + admin_state: enabled + state: present + delegate_to: localhost + +- name: Create a Fabric Management Access policy with SSH access via WEB enabled + cisco.aci.aci_fabric_management_access: + host: apic + username: admin + password: SomeSecretPassword + name: fabric_management_access_policy_1 + description: "This is a example Fabric Management Access policy." + ssh_web: + admin_state: enabled + state: present + delegate_to: localhost + +- name: Create a Fabric Management Access policy with SSH enabled and ciphers set + cisco.aci.aci_fabric_management_access: + host: apic + username: admin + password: SomeSecretPassword + name: fabric_management_access_policy_1 + description: "This is a example Fabric Management Access policy." + ssh: + admin_state: enabled + ciphers: + - aes128_ctr + - aes192_ctr + - aes256_ctr + state: present + delegate_to: localhost + +- name: Create a Fabric Management Access policy with HTTP enabled + cisco.aci.aci_fabric_management_access: + host: apic + username: admin + password: SomeSecretPassword + name: fabric_management_access_policy_1 + description: "This is a example Fabric Management Access policy." + http: + admin_state: enabled + allow_origins: http://127.0.0.1:8000 + throttle: enabled + throttle_rate: 7500 + throttle_unit: requests_per_minute + state: present + delegate_to: localhost + +- name: Create a Fabric Management Access policy with HTTPS enabled + cisco.aci.aci_fabric_management_access: + host: apic + username: admin + password: SomeSecretPassword + name: fabric_management_access_policy_1 + description: "This is a example Fabric Management Access policy." + https: + admin_state: enabled + port: 445 + allow_origins: http://127.0.0.1:8000 + allow_credentials: enabled + ssl: + - tls_v1.2 + dh_param: 4096 + throttle: enabled + throttle_rate: 7500 + throttle_unit: requests_per_minute + admin_key_ring: default + client_certificate_trustpoint: ansible_trustpoint + client_certificate_authentication_state: enabled + state: present + delegate_to: localhost + +- name: Query a Fabric Management Access policy + cisco.aci.aci_fabric_management_access: + host: apic + username: admin + password: SomeSecretPassword + name: fabric_management_access_policy_1 + state: query + delegate_to: localhost + register: query_result + +- name: Query all Fabric Management Access policies + cisco.aci.aci_fabric_management_access: + host: apic + username: admin + password: SomeSecretPassword + state: query + delegate_to: localhost + register: query_result + +- name: Delete a Fabric Management Access policy + cisco.aci.aci_fabric_management_access: + host: apic + username: admin + password: SomeSecretPassword + name: fabric_management_access_policy_1 + 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: '' +sent: + description: The actual/minimal configuration pushed to the APIC + returned: info + type: list + sample: + { + "fvTenant": { + "attributes": { + "descr": "Production environment" + } + } + } +previous: + description: The original configuration from the APIC before the module has started + returned: info + type: list + sample: + [ + { + "fvTenant": { + "attributes": { + "descr": "Production", + "dn": "uni/tn-production", + "name": "production", + "nameAlias": "", + "ownerKey": "", + "ownerTag": "" + } + } + } + ] +proposed: + description: The assembled configuration from the user-provided parameters + returned: info + type: dict + sample: + { + "fvTenant": { + "attributes": { + "descr": "Production environment", + "name": "production" + } + } + } +filter_string: + description: The filter string used for the request + returned: failure or debug + type: str + sample: ?rsp-prop-include=config-only +method: + description: The HTTP method used for the request to the APIC + returned: failure or debug + type: str + sample: POST +response: + description: The HTTP response from the APIC + returned: failure or debug + type: str + sample: OK (30 bytes) +status: + description: The HTTP status from the APIC + returned: failure or debug + type: int + sample: 200 +url: + description: The HTTP url used for the request to the APIC + returned: failure or debug + type: str + sample: https://10.11.12.13/api/mo/uni/tn-production.json +""" + +from ansible.module_utils.basic import AnsibleModule +from ansible_collections.cisco.aci.plugins.module_utils.aci import ACIModule, aci_argument_spec, aci_annotation_spec, aci_owner_spec +from ansible_collections.cisco.aci.plugins.module_utils.constants import THROTTLE_UNIT, SSH_CIPHERS, KEX_ALGORITHMS, SSH_MACS, HTTP_TLS_MAPPING + + +def main(): + argument_spec = aci_argument_spec() + argument_spec.update(aci_annotation_spec()) + argument_spec.update(aci_owner_spec()) + argument_spec.update( + name=dict(type="str", aliases=["fabric_management_access_policy_name"]), # Not required for querying all objects + description=dict(type="str", aliases=["descr"]), + name_alias=dict(type="str"), + http=dict( + type="dict", + options=dict( + admin_state=dict(type="str", choices=["enabled", "disabled"]), + port=dict(type="int"), + redirect=dict(type="str", choices=["enabled", "disabled", "tested"]), + allow_origins=dict(type="str"), + allow_credentials=dict(type="str", choices=["enabled", "disabled"]), + throttle=dict(type="str", choices=["enabled", "disabled"]), + throttle_rate=dict(type="int"), + throttle_unit=dict(type="str", choices=["requests_per_second", "requests_per_minute"]), + ), + ), + https=dict( + type="dict", + options=dict( + admin_state=dict(type="str", choices=["enabled", "disabled"]), + port=dict(type="int"), + allow_origins=dict(type="str"), + allow_credentials=dict(type="str", choices=["enabled", "disabled"]), + ssl=dict( + type="list", + elements="str", + choices=list(HTTP_TLS_MAPPING.keys()), + aliases=["ssl_protocols"], + ), + dh_param=dict(type="str", choices=["1024", "2048", "4096", "none"]), + throttle=dict(type="str", choices=["enabled", "disabled"]), + throttle_rate=dict(type="int"), + throttle_unit=dict(type="str", choices=["requests_per_second", "requests_per_minute"]), + admin_key_ring=dict(type="str", no_log=False), + client_certificate_trustpoint=dict(type="str", aliases=["trustpoint"]), + client_certificate_authentication_state=dict( + type="str", + choices=["enabled", "disabled"], + aliases=["client_certificate_auth_state", "auth_state", "authentication_state"], + ), + ), + ), + telnet=dict( + type="dict", + options=dict( + admin_state=dict(type="str", choices=["enabled", "disabled"]), + port=dict(type="int"), + ), + ), + ssh=dict( + type="dict", + options=dict( + admin_state=dict(type="str", choices=["enabled", "disabled"]), + password_auth_state=dict(type="str", choices=["enabled", "disabled"]), + port=dict(type="int"), + ciphers=dict(type="list", elements="str", choices=list(SSH_CIPHERS.keys())), + kex=dict(type="list", elements="str", choices=list(KEX_ALGORITHMS.keys())), + macs=dict(type="list", elements="str", choices=list(SSH_MACS.keys())), + ), + ), + ssh_web=dict( + type="dict", + options=dict( + admin_state=dict(type="str", choices=["enabled", "disabled"]), + ), + ), + state=dict(type="str", default="present", choices=["absent", "present", "query"]), + ) + + module = AnsibleModule( + argument_spec=argument_spec, + supports_check_mode=True, + required_if=[ + ["state", "present", ["name"]], + ["state", "absent", ["name"]], + ], + ) + + aci = ACIModule(module) + aci_class = "commPol" + aci_child_classes = ["commSsh", "commHttp", "commHttps", "commTelnet", "commShellinabox"] + + name = module.params.get("name") + description = module.params.get("description") + name_alias = module.params.get("name_alias") + http = module.params.get("http") + https = module.params.get("https") + telnet = module.params.get("telnet") + ssh = module.params.get("ssh") + ssh_web = module.params.get("ssh_web") + state = module.params.get("state") + + aci.construct_url( + root_class=dict( + aci_class=aci_class, + aci_rn="fabric/comm-{0}".format(name), + module_object=name, + target_filter={"name": name}, + ), + child_classes=aci_child_classes, + ) + + aci.get_existing() + + if state == "present": + child_configs = [] + + if ssh: + child_configs.append( + dict( + commSsh=dict( + attributes=dict( + adminSt=ssh.get("admin_state"), + passwordAuth=ssh.get("password_auth_state"), + port=ssh.get("port"), + sshCiphers=",".join(sorted(SSH_CIPHERS.get(v) for v in set(ssh.get("ciphers")))) if ssh.get("ciphers") else None, + kexAlgos=",".join(sorted(KEX_ALGORITHMS.get(v) for v in set(ssh.get("kex")))) if ssh.get("kex") else None, + sshMacs=",".join(sorted(SSH_MACS.get(v) for v in set(ssh.get("macs")))) if ssh.get("macs") else None, + ) + ) + ) + ) + + if http: + child_configs.append( + dict( + commHttp=dict( + attributes=dict( + adminSt=http.get("admin_state"), + port=http.get("port"), + redirectSt=http.get("redirect"), + accessControlAllowOrigins=http.get("allow_origins"), + accessControlAllowCredential=http.get("allow_credentials"), + globalThrottleSt=http.get("throttle"), + globalThrottleRate=http.get("throttle_rate"), + globalThrottleUnit=THROTTLE_UNIT.get(http.get("throttle_unit")), + ) + ) + ) + ) + + if https: + https_config = dict( + commHttps=dict( + attributes=dict( + adminSt=https.get("admin_state"), + port=https.get("port"), + accessControlAllowOrigins=https.get("allow_origins"), + accessControlAllowCredential=https.get("allow_credentials"), + sslProtocols=",".join(sorted(HTTP_TLS_MAPPING.get(v) for v in set(https.get("ssl")))) if https.get("ssl") else None, + dhParam=https.get("dh_param"), + globalThrottleSt=https.get("throttle"), + globalThrottleRate=https.get("throttle_rate"), + globalThrottleUnit=THROTTLE_UNIT.get(https.get("throttle_unit")), + clientCertAuthState=https.get("client_certificate_authentication_state"), + ), + children=[], + ) + ) + + if https.get("admin_key_ring"): + https_config["commHttps"]["children"].append(dict(commRsKeyRing=dict(attributes=dict(tnPkiKeyRingName=https.get("admin_key_ring"))))) + + if https.get("client_certificate_trustpoint"): + https_config["commHttps"]["children"].append( + dict(commRsClientCertCA=dict(attributes=dict(tDn="uni/userext/pkiext/tp-{0}".format(https.get("client_certificate_trustpoint"))))) + ) + + child_configs.append(https_config) + + if telnet: + child_configs.append( + dict( + commTelnet=dict( + attributes=dict( + adminSt=telnet.get("admin_state"), + port=telnet.get("port"), + ) + ) + ) + ) + + if ssh_web: + child_configs.append( + dict( + commShellinabox=dict( + attributes=dict( + adminSt=ssh_web.get("admin_state"), + ) + ) + ) + ) + + aci.payload( + aci_class=aci_class, + class_config=dict( + name=name, + descr=description, + nameAlias=name_alias, + ), + child_configs=child_configs, + ) + + 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/ansible_collections/cisco/aci/plugins/modules/aci_fabric_management_access_https_cipher.py b/ansible_collections/cisco/aci/plugins/modules/aci_fabric_management_access_https_cipher.py new file mode 100644 index 000000000..96952f263 --- /dev/null +++ b/ansible_collections/cisco/aci/plugins/modules/aci_fabric_management_access_https_cipher.py @@ -0,0 +1,282 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- + +# Copyright: (c) 2024, Akini Ross (@akinross) +# 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_management_access_https_cipher +short_description: Manage Fabric Management Access HTTPS SSL Cipher Configuration (comm:Cipher) +description: +- Manage Fabric Management Access HTTPS SSL Cipher Configuration on Cisco ACI fabrics. +options: + fabric_management_access_policy_name: + description: + - The name of the Fabric Management Access policy. + type: str + aliases: [ name ] + id: + description: + - The ID of the SSL Cipher Configuration. + type: str + cipher_state: + description: + - The state of the SSL Cipher Configuration. + type: str + choices: [ enabled, disabled ] + name_alias: + description: + - The name alias of the Fabric Management Access HTTPS SSL Cipher Configuration. + - This relates to the nameAlias property in ACI. + type: str + state: + description: + - Use C(present) for updating configuration. + - Use C(query) for showing current configuration. + type: str + choices: [ absent, present, query ] + default: present +extends_documentation_fragment: +- cisco.aci.aci +- cisco.aci.annotation +- cisco.aci.owner + +notes: +- The C(fabric_management_access_policy_name) must exist before using this module in your playbook. + The M(cisco.aci.aci_fabric_management_access) module can be used for this. +seealso: +- name: APIC Management Information Model reference + description: More information about the internal APIC class B(comm:Cipher). + link: https://developer.cisco.com/docs/apic-mim-ref/ +author: +- Akini Ross (@akinross) +""" + +EXAMPLES = r""" +- name: Create a Fabric Management Access HTTPS SSL Cipher + cisco.aci.aci_fabric_management_access_https_cipher: + host: apic + username: admin + password: SomeSecretPassword + fabric_management_access_policy_name: fabric_management_access_policy_1 + id: DHE-RSA-AES128-SHA + cipher_state: enabled + state: present + delegate_to: localhost + +- name: Query a Fabric Management Access HTTPS SSL Cipher + cisco.aci.aci_fabric_management_access_https_cipher: + host: apic + username: admin + password: SomeSecretPassword + fabric_management_access_policy_name: fabric_management_access_policy_1 + id: DHE-RSA-AES128-SHA + state: query + delegate_to: localhost + register: query_result + +- name: Query all Fabric Management Access policies + cisco.aci.aci_fabric_management_access_https_cipher: + host: apic + username: admin + password: SomeSecretPassword + state: query + delegate_to: localhost + register: query_result + +- name: Delete a Fabric Management Access HTTPS SSL Cipher + cisco.aci.aci_fabric_management_access_https_cipher: + host: apic + username: admin + password: SomeSecretPassword + fabric_management_access_policy_name: fabric_management_access_policy_1 + id: DHE-RSA-AES128-SHA + 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: '' +sent: + description: The actual/minimal configuration pushed to the APIC + returned: info + type: list + sample: + { + "fvTenant": { + "attributes": { + "descr": "Production environment" + } + } + } +previous: + description: The original configuration from the APIC before the module has started + returned: info + type: list + sample: + [ + { + "fvTenant": { + "attributes": { + "descr": "Production", + "dn": "uni/tn-production", + "name": "production", + "nameAlias": "", + "ownerKey": "", + "ownerTag": "" + } + } + } + ] +proposed: + description: The assembled configuration from the user-provided parameters + returned: info + type: dict + sample: + { + "fvTenant": { + "attributes": { + "descr": "Production environment", + "name": "production" + } + } + } +filter_string: + description: The filter string used for the request + returned: failure or debug + type: str + sample: ?rsp-prop-include=config-only +method: + description: The HTTP method used for the request to the APIC + returned: failure or debug + type: str + sample: POST +response: + description: The HTTP response from the APIC + returned: failure or debug + type: str + sample: OK (30 bytes) +status: + description: The HTTP status from the APIC + returned: failure or debug + type: int + sample: 200 +url: + description: The HTTP url used for the request to the APIC + returned: failure or debug + type: str + sample: https://10.11.12.13/api/mo/uni/tn-production.json +""" + +from ansible.module_utils.basic import AnsibleModule +from ansible_collections.cisco.aci.plugins.module_utils.aci import ACIModule, aci_argument_spec, aci_annotation_spec, aci_owner_spec + + +def main(): + argument_spec = aci_argument_spec() + argument_spec.update(aci_annotation_spec()) + argument_spec.update(aci_owner_spec()) + argument_spec.update( + fabric_management_access_policy_name=dict(type="str", aliases=["name"]), # Not required for querying all objects + id=dict(type="str"), + cipher_state=dict(type="str", choices=["enabled", "disabled"]), + name_alias=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", "present", ["fabric_management_access_policy_name", "id", "cipher_state"]], + ["state", "absent", ["fabric_management_access_policy_name", "id"]], + ], + ) + + aci = ACIModule(module) + aci_class = "commCipher" + + fabric_management_access_policy_name = module.params.get("fabric_management_access_policy_name") + id_value = module.params.get("id") + cipher_state = module.params.get("cipher_state") + name_alias = module.params.get("name_alias") + state = module.params.get("state") + + aci.construct_url( + root_class=dict( + aci_class=aci_class, + aci_rn="fabric/comm-{0}".format(fabric_management_access_policy_name), + module_object=fabric_management_access_policy_name, + target_filter={"name": fabric_management_access_policy_name}, + ), + subclass_1=dict( + aci_class=aci_class, + aci_rn="https/cph-{0}".format(id_value), + module_object=id_value, + target_filter={"id": id_value}, + ), + ) + + aci.get_existing() + + if state == "present": + aci.payload( + aci_class=aci_class, + class_config=dict( + id=id_value, + state=cipher_state, + 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/ansible_collections/cisco/aci/plugins/modules/aci_fabric_pod.py b/ansible_collections/cisco/aci/plugins/modules/aci_fabric_pod.py new file mode 100644 index 000000000..b9adc1d27 --- /dev/null +++ b/ansible_collections/cisco/aci/plugins/modules/aci_fabric_pod.py @@ -0,0 +1,292 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- + +# Copyright: (c) 2023, Samita Bhattacharjee (@samitab) +# 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_pod +short_description: Manage Fabric Pod Setup Policy (fabric:SetupP) +description: +- Manage Fabric Pod Setup Policy on Cisco ACI fabrics. +options: + pod_id: + description: + - The Pod ID for the Fabric Pod Setup Policy. + - Accepted value range between C(1) and C(254). + type: int + aliases: [ pod, id ] + pod_type: + description: + - The type of the Pod. Use C(physical) or C(virtual). + - The APIC defaults to C(physical) when unset during creation. + type: str + choices: [ physical, virtual ] + aliases: [ type ] + tep_pool: + description: + - The TEP address pool for the Fabric Pod Setup Policy. + - Must be valid IPv4 and include the subnet mask. + - Example 192.168.1.0/24 + type: str + aliases: [ tep, pool ] + description: + description: + - The description for the Fabric Pod Setup 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 +- cisco.aci.annotation +- cisco.aci.owner + +seealso: +- name: APIC Management Information Model reference + description: More information about the internal APIC class B(fabric:SetupP). + link: https://developer.cisco.com/docs/apic-mim-ref/ +author: +- Samita Bhattacharjee (@samitab) +""" + +EXAMPLES = r""" +- name: Add a fabric pod setup policy + cisco.aci.aci_fabric_pod: + host: apic + username: admin + password: SomeSecretPassword + pod_id: 1 + tep_pool: 10.0.0.0/16 + state: present + delegate_to: localhost + +- name: Query the fabric pod setup policy + cisco.aci.aci_fabric_pod: + host: apic + username: admin + password: SomeSecretPassword + pod_id: 1 + state: query + delegate_to: localhost + register: query_result + +- name: Query all fabric pod setup policies + cisco.aci.aci_fabric_pod: + host: apic + username: admin + password: SomeSecretPassword + state: query + delegate_to: localhost + register: query_result + +- name: Remove a fabric pod setup policy + cisco.aci.aci_fabric_pod: + host: apic + username: admin + password: SomeSecretPassword + pod_id: 1 + 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: '' +sent: + description: The actual/minimal configuration pushed to the APIC + returned: info + type: list + sample: + { + "fvTenant": { + "attributes": { + "descr": "Production environment" + } + } + } +previous: + description: The original configuration from the APIC before the module has started + returned: info + type: list + sample: + [ + { + "fvTenant": { + "attributes": { + "descr": "Production", + "dn": "uni/tn-production", + "name": "production", + "nameAlias": "", + "ownerKey": "", + "ownerTag": "" + } + } + } + ] +proposed: + description: The assembled configuration from the user-provided parameters + returned: info + type: dict + sample: + { + "fvTenant": { + "attributes": { + "descr": "Production environment", + "name": "production" + } + } + } +filter_string: + description: The filter string used for the request + returned: failure or debug + type: str + sample: ?rsp-prop-include=config-only +method: + description: The HTTP method used for the request to the APIC + returned: failure or debug + type: str + sample: POST +response: + description: The HTTP response from the APIC + returned: failure or debug + type: str + sample: OK (30 bytes) +status: + description: The HTTP status from the APIC + returned: failure or debug + type: int + sample: 200 +url: + description: The HTTP url used for the request to the APIC + returned: failure or debug + type: str + sample: https://10.11.12.13/api/mo/uni/tn-production.json +""" + +from ansible.module_utils.basic import AnsibleModule +from ansible_collections.cisco.aci.plugins.module_utils.aci import ( + ACIModule, + aci_argument_spec, + aci_annotation_spec, + aci_owner_spec, +) + + +def main(): + argument_spec = aci_argument_spec() + argument_spec.update(aci_annotation_spec()) + argument_spec.update(aci_owner_spec()) + argument_spec.update( + description=dict(type="str", aliases=["descr"]), + state=dict(type="str", default="present", choices=["absent", "present", "query"]), + name_alias=dict(type="str"), + pod_id=dict(type="int", aliases=["pod", "id"]), + pod_type=dict(type="str", choices=["physical", "virtual"], aliases=["type"]), + tep_pool=dict(type="str", aliases=["tep", "pool"]), + ) + + module = AnsibleModule( + argument_spec=argument_spec, + supports_check_mode=True, + required_if=[ + ["state", "absent", ["pod_id"]], + ["state", "present", ["pod_id"]], + ], + ) + + aci = ACIModule(module) + + name_alias = module.params.get("name_alias") + pod_id = module.params.get("pod_id") + pod_type = module.params.get("pod_type") + tep_pool = module.params.get("tep_pool") + description = module.params.get("description") + state = module.params.get("state") + + if pod_id is not None and int(pod_id) not in range(1, 254): + aci.fail_json(msg="Pod ID: {0} is invalid; it must be in the range of 1 to 254.".format(pod_id)) + + aci.construct_url( + root_class=dict( + aci_class="fabricSetupP", + aci_rn="controller/setuppol/setupp-{0}".format(pod_id), + module_object=pod_id, + target_filter={"podId": pod_id}, + ), + child_classes=["fabricExtRoutablePodSubnet", "fabricExtSetupP"], + ) + + aci.get_existing() + + if state == "present": + aci.payload( + aci_class="fabricSetupP", + class_config=dict( + podId=pod_id, + podType=pod_type, + tepPool=tep_pool, + descr=description, + nameAlias=name_alias, + ), + ) + + aci.get_diff(aci_class="fabricSetupP") + + aci.post_config() + + elif state == "absent": + aci.delete_config() + + aci.exit_json() + + +if __name__ == "__main__": + main() diff --git a/ansible_collections/cisco/aci/plugins/modules/aci_fabric_pod_connectivity_profile.py b/ansible_collections/cisco/aci/plugins/modules/aci_fabric_pod_connectivity_profile.py new file mode 100644 index 000000000..ed601a358 --- /dev/null +++ b/ansible_collections/cisco/aci/plugins/modules/aci_fabric_pod_connectivity_profile.py @@ -0,0 +1,336 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- +# Copyright: (c) 2024, Samita Bhattacharjee (@samitab) + +# 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_pod_connectivity_profile +short_description: Manage Fabric External Pod Connectivity Profiles (fv:PodConnP) +description: +- Manage Fabric External Pod Connectivity Profiles on Cisco ACI fabrics. +options: + pod_id: + description: + - The Pod ID associated with the Pod Connectivity Profile. + type: int + aliases: [ pod, pid ] + fabric_id: + description: + - The Fabric ID associated with the Pod Connectivity Profile. + type: int + aliases: [ fabric, fid ] + virtual_pod_id: + description: + - The Pod ID in the main fabric to which this I(pod_id) is associated. This property is valid only if this pod is a virtual pod. + type: int + aliases: [ vpod, vpod_id ] + description: + description: + - The description of the Pod Connectivity Profile. + type: str + aliases: [ descr ] + data_plane_tep: + description: + - The Data Plane TEP IPv4 address and prefix. + - eg. 10.1.1.1/32 + type: str + aliases: [ dp_tep ] + unicast_tep: + description: + - The Unicast TEP IPv4 address and prefix. + - eg. 10.1.1.2/32 + type: str + aliases: [ u_tep ] + state: + description: + - Use C(present) or C(absent) for adding or removing. + - Use C(query) for listing an object or multiple objects. + type: str + choices: [ absent, present, query ] + default: present +extends_documentation_fragment: +- cisco.aci.aci +- cisco.aci.annotation +- cisco.aci.owner + +notes: +- This module requires an existing I(fabric_external_connection_profile). + The module M(cisco.aci.aci_fabric_external_connection_profile) can be used for this. +seealso: +- module: cisco.aci.aci_fabric_external_connection_profile +- name: APIC Management Information Model reference + description: More information about the internal APIC class B(fv:PodConnP). + link: https://developer.cisco.com/docs/apic-mim-ref/ +author: +- Samita Bhattacharjee (@samitab) +""" + +EXAMPLES = r""" +- name: Add a Pod Connectivity Profile + cisco.aci.aci_fabric_pod_connectivity_profile: + host: apic + username: admin + password: SomeSecretPassword + fabric_id: 1 + pod_id: 1 + description: First pod connectivity profile + data_plane_tep: 10.1.1.1/32 + unicast_tep: 10.1.1.2/32 + state: present + delegate_to: localhost + +- name: Query a Pod Connectivity Profile + cisco.aci.aci_fabric_pod_connectivity_profile: + host: apic + username: admin + password: SomeSecretPassword + fabric_id: 1 + pod_id: 1 + state: query + delegate_to: localhost + register: query_result + +- name: Query all Pod Connectivity Profiles + cisco.aci.aci_fabric_pod_connectivity_profile: + host: apic + username: admin + password: SomeSecretPassword + state: query + delegate_to: localhost + register: query_result + +- name: Remove a Pod Connectivity Profile + cisco.aci.aci_fabric_pod_connectivity_profile: + host: apic + username: admin + password: SomeSecretPassword + fabric_id: 1 + pod_id: 1 + 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: '' +sent: + description: The actual/minimal configuration pushed to the APIC + returned: info + type: list + sample: + { + "fvTenant": { + "attributes": { + "descr": "Production environment" + } + } + } +previous: + description: The original configuration from the APIC before the module has started + returned: info + type: list + sample: + [ + { + "fvTenant": { + "attributes": { + "descr": "Production", + "dn": "uni/tn-production", + "name": "production", + "nameAlias": "", + "ownerKey": "", + "ownerTag": "" + } + } + } + ] +proposed: + description: The assembled configuration from the user-provided parameters + returned: info + type: dict + sample: + { + "fvTenant": { + "attributes": { + "descr": "Production environment", + "name": "production" + } + } + } +filter_string: + description: The filter string used for the request + returned: failure or debug + type: str + sample: ?rsp-prop-include=config-only +method: + description: The HTTP method used for the request to the APIC + returned: failure or debug + type: str + sample: POST +response: + description: The HTTP response from the APIC + returned: failure or debug + type: str + sample: OK (30 bytes) +status: + description: The HTTP status from the APIC + returned: failure or debug + type: int + sample: 200 +url: + description: The HTTP url used for the request to the APIC + returned: failure or debug + type: str + sample: https://10.11.12.13/api/mo/uni/tn-production.json +""" + +from ansible.module_utils.basic import AnsibleModule +from ansible_collections.cisco.aci.plugins.module_utils.aci import ACIModule, aci_argument_spec, aci_annotation_spec, aci_owner_spec + + +def main(): + argument_spec = aci_argument_spec() + argument_spec.update(aci_annotation_spec()) + argument_spec.update(aci_owner_spec()) + argument_spec.update( + pod_id=dict(type="int", aliases=["pod", "pid"]), + fabric_id=dict(type="int", aliases=["fabric", "fid"]), + virtual_pod_id=dict(type="int", aliases=["vpod", "vpod_id"]), + description=dict(type="str", aliases=["descr"]), + data_plane_tep=dict(type="str", aliases=["dp_tep"]), + unicast_tep=dict(type="str", aliases=["u_tep"]), + state=dict(type="str", default="present", choices=["absent", "present", "query"]), + ) + + module = AnsibleModule( + argument_spec=argument_spec, + supports_check_mode=True, + required_if=[ + ["state", "absent", ["fabric_id", "pod_id"]], + ["state", "present", ["fabric_id", "pod_id"]], + ], + ) + + aci = ACIModule(module) + + pod_id = module.params.get("pod_id") + fabric_id = module.params.get("fabric_id") + virtual_pod_id = module.params.get("virtual_pod_id") + description = module.params.get("description") + data_plane_tep = module.params.get("data_plane_tep") + unicast_tep = module.params.get("unicast_tep") + state = module.params.get("state") + + aci.construct_url( + root_class=dict( + aci_class="fvFabricExtConnP", + aci_rn="tn-infra/fabricExtConnP-{0}".format(fabric_id), + module_object=fabric_id, + target_filter={"id": fabric_id}, + ), + subclass_1=dict( + aci_class="fvPodConnP", + aci_rn="podConnP-{0}".format(pod_id), + module_object=pod_id, + target_filter={"id": pod_id}, + ), + child_classes=["fvIp", "fvExtRoutableUcastConnP"], + ) + + aci.get_existing() + + if state == "present": + child_configs = [] + + # Validate if existing and remove child objects when the config does not match the provided config. + if isinstance(aci.existing, list) and len(aci.existing) > 0: + for child in aci.existing[0].get("fvPodConnP", {}).get("children", {}): + if child.get("fvExtRoutableUcastConnP") and child.get("fvExtRoutableUcastConnP").get("attributes").get("addr") != unicast_tep: + child_configs.append( + { + "fvExtRoutableUcastConnP": { + "attributes": { + "addr": child.get("fvExtRoutableUcastConnP").get("attributes").get("addr"), + "status": "deleted", + } + } + } + ) + if child.get("fvIp") and child.get("fvIp").get("attributes").get("addr") != data_plane_tep: + child_configs.append( + { + "fvIp": { + "attributes": { + "addr": child.get("fvIp").get("attributes").get("addr"), + "status": "deleted", + } + } + } + ) + + if unicast_tep is not None: + child_configs.append({"fvExtRoutableUcastConnP": {"attributes": {"addr": unicast_tep}}}) + if data_plane_tep is not None: + child_configs.append({"fvIp": {"attributes": {"addr": data_plane_tep}}}) + + aci.payload( + aci_class="fvPodConnP", + class_config=dict( + id=pod_id, + assocIntersitePodId=virtual_pod_id, + descr=description, + ), + child_configs=child_configs, + ) + + aci.get_diff(aci_class="fvPodConnP") + + aci.post_config() + + elif state == "absent": + aci.delete_config() + + aci.exit_json() + + +if __name__ == "__main__": + main() diff --git a/ansible_collections/cisco/aci/plugins/modules/aci_fabric_pod_external_tep.py b/ansible_collections/cisco/aci/plugins/modules/aci_fabric_pod_external_tep.py new file mode 100644 index 000000000..511a5aa93 --- /dev/null +++ b/ansible_collections/cisco/aci/plugins/modules/aci_fabric_pod_external_tep.py @@ -0,0 +1,321 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- + +# Copyright: (c) 2023, Samita Bhattacharjee (@samitab) +# 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_pod_external_tep +short_description: Manage Fabric Pod External TEP (fabric:ExtRoutablePodSubnet) +description: +- Manage Fabric Pod External TEP Subnets. +options: + pod_id: + description: + - The Pod ID for the External TEP. + type: int + aliases: [ pod ] + description: + description: + - The description for the External TEP. + type: str + aliases: [ descr ] + name_alias: + description: + - The alias for the current object. This relates to the nameAlias field in ACI. + type: str + external_tep_pool: + description: + - The subnet IP address pool for the External TEP. + - Must be valid IPv4 and include the subnet mask. + - Example 192.168.1.0/24 + type: str + aliases: [ ip, ip_address, tep_pool, pool ] + reserve_address_count: + description: + - Indicates the number of IP addresses that are reserved from the start of the subnet. + type: int + aliases: [ address_count ] + status: + description: + - State of the External TEP C(active) or C(inactive). + - An External TEP can only be deleted when the state is inactive. + - The APIC defaults to C(active) when unset during creation. + type: str + choices: [ active, inactive ] + state: + description: + - Use C(present) or C(absent) for adding or removing. + - Use C(query) for listing an object or multiple objects. + type: str + choices: [ absent, present, query ] + default: present +extends_documentation_fragment: +- cisco.aci.aci +- cisco.aci.annotation +- cisco.aci.owner + +notes: +- The C(Fabric Pod Setup Policy) must exist before using this module in your playbook. + The M(cisco.aci.aci_fabric_pod) module can be used for this. +seealso: +- name: APIC Management Information Model reference + description: More information about the internal APIC class B(fabric:ExtRoutablePodSubnet). + link: https://developer.cisco.com/docs/apic-mim-ref/ +author: +- Samita Bhattacharjee (@samitab) +""" + +EXAMPLES = r""" +- name: Add an External TEP to a fabric pod setup policy + cisco.aci.aci_fabric_pod_external_tep: + host: apic + username: admin + password: SomeSecretPassword + pod_id: 2 + external_tep_pool: 10.6.1.0/24 + reserve_address_count: 5 + status: active + state: present + delegate_to: localhost + +- name: Change an External TEP state on a fabric pod setup policy to inactive + cisco.aci.aci_fabric_pod_external_tep: + host: apic + username: admin + password: SomeSecretPassword + pod_id: 2 + external_tep_pool: 10.6.1.0/24 + status: inactive + state: present + delegate_to: localhost + +- name: Query the External TEP on a fabric pod setup policy + cisco.aci.aci_fabric_pod_external_tep: + host: apic + username: admin + password: SomeSecretPassword + pod_id: 2 + external_tep_pool: 10.6.1.0/24 + state: query + delegate_to: localhost + register: query_result + +- name: Query External TEPs on all fabric pod setup policies + cisco.aci.aci_fabric_pod_external_tep: + host: apic + username: admin + password: SomeSecretPassword + state: query + delegate_to: localhost + register: query_result + +- name: Delete an External TEP on a fabric pod setup policy + cisco.aci.aci_fabric_pod_external_tep: + host: apic + username: admin + password: SomeSecretPassword + pod_id: 2 + external_tep_pool: 10.6.1.0/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: '' +sent: + description: The actual/minimal configuration pushed to the APIC + returned: info + type: list + sample: + { + "fvTenant": { + "attributes": { + "descr": "Production environment" + } + } + } +previous: + description: The original configuration from the APIC before the module has started + returned: info + type: list + sample: + [ + { + "fvTenant": { + "attributes": { + "descr": "Production", + "dn": "uni/tn-production", + "name": "production", + "nameAlias": "", + "ownerKey": "", + "ownerTag": "" + } + } + } + ] +proposed: + description: The assembled configuration from the user-provided parameters + returned: info + type: dict + sample: + { + "fvTenant": { + "attributes": { + "descr": "Production environment", + "name": "production" + } + } + } +filter_string: + description: The filter string used for the request + returned: failure or debug + type: str + sample: ?rsp-prop-include=config-only +method: + description: The HTTP method used for the request to the APIC + returned: failure or debug + type: str + sample: POST +response: + description: The HTTP response from the APIC + returned: failure or debug + type: str + sample: OK (30 bytes) +status: + description: The HTTP status from the APIC + returned: failure or debug + type: int + sample: 200 +url: + description: The HTTP url used for the request to the APIC + returned: failure or debug + type: str + sample: https://10.11.12.13/api/mo/uni/tn-production.json +""" + +from ansible.module_utils.basic import AnsibleModule +from ansible_collections.cisco.aci.plugins.module_utils.aci import ( + ACIModule, + aci_argument_spec, + aci_annotation_spec, + aci_owner_spec, +) + + +def main(): + argument_spec = aci_argument_spec() + argument_spec.update(aci_annotation_spec()) + argument_spec.update(aci_owner_spec()) + argument_spec.update( + description=dict(type="str", aliases=["descr"]), + name_alias=dict(type="str"), + pod_id=dict(type="int", aliases=["pod"]), + external_tep_pool=dict(type="str", aliases=["ip", "ip_address", "tep_pool", "pool"]), + reserve_address_count=dict(type="int", aliases=["address_count"]), + status=dict(type="str", choices=["active", "inactive"]), + state=dict(type="str", default="present", choices=["absent", "present", "query"]), + ) + + module = AnsibleModule( + argument_spec=argument_spec, + supports_check_mode=True, + required_if=[ + ["state", "absent", ["pod_id", "external_tep_pool"]], + ["state", "present", ["pod_id", "external_tep_pool"]], + ], + ) + + aci = ACIModule(module) + + pod_id = module.params.get("pod_id") + descr = module.params.get("descr") + name_alias = module.params.get("name_alias") + external_tep_pool = module.params.get("external_tep_pool") + reserve_address_count = module.params.get("reserve_address_count") + status = module.params.get("status") + state = module.params.get("state") + + if pod_id is not None and int(pod_id) not in range(1, 254): + aci.fail_json(msg="Pod ID: {0} is invalid; it must be in the range of 1 to 254.".format(pod_id)) + + aci.construct_url( + root_class=dict( + aci_class="fabricSetupP", + aci_rn="controller/setuppol/setupp-{0}".format(pod_id), + module_object=pod_id, + target_filter={"podId": pod_id}, + ), + subclass_1=dict( + aci_class="fabricExtRoutablePodSubnet", + aci_rn="extrtpodsubnet-[{0}]".format(external_tep_pool), + module_object=external_tep_pool, + target_filter={"pool": external_tep_pool}, + ), + ) + + aci.get_existing() + + if state == "present": + aci.payload( + aci_class="fabricExtRoutablePodSubnet", + class_config=dict( + descr=descr, + nameAlias=name_alias, + pool=external_tep_pool, + reserveAddressCount=reserve_address_count, + state=status, + ), + ) + + aci.get_diff(aci_class="fabricExtRoutablePodSubnet") + + aci.post_config() + + elif state == "absent": + aci.delete_config() + + aci.exit_json() + + +if __name__ == "__main__": + main() diff --git a/ansible_collections/cisco/aci/plugins/modules/aci_fabric_pod_profile.py b/ansible_collections/cisco/aci/plugins/modules/aci_fabric_pod_profile.py new file mode 100644 index 000000000..e77114848 --- /dev/null +++ b/ansible_collections/cisco/aci/plugins/modules/aci_fabric_pod_profile.py @@ -0,0 +1,267 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- + +# Copyright: (c) 2023, Samita Bhattacharjee (@samitab) +# 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_pod_profile +short_description: Manage Fabric Pod Profile (fabric:PodP) +description: +- Manage Fabric Pod Profile on Cisco ACI fabrics. +options: + name: + description: + - The name of the Pod Profile. + type: str + aliases: [ profile, pod_profile ] + description: + description: + - The description for the Fabric Pod 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 +- cisco.aci.annotation +- cisco.aci.owner + +seealso: +- name: APIC Management Information Model reference + description: More information about the internal APIC class B(fabric:PodP). + link: https://developer.cisco.com/docs/apic-mim-ref/ +author: +- Samita Bhattacharjee (@samitab) +""" + +EXAMPLES = r""" +- name: Add a new pod profile + cisco.aci.aci_fabric_pod_profile: + host: apic + username: admin + password: SomeSecretPassword + name: ans_pod_profile + state: present + delegate_to: localhost + +- name: Query a pod profile + cisco.aci.aci_fabric_pod_profile: + host: apic + username: admin + password: SomeSecretPassword + name: ans_pod_profile + state: query + delegate_to: localhost + register: query_result + +- name: Query all pod profiles + cisco.aci.aci_fabric_pod_profile: + host: apic + username: admin + password: SomeSecretPassword + state: query + delegate_to: localhost + register: query_result + +- name: Remove a pod profile + cisco.aci.aci_fabric_pod_profile: + host: apic + username: admin + password: SomeSecretPassword + name: ans_pod_profile + 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: '' +sent: + description: The actual/minimal configuration pushed to the APIC + returned: info + type: list + sample: + { + "fvTenant": { + "attributes": { + "descr": "Production environment" + } + } + } +previous: + description: The original configuration from the APIC before the module has started + returned: info + type: list + sample: + [ + { + "fvTenant": { + "attributes": { + "descr": "Production", + "dn": "uni/tn-production", + "name": "production", + "nameAlias": "", + "ownerKey": "", + "ownerTag": "" + } + } + } + ] +proposed: + description: The assembled configuration from the user-provided parameters + returned: info + type: dict + sample: + { + "fvTenant": { + "attributes": { + "descr": "Production environment", + "name": "production" + } + } + } +filter_string: + description: The filter string used for the request + returned: failure or debug + type: str + sample: ?rsp-prop-include=config-only +method: + description: The HTTP method used for the request to the APIC + returned: failure or debug + type: str + sample: POST +response: + description: The HTTP response from the APIC + returned: failure or debug + type: str + sample: OK (30 bytes) +status: + description: The HTTP status from the APIC + returned: failure or debug + type: int + sample: 200 +url: + description: The HTTP url used for the request to the APIC + returned: failure or debug + type: str + sample: https://10.11.12.13/api/mo/uni/tn-production.json +""" + +from ansible.module_utils.basic import AnsibleModule +from ansible_collections.cisco.aci.plugins.module_utils.aci import ( + ACIModule, + aci_argument_spec, + aci_annotation_spec, + aci_owner_spec, +) + + +def main(): + argument_spec = aci_argument_spec() + argument_spec.update(aci_annotation_spec()) + argument_spec.update(aci_owner_spec()) + argument_spec.update( + description=dict(type="str", aliases=["descr"]), + state=dict(type="str", default="present", choices=["absent", "present", "query"]), + name_alias=dict(type="str"), + name=dict(type="str", aliases=["profile", "pod_profile"]), + ) + + module = AnsibleModule( + argument_spec=argument_spec, + supports_check_mode=True, + required_if=[ + ["state", "absent", ["name"]], + ["state", "present", ["name"]], + ], + ) + + aci = ACIModule(module) + + name_alias = module.params.get("name_alias") + name = module.params.get("name") + description = module.params.get("description") + state = module.params.get("state") + + aci.construct_url( + root_class=dict( + aci_class="fabricPodP", + aci_rn="fabric/podprof-{0}".format(name), + module_object=name, + target_filter={"name": name}, + ), + child_classes=["fabricPodS"], + ) + + aci.get_existing() + + if state == "present": + aci.payload( + aci_class="fabricPodP", + class_config=dict( + name=name, + descr=description, + nameAlias=name_alias, + ), + ) + + aci.get_diff(aci_class="fabricPodP") + + aci.post_config() + + elif state == "absent": + aci.delete_config() + + aci.exit_json() + + +if __name__ == "__main__": + main() diff --git a/ansible_collections/cisco/aci/plugins/modules/aci_fabric_pod_remote_pool.py b/ansible_collections/cisco/aci/plugins/modules/aci_fabric_pod_remote_pool.py new file mode 100644 index 000000000..189a0273d --- /dev/null +++ b/ansible_collections/cisco/aci/plugins/modules/aci_fabric_pod_remote_pool.py @@ -0,0 +1,294 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- + +# Copyright: (c) 2023, Samita Bhattacharjee (@samitab) +# 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_pod_remote_pool +short_description: Manage Fabric Pod Remote Pool (fabric:ExtSetupP) +description: +- Manage Remote Pools on Fabric Pod Subnets. +options: + pod_id: + description: + - The Pod ID for the Remote Pool. + type: int + aliases: [ pod ] + description: + description: + - The description for the Remote Pool. + type: str + aliases: [desc] + remote_id: + description: + - The Identifier for the Remote Pool. + type: int + aliases: [ id ] + name_alias: + description: + - The alias for the current object. This relates to the nameAlias field in ACI. + type: str + remote_pool: + description: + - The subnet IP address pool for the Remote Pool. + - Must be valid IPv4 and include the subnet mask. + - Example 192.168.1.0/24 + type: str + aliases: [ pool ] + state: + description: + - Use C(present) or C(absent) for adding or removing. + - Use C(query) for listing an object or multiple objects. + type: str + choices: [ absent, present, query ] + default: present +extends_documentation_fragment: +- cisco.aci.aci +- cisco.aci.annotation +- cisco.aci.owner + +notes: +- The C(Fabric Pod Setup Policy) must exist before using this module in your playbook. + The M(cisco.aci.aci_fabric_pod) module can be used for this. +seealso: +- name: APIC Management Information Model reference + description: More information about the internal APIC class B(fabric:ExtSetupP). + link: https://developer.cisco.com/docs/apic-mim-ref/ +author: +- Samita Bhattacharjee (@samitab) +""" + +EXAMPLES = r""" +- name: Add a Remote Pool to a fabric pod setup policy + cisco.aci.aci_fabric_pod_remote_pool: + host: apic + username: admin + password: SomeSecretPassword + pod_id: 2 + remote_id: 1 + remote_pool: 10.6.2.0/24 + state: present + delegate_to: localhost + +- name: Query the Remote Pool on a fabric pod setup policy + cisco.aci.aci_fabric_pod_remote_pool: + host: apic + username: admin + password: SomeSecretPassword + pod_id: 2 + remote_id: 1 + state: query + delegate_to: localhost + register: query_result + +- name: Query Remote Pools on all fabric pod setup policies + cisco.aci.aci_fabric_pod_remote_pool: + host: apic + username: admin + password: SomeSecretPassword + state: query + delegate_to: localhost + register: query_result + +- name: Delete a Remote Pool from a fabric pod setup policy + cisco.aci.aci_fabric_pod_external_tep: + host: apic + username: admin + password: SomeSecretPassword + pod_id: 2 + remote_id: 1 + 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: '' +sent: + description: The actual/minimal configuration pushed to the APIC + returned: info + type: list + sample: + { + "fvTenant": { + "attributes": { + "descr": "Production environment" + } + } + } +previous: + description: The original configuration from the APIC before the module has started + returned: info + type: list + sample: + [ + { + "fvTenant": { + "attributes": { + "descr": "Production", + "dn": "uni/tn-production", + "name": "production", + "nameAlias": "", + "ownerKey": "", + "ownerTag": "" + } + } + } + ] +proposed: + description: The assembled configuration from the user-provided parameters + returned: info + type: dict + sample: + { + "fvTenant": { + "attributes": { + "descr": "Production environment", + "name": "production" + } + } + } +filter_string: + description: The filter string used for the request + returned: failure or debug + type: str + sample: ?rsp-prop-include=config-only +method: + description: The HTTP method used for the request to the APIC + returned: failure or debug + type: str + sample: POST +response: + description: The HTTP response from the APIC + returned: failure or debug + type: str + sample: OK (30 bytes) +status: + description: The HTTP status from the APIC + returned: failure or debug + type: int + sample: 200 +url: + description: The HTTP url used for the request to the APIC + returned: failure or debug + type: str + sample: https://10.11.12.13/api/mo/uni/tn-production.json +""" + +from ansible.module_utils.basic import AnsibleModule +from ansible_collections.cisco.aci.plugins.module_utils.aci import ACIModule, aci_argument_spec, aci_annotation_spec, aci_owner_spec + + +def main(): + argument_spec = aci_argument_spec() + argument_spec.update(aci_annotation_spec()) + argument_spec.update(aci_owner_spec()) + argument_spec.update( + pod_id=dict(type="int", aliases=["pod"]), + description=dict(type="str", aliases=["desc"]), + remote_id=dict(type="int", aliases=["id"]), + name_alias=dict(type="str"), + remote_pool=dict(type="str", aliases=["pool"]), + state=dict(type="str", default="present", choices=["absent", "present", "query"]), + ) + + module = AnsibleModule( + argument_spec=argument_spec, + supports_check_mode=True, + required_if=[ + ["state", "absent", ["pod_id", "remote_id"]], + ["state", "present", ["pod_id", "remote_id"]], + ], + ) + + aci = ACIModule(module) + + pod_id = module.params.get("pod_id") + description = module.params.get("description") + remote_id = module.params.get("remote_id") + name_alias = module.params.get("name_alias") + remote_pool = module.params.get("remote_pool") + state = module.params.get("state") + + if pod_id is not None and int(pod_id) not in range(1, 254): + aci.fail_json(msg="Pod ID: {0} is invalid; it must be in the range of 1 to 254.".format(pod_id)) + + aci.construct_url( + root_class=dict( + aci_class="fabricSetupP", + aci_rn="controller/setuppol/setupp-{0}".format(pod_id), + module_object=pod_id, + target_filter={"podId": pod_id}, + ), + subclass_1=dict( + aci_class="fabricExtSetupP", + aci_rn="extsetupp-{0}".format(remote_id), + module_object=remote_id, + target_filter={"extPoolId": remote_id}, + ), + ) + + aci.get_existing() + + if state == "present": + aci.payload( + aci_class="fabricExtSetupP", + class_config=dict( + descr=description, + extPoolId=remote_id, + nameAlias=name_alias, + tepPool=remote_pool, + ), + ) + + aci.get_diff(aci_class="fabricExtSetupP") + + aci.post_config() + + elif state == "absent": + aci.delete_config() + + aci.exit_json() + + +if __name__ == "__main__": + main() diff --git a/ansible_collections/cisco/aci/plugins/modules/aci_fabric_pod_selector.py b/ansible_collections/cisco/aci/plugins/modules/aci_fabric_pod_selector.py index 6c95f32df..28d95eae0 100644 --- a/ansible_collections/cisco/aci/plugins/modules/aci_fabric_pod_selector.py +++ b/ansible_collections/cisco/aci/plugins/modules/aci_fabric_pod_selector.py @@ -67,6 +67,7 @@ extends_documentation_fragment: notes: - The C(pod_profile) must exist before using this module in your playbook. +- The M(cisco.aci.aci_fabric_pod_profile) module can be used to create the C(pod_profile). seealso: - name: APIC Management Information Model reference description: More information about the internal APIC class B(fabric:PodS). @@ -76,9 +77,6 @@ author: - Akini Ross (@akinross) """ -# TODO add to notes section when cisco.aci.aci_pod_profile is implemented: -# The M(cisco.aci.aci_pod_profile) module can be used for this. - EXAMPLES = r""" - name: Add a new pod selector with type all cisco.aci.aci_fabric_pod_selector: diff --git a/ansible_collections/cisco/aci/plugins/modules/aci_fabric_spine_profile.py b/ansible_collections/cisco/aci/plugins/modules/aci_fabric_spine_profile.py index 364b613ff..af80ee415 100644 --- a/ansible_collections/cisco/aci/plugins/modules/aci_fabric_spine_profile.py +++ b/ansible_collections/cisco/aci/plugins/modules/aci_fabric_spine_profile.py @@ -12,7 +12,7 @@ ANSIBLE_METADATA = {"metadata_version": "1.1", "status": ["preview"], "supported DOCUMENTATION = r""" --- module: aci_fabric_spine_profile -short_description: Manage fabric spine profiles (fabric:SpineP). +short_description: Manage fabric spine profiles (fabric:SpineP) description: - Manage fabric spine switch profiles in an ACI fabric. options: diff --git a/ansible_collections/cisco/aci/plugins/modules/aci_fabric_spine_switch_assoc.py b/ansible_collections/cisco/aci/plugins/modules/aci_fabric_spine_switch_assoc.py index ce0a00ce8..5884cd1e1 100644 --- a/ansible_collections/cisco/aci/plugins/modules/aci_fabric_spine_switch_assoc.py +++ b/ansible_collections/cisco/aci/plugins/modules/aci_fabric_spine_switch_assoc.py @@ -12,7 +12,7 @@ ANSIBLE_METADATA = {"metadata_version": "1.1", "status": ["preview"], "supported DOCUMENTATION = r""" --- module: aci_fabric_spine_switch_assoc -short_description: Manage spine switch bindings to profiles and policy groups (fabric:SpineS and fabric:RsSpNodePGrp). +short_description: Manage spine switch bindings to profiles and policy groups (fabric:SpineS and fabric:RsSpNodePGrp) description: - Manage fabric spine switch associations (fabric:SpineS) to an existing fabric spine profile (fabric:SpineP) in an ACI fabric, and bind them to a diff --git a/ansible_collections/cisco/aci/plugins/modules/aci_fabric_switch_block.py b/ansible_collections/cisco/aci/plugins/modules/aci_fabric_switch_block.py index 57bd59874..ded3b56ec 100644 --- a/ansible_collections/cisco/aci/plugins/modules/aci_fabric_switch_block.py +++ b/ansible_collections/cisco/aci/plugins/modules/aci_fabric_switch_block.py @@ -12,7 +12,7 @@ ANSIBLE_METADATA = {"metadata_version": "1.1", "status": ["preview"], "supported DOCUMENTATION = r""" --- module: aci_fabric_switch_block -short_description: Manage switch blocks (fabric:NodeBlk). +short_description: Manage switch blocks (fabric:NodeBlk) description: - Manage fabric node blocks within switch associations (fabric:SpineS and fabric:LeafS) contained within fabric switch profiles (fabric:SpineP and fabric:LeafP) diff --git a/ansible_collections/cisco/aci/plugins/modules/aci_fabric_switch_policy_group.py b/ansible_collections/cisco/aci/plugins/modules/aci_fabric_switch_policy_group.py index 1d766a34e..a3ba0a033 100644 --- a/ansible_collections/cisco/aci/plugins/modules/aci_fabric_switch_policy_group.py +++ b/ansible_collections/cisco/aci/plugins/modules/aci_fabric_switch_policy_group.py @@ -13,72 +13,72 @@ ANSIBLE_METADATA = {"metadata_version": "1.1", "status": ["preview"], "supported DOCUMENTATION = r""" --- module: aci_fabric_switch_policy_group -short_description: Manage Fabric Switch Policy Group objects. +short_description: Manage Fabric Switch Policy Group objects (fabric:LeNodePGrp and fabric:SpNodePGrp) description: -- Manage Fabric Switch Policy Group (fabricLeNodePGrp and fabricSpNodePGrp) configuration on Cisco ACI fabrics. +- Manage Fabric Switch Policy Group configuration on Cisco ACI fabrics. options: name: description: - - The name of the Leaf Policy Group. + - The name of the Fabric Switch Policy Group. type: str aliases: [ 'policy_group', 'policy_group_name' ] description: description: - - Description for the Leaf Policy Group. + - Description for the Fabric Switch Policy Group. type: str switch_type: description: - - Whether this is a leaf or spine policy group + - Whether this is a leaf or spine Fabric Switch Policy Group. type: str choices: [ leaf, spine ] required: true monitoring_policy: description: - - Monitoring Policy to attach to this Policy Group + - Monitoring Policy to attach to this Fabric Switch Policy Group. type: str aliases: [ 'monitoring', 'fabricRsMonInstFabricPol' ] tech_support_export_policy: description: - - Tech Support Export Policy to attach to this Policy Group + - Tech Support Export Policy to attach to this Fabric Switch Policy Group. type: str aliases: [ 'tech_support', 'tech_support_export', 'fabricRsNodeTechSupP'] core_export_policy: description: - - Core Export Policy to attach to this Policy Group + - Core Export Policy to attach to this Fabric Switch Policy Group. type: str aliases: [ 'core', 'core_export', 'fabricRsNodeCoreP' ] inventory_policy: description: - - Inventory Policy to attach to this Policy Group + - Inventory Policy to attach to this Fabric Switch Policy Group. type: str aliases: [ 'inventory', 'fabricRsCallhomeInvPol' ] power_redundancy_policy: description: - - Power Redundancy Policy to atttach to this Policy Group + - Power Redundancy Policy to atttach to this Fabric Switch Policy Group. type: str aliases: [ 'power_redundancy', 'fabricRsPsuInstPol' ] twamp_server_policy: description: - - TWAMP Server Policy to attach to this Policy Group + - TWAMP Server Policy to attach to this Fabric Switch Policy Group. type: str aliases: [ 'twamp_server', 'fabricRsTwampServerPol' ] twamp_responder_policy: description: - - TWAMP Responder Policy to attach to this Policy Group + - TWAMP Responder Policy to attach to this Fabric Switch Policy Group. type: str aliases: [ 'twamp_responder', 'fabricRsTwampResponderPol' ] node_control_policy: description: - - Node Control Policy to attach to this Policy Group + - Node Control Policy to attach to this Fabric Switch Policy Group. type: str aliases: [ 'node_control', 'fabricRsNodeCtrl' ] analytics_cluster: description: - - Name of the analytics cluster. Requires analytics_name to be present + - Name of the analytics cluster. Requires analytics_name to be present. type: str analytics_name: description: - - Name of the analytics policy. Requires analytics_cluster to be present + - Name of the analytics policy. Requires analytics_cluster to be present. type: str state: description: @@ -93,7 +93,7 @@ extends_documentation_fragment: seealso: - name: APIC Management Information Model reference - description: More information about the internal APIC classes B(fabricLeNodePGrp and fabricSpNodePGrp). + description: More information about the internal APIC classes B(fabric:LeNodePGrp) and B(fabric:SpNodePGrp). link: https://developer.cisco.com/docs/apic-mim-ref/ author: - Tim Cragg (@timcragg) diff --git a/ansible_collections/cisco/aci/plugins/modules/aci_fabric_wide_settings.py b/ansible_collections/cisco/aci/plugins/modules/aci_fabric_wide_settings.py index 1bc7c28eb..2f8a879a9 100644 --- a/ansible_collections/cisco/aci/plugins/modules/aci_fabric_wide_settings.py +++ b/ansible_collections/cisco/aci/plugins/modules/aci_fabric_wide_settings.py @@ -235,7 +235,7 @@ url: from ansible.module_utils.basic import AnsibleModule from ansible_collections.cisco.aci.plugins.module_utils.aci import ACIModule, aci_argument_spec, aci_annotation_spec, aci_owner_spec -from ansible_collections.cisco.aci.plugins.module_utils.constants import TLS_MAPPING +from ansible_collections.cisco.aci.plugins.module_utils.constants import OPFLEX_TLS_MAPPING def main(): @@ -251,7 +251,7 @@ def main(): leaf_opflex_client_auth=dict(type="bool"), spine_ssl_opflex=dict(type="bool"), leaf_ssl_opflex=dict(type="bool"), - opflex_ssl_versions=dict(type="list", choices=list(TLS_MAPPING.keys()), elements="str"), + opflex_ssl_versions=dict(type="list", choices=list(OPFLEX_TLS_MAPPING.keys()), elements="str"), reallocate_gipo=dict(type="bool"), restrict_infra_vlan_traffic=dict(type="bool"), state=dict(type="str", default="present", choices=["present", "query"]), @@ -300,7 +300,7 @@ def main(): restrictInfraVLANTraffic=restrict_infra_vlan_traffic, ) if opflex_ssl_versions is not None: - class_config["opflexpSslProtocols"] = ",".join([TLS_MAPPING.get(tls) for tls in sorted(opflex_ssl_versions)]) + class_config["opflexpSslProtocols"] = ",".join([OPFLEX_TLS_MAPPING.get(tls) for tls in sorted(opflex_ssl_versions)]) aci.payload( aci_class="infraSetPol", diff --git a/ansible_collections/cisco/aci/plugins/modules/aci_igmp_interface_policy.py b/ansible_collections/cisco/aci/plugins/modules/aci_igmp_interface_policy.py index 7f537871a..78369df89 100644 --- a/ansible_collections/cisco/aci/plugins/modules/aci_igmp_interface_policy.py +++ b/ansible_collections/cisco/aci/plugins/modules/aci_igmp_interface_policy.py @@ -294,8 +294,8 @@ def main(): argument_spec=argument_spec, supports_check_mode=True, required_if=[ - ["state", "present", ["name"]], - ["state", "absent", ["name"]], + ["state", "present", ["name", "tenant"]], + ["state", "absent", ["name", "tenant"]], ], required_together=[ ["allow_v3_asm", "fast_leave", "report_link_local_groups"], diff --git a/ansible_collections/cisco/aci/plugins/modules/aci_interface_blacklist.py b/ansible_collections/cisco/aci/plugins/modules/aci_interface_blacklist.py index 61d5ef44d..aeba32988 100644 --- a/ansible_collections/cisco/aci/plugins/modules/aci_interface_blacklist.py +++ b/ansible_collections/cisco/aci/plugins/modules/aci_interface_blacklist.py @@ -12,7 +12,7 @@ ANSIBLE_METADATA = {"metadata_version": "1.1", "status": ["preview"], "supported DOCUMENTATION = r""" --- module: aci_interface_blacklist -short_description: Enabling or Disabling physical interfaces. +short_description: Enabling or Disabling physical interfaces (fabric:RsOosPath) description: - Enables or Disables physical interfaces on Cisco ACI fabrics. options: @@ -49,6 +49,10 @@ extends_documentation_fragment: - cisco.aci.aci - cisco.aci.annotation +seealso: +- name: APIC Management Information Model reference + description: More information about the internal APIC class B(fabric:RsOosPath). + link: https://developer.cisco.com/docs/apic-mim-ref/ author: - Akini Ross (@akinross) """ diff --git a/ansible_collections/cisco/aci/plugins/modules/aci_interface_description.py b/ansible_collections/cisco/aci/plugins/modules/aci_interface_description.py index c4a204c89..387acd54a 100644 --- a/ansible_collections/cisco/aci/plugins/modules/aci_interface_description.py +++ b/ansible_collections/cisco/aci/plugins/modules/aci_interface_description.py @@ -12,7 +12,7 @@ ANSIBLE_METADATA = {"metadata_version": "1.1", "status": ["preview"], "supported DOCUMENTATION = r""" --- module: aci_interface_description -short_description: Setting and removing description on physical interfaces. +short_description: Setting and removing description on physical interfaces (infra:HPathS, infra:RsHPathAtt, infra:SHPathS, and infra:RsSHPathAtt) description: - Setting and removing description on physical interfaces on Cisco ACI fabrics. options: @@ -59,6 +59,10 @@ extends_documentation_fragment: - cisco.aci.annotation - cisco.aci.owner +seealso: +- name: APIC Management Information Model reference + description: More information about the internal APIC classes B(infra:HPathS), B(infra:RsHPathAtt), B(infra:SHPathS), and B(infra:RsSHPathAtt). + link: https://developer.cisco.com/docs/apic-mim-ref/ author: - Akini Ross (@akinross) """ diff --git a/ansible_collections/cisco/aci/plugins/modules/aci_interface_policy_bfd.py b/ansible_collections/cisco/aci/plugins/modules/aci_interface_policy_bfd.py new file mode 100644 index 000000000..ec651f360 --- /dev/null +++ b/ansible_collections/cisco/aci/plugins/modules/aci_interface_policy_bfd.py @@ -0,0 +1,318 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- + +# Copyright: (c) 2023, Anvitha Jain (@anvjain) +# 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_bfd +short_description: Manage BFD Interface policies (bfd:IfPol) +description: +- Manage BFD Interface policy configuration on Cisco ACI fabrics +- Only available in APIC version 5.2 or later +options: + tenant: + description: + - Name of an existing tenant + type: str + name: + description: + - Name of the BFD Interface policy + type: str + aliases: [ bfd_interface_policy ] + description: + description: + - Description of the BFD Interface policy + type: str + admin_state: + description: + - Admin state of the BFD Interface policy + - APIC sets the default value to enabled + type: str + choices: [ enabled, disabled ] + detection_multiplier: + description: + - Detection multiplier of the BFD Interface policy + - APIC sets the default value to 3 + - Allowed range is 1-50 + type: int + min_transmit_interval: + description: + - Minimum transmit (Tx) interval of the BFD Interface policy + - APIC sets the default value to 50 + - Allowed range is 250-999 + type: int + min_receive_interval: + description: + - Minimum receive (Rx) interval of the BFD Interface policy + - APIC sets the default value to 50 + - Allowed range is 250-999 + 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 +- cisco.aci.annotation + +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(bfd:IfPol) + link: https://developer.cisco.com/docs/apic-mim-ref/ +- module: cisco.aci.aci_tenant +author: +- Anvitha Jain (@anvjain) +""" + +EXAMPLES = r""" +- name: Add a new BFD Interface policy + cisco.aci.aci_interface_policy_bfd: + host: apic + username: admin + password: SomeSecretPassword + tenant: ansible_tenant + name: ansible_bfd_interface_policy + description: Ansible BFD Interface Policy + state: present + delegate_to: localhost + +- name: Remove a BFD Interface policy + cisco.aci.aci_interface_policy_bfd: + host: apic + username: admin + password: SomeSecretPassword + tenant: ansible_tenant + name: ansible_bfd_interface_policy + state: absent + delegate_to: localhost + +- name: Query a BFD Interface policy + cisco.aci.aci_interface_policy_bfd: + host: apic + username: admin + password: SomeSecretPassword + tenant: ansible_tenant + name: ansible_bfd_interface_policy + state: query + delegate_to: localhost + +- name: Query all BFD Interface policies in a specific tenant + cisco.aci.aci_interface_policy_bfd: + host: apic + username: admin + password: SomeSecretPassword + tenant: ansible_tenant + 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: '' + sent: + description: The actual/minimal configuration pushed to the APIC + returned: info + type: list + sample: + { + "fvTenant": { + "attributes": { + "descr": "Production environment" + } + } + } + previous: + description: The original configuration from the APIC before the module has started + returned: info + type: list + sample: + [ + { + "fvTenant": { + "attributes": { + "descr": "Production", + "dn": "uni/tn-production", + "name": "production", + "nameAlias": "", + "ownerKey": "", + "ownerTag": "" + } + } + } + ] + proposed: + description: The assembled configuration from the user-provided parameters + returned: info + type: dict + sample: + { + "fvTenant": { + "attributes": { + "descr": "Production environment", + "name": "production" + } + } + } + filter_string: + description: The filter string used for the request + returned: failure or debug + type: str + sample: ?rsp-prop-include=config-only + method: + description: The HTTP method used for the request to the APIC + returned: failure or debug + type: str + sample: POST + response: + description: The HTTP response from the APIC + returned: failure or debug + type: str + sample: OK (30 bytes) + status: + description: The HTTP status from the APIC + returned: failure or debug + type: int + sample: 200 + url: + description: The HTTP url used for the request to the APIC + returned: failure or debug + type: str + sample: https://10.11.12.13/api/mo/uni/tn-production.json + """ + +from ansible.module_utils.basic import AnsibleModule +from ansible_collections.cisco.aci.plugins.module_utils.aci import ACIModule, aci_argument_spec, aci_annotation_spec + + +def main(): + argument_spec = aci_argument_spec() + argument_spec.update(aci_annotation_spec()) + argument_spec.update( + name=dict(type="str", aliases=["bfd_interface_policy"]), + description=dict(type="str"), + admin_state=dict(type="str", choices=["enabled", "disabled"]), + detection_multiplier=dict(type="int"), + min_transmit_interval=dict(type="int"), + min_receive_interval=dict(type="int"), + state=dict(type="str", default="present", choices=["absent", "present", "query"]), + tenant=dict(type="str"), + ) + + module = AnsibleModule( + argument_spec=argument_spec, + supports_check_mode=True, + required_if=[ + ["state", "absent", ["name", "tenant"]], + ["state", "present", ["name", "tenant"]], + ], + ) + + name = module.params.get("name") + description = module.params.get("description") + state = module.params.get("state") + tenant = module.params.get("tenant") + admin_state = module.params.get("admin_state") + detection_multiplier = module.params.get("detection_multiplier") + min_transmit_interval = module.params.get("min_transmit_interval") + min_receive_interval = module.params.get("min_receive_interval") + + 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="bfdIfPol", + aci_rn="bfdIfPol-{0}".format(name), + module_object=name, + target_filter={"name": name}, + ), + ) + + aci.get_existing() + + if state == "present": + class_config = dict( + name=name, + descr=description, + adminSt=admin_state, + ) + + if detection_multiplier and detection_multiplier not in range(1, 50): + module.fail_json(msg='The "detection_multiplier" must be a value between 1 and 50') + else: + class_config["detectMult"] = detection_multiplier + if min_transmit_interval and min_transmit_interval not in range(50, 999): + module.fail_json(msg='The "min_transmit_interval" must be a value between 50 and 999') + else: + class_config["minTxIntvl"] = min_transmit_interval + if min_receive_interval and min_receive_interval not in range(50, 999): + module.fail_json(msg='The "min_receive_interval" must be a value between 50 and 999') + else: + class_config["minRxIntvl"] = min_receive_interval + + aci.payload( + aci_class="bfdIfPol", + class_config=class_config, + ) + + aci.get_diff(aci_class="bfdIfPol") + + aci.post_config() + + elif state == "absent": + aci.delete_config() + + aci.exit_json() + + +if __name__ == "__main__": + main() diff --git a/ansible_collections/cisco/aci/plugins/modules/aci_interface_policy_bfd_multihop.py b/ansible_collections/cisco/aci/plugins/modules/aci_interface_policy_bfd_multihop.py new file mode 100644 index 000000000..31cc9321c --- /dev/null +++ b/ansible_collections/cisco/aci/plugins/modules/aci_interface_policy_bfd_multihop.py @@ -0,0 +1,318 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- + +# Copyright: (c) 2023, Anvitha Jain (@anvjain) +# 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_bfd_multihop +short_description: Manage BFD Multihop Interface policies (bfd:MhIfPol) +description: +- Manage BFD Multihop Interface policy configuration on Cisco ACI fabrics +- Only available in APIC version 5.2 or later +options: + tenant: + description: + - Name of an existing tenant + type: str + name: + description: + - Name of the BFD Multihop Interface policy + type: str + aliases: [ bfd_multihop_interface_policy ] + description: + description: + - Description of the BFD Multihop Interface policy + type: str + admin_state: + description: + - Admin state of the BFD Multihop Interface policy + - APIC sets the default value to enabled. + type: str + choices: [ enabled, disabled ] + detection_multiplier: + description: + - Detection multiplier of the BFD Multihop Interface policy + - APIC sets the default value to 3. + - Allowed range is 1-50. + type: int + min_transmit_interval: + description: + - Minimum transmit (Tx) interval of the BFD Multihop Interface policy + - APIC sets the default value to 250 + - Allowed range is 250-999 + type: int + min_receive_interval: + description: + - Minimum receive (Rx) interval of the BFD Multihop Interface policy + - APIC sets the default value to 250 + - Allowed range is 250-999 + 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 +- cisco.aci.annotation + +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(bfd:MhIfPol) + link: https://developer.cisco.com/docs/apic-mim-ref/ +- module: cisco.aci.aci_tenant +author: +- Anvitha Jain (@anvjain) +""" + +EXAMPLES = r""" +- name: Add a new BFD Multihop Interface policy + cisco.aci.aci_interface_policy_bfd_multihop: + host: apic + username: admin + password: SomeSecretPassword + tenant: ansible_tenant + name: ansible_bfd_multihop_interface_policy + description: Ansible BFD Multihop Interface Policy + state: present + delegate_to: localhost + +- name: Remove a BFD Multihop Interface policy + cisco.aci.aci_interface_policy_bfd_multihop: + host: apic + username: admin + password: SomeSecretPassword + tenant: ansible_tenant + name: ansible_bfd_multihop_interface_policy + state: absent + delegate_to: localhost + +- name: Query a BFD Multihop Interface policy + cisco.aci.aci_interface_policy_bfd_multihop: + host: apic + username: admin + password: SomeSecretPassword + tenant: ansible_tenant + name: ansible_bfd_multihop_interface_policy + state: query + delegate_to: localhost + +- name: Query all BFD Multihop Interface policies in a specific tenant + cisco.aci.aci_interface_policy_bfd_multihop: + host: apic + username: admin + password: SomeSecretPassword + tenant: ansible_tenant + 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: '' + sent: + description: The actual/minimal configuration pushed to the APIC + returned: info + type: list + sample: + { + "fvTenant": { + "attributes": { + "descr": "Production environment" + } + } + } + previous: + description: The original configuration from the APIC before the module has started + returned: info + type: list + sample: + [ + { + "fvTenant": { + "attributes": { + "descr": "Production", + "dn": "uni/tn-production", + "name": "production", + "nameAlias": "", + "ownerKey": "", + "ownerTag": "" + } + } + } + ] + proposed: + description: The assembled configuration from the user-provided parameters + returned: info + type: dict + sample: + { + "fvTenant": { + "attributes": { + "descr": "Production environment", + "name": "production" + } + } + } + filter_string: + description: The filter string used for the request + returned: failure or debug + type: str + sample: ?rsp-prop-include=config-only + method: + description: The HTTP method used for the request to the APIC + returned: failure or debug + type: str + sample: POST + response: + description: The HTTP response from the APIC + returned: failure or debug + type: str + sample: OK (30 bytes) + status: + description: The HTTP status from the APIC + returned: failure or debug + type: int + sample: 200 + url: + description: The HTTP url used for the request to the APIC + returned: failure or debug + type: str + sample: https://10.11.12.13/api/mo/uni/tn-production.json + """ + +from ansible.module_utils.basic import AnsibleModule +from ansible_collections.cisco.aci.plugins.module_utils.aci import ACIModule, aci_argument_spec, aci_annotation_spec + + +def main(): + argument_spec = aci_argument_spec() + argument_spec.update(aci_annotation_spec()) + argument_spec.update( + name=dict(type="str", aliases=["bfd_multihop_interface_policy"]), + description=dict(type="str"), + admin_state=dict(type="str", choices=["enabled", "disabled"]), + detection_multiplier=dict(type="int"), + min_transmit_interval=dict(type="int"), + min_receive_interval=dict(type="int"), + state=dict(type="str", default="present", choices=["absent", "present", "query"]), + tenant=dict(type="str"), + ) + + module = AnsibleModule( + argument_spec=argument_spec, + supports_check_mode=True, + required_if=[ + ["state", "absent", ["name", "tenant"]], + ["state", "present", ["name", "tenant"]], + ], + ) + + name = module.params.get("name") + description = module.params.get("description") + state = module.params.get("state") + tenant = module.params.get("tenant") + admin_state = module.params.get("admin_state") + detection_multiplier = module.params.get("detection_multiplier") + min_transmit_interval = module.params.get("min_transmit_interval") + min_receive_interval = module.params.get("min_receive_interval") + + 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="bfdMhIfPol", + aci_rn="bfdMhIfPol-{0}".format(name), + module_object=name, + target_filter={"name": name}, + ), + ) + + aci.get_existing() + + if state == "present": + class_config = dict( + name=name, + descr=description, + adminSt=admin_state, + ) + + if detection_multiplier and detection_multiplier not in range(1, 50): + module.fail_json(msg='The "detection_multiplier" must be a value between 1 and 50') + else: + class_config["detectMult"] = detection_multiplier + if min_transmit_interval and min_transmit_interval not in range(250, 999): + module.fail_json(msg='The "min_transmit_interval" must be a value between 250 and 999') + else: + class_config["minTxIntvl"] = min_transmit_interval + if min_receive_interval and min_receive_interval not in range(250, 999): + module.fail_json(msg='The "min_receive_interval" must be a value between 250 and 999') + else: + class_config["minRxIntvl"] = min_receive_interval + + aci.payload( + aci_class="bfdMhIfPol", + class_config=class_config, + ) + + aci.get_diff(aci_class="bfdMhIfPol") + + aci.post_config() + + elif state == "absent": + aci.delete_config() + + aci.exit_json() + + +if __name__ == "__main__": + main() diff --git a/ansible_collections/cisco/aci/plugins/modules/aci_interface_policy_eigrp.py b/ansible_collections/cisco/aci/plugins/modules/aci_interface_policy_eigrp.py new file mode 100644 index 000000000..7e0e64d53 --- /dev/null +++ b/ansible_collections/cisco/aci/plugins/modules/aci_interface_policy_eigrp.py @@ -0,0 +1,371 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- + +# Copyright: (c) 2022, Lukas Holub (@lukasholub) +# Copyright: (c) 2023, Gaspard Micol (@gmicol) +# 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_eigrp +short_description: Manage EIGRP interface policies (eigrp:IfPol) +description: +- Manage EIGRP interface policies for Tenants on Cisco ACI fabrics. +options: + tenant: + description: + - The name of an existing Tenant. + type: str + aliases: [ tenant_name ] + eigrp: + description: + - The EIGRP interface policy name. + - Note that you cannot change this name after the object has been created. + type: str + aliases: [ eigrp_interface, name ] + bandwidth: + description: + - The EIGRP bandwidth in kbps, overrides the bandwidth configured on an interface. + - This is used to influence path selection. + - Accepted values range between C(0) and C(2560000000). + - The APIC defaults to C(0) when unset during creation. + type: int + control_state: + description: + - The interface policy control state. + - 'This is a list of one or more of the following controls:' + - C(bfd) -- Enable Bidirectional Forwarding Detection. + - C(nexthop_self) -- Nexthop Self. + - C(split_horizon) -- Split Horizon. + - C(passive) -- The interface does not participate in the EIGRP protocol and + will not establish adjacencies or send routing updates. + - The APIC defaults to C([split_horizon, nexthop_self]) when unset during creation. + type: list + elements: str + choices: [ bfd, nexthop_self, passive, split_horizon ] + delay: + description: + - The EIGRP throughput delay, overrides the delay configured on an interface. + - This is used to influence path selection. + - The APIC defaults to C(0) when unset during creation. + type: int + delay_unit: + description: + - The EIGRP delay units, Wide metrics can use picoseconds accuracy for delay. + - The APIC defaults to C(tens_of_microseconds) when unset during creation. + type: str + choices: [ picoseconds, tens_of_microseconds ] + hello_interval: + description: + - The time interval in seconds between hello packets that EIGRP sends on the interface. + - The smaller the hello interval, the faster topological changes will be detected, but more routing traffic will ensue. + - Accepted values range between C(1) and C(65535). + - The APIC defaults to C(5) when unset during creation. + type: int + hold_interval: + description: + - The time period of time in seconds before declaring that the neighbor is down. + - Accepted values range between C(1) and C(65535). + - The APIC defaults to C(15) when unset during creation. + type: int + description: + description: + - The description of the EIGRP interface 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 +- cisco.aci.annotation +- cisco.aci.owner + +notes: +- The C(tenant) used must exist before using this module in your playbook. +- The M(cisco.aci.aci_tenant) module can be used for this. +seealso: +- module: cisco.aci.aci_tenant +- name: APIC Management Information Model reference + description: More information about the internal APIC class B(eigrp:IfPol). + link: https://developer.cisco.com/docs/apic-mim-ref/ +author: +- Gaspard Micol (@gmicol) +- Lukas Holub (@lukasholub) +""" + +EXAMPLES = r""" +- name: Create an EIGRP interface policy + cisco.aci.aci_interface_policy_eigrp: + host: apic + username: admin + password: SomeSecretPassword + tenant: production + eigrp: eigrp1 + bandwidth: 10000 + control_state: [split-horizon, nh-self] + delay: 10 + delay_unit: tens_of_micro + hello_interval: 5 + hold_interval: 15 + state: present + delegate_to: localhost + +- name: Delete EIGRRP interface policy + cisco.aci.aci_interface_policy_eigrp: + host: apic + username: admin + password: SomeSecretPassword + tenant: production + eigrp: eigrp1 + state: present + delegate_to: localhost + +- name: Query an EIGRRP interface policy + cisco.aci.aci_interface_policy_eigrp: + host: apic + username: admin + password: SomeSecretPassword + tenant: production + eigrp: eigrp1 + state: query + delegate_to: localhost + register: query_result + +- name: Query all EIGRP interface policies in tenant production + cisco.aci.aci_interface_policy_eigrp: + 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: '' +sent: + description: The actual/minimal configuration pushed to the APIC + returned: info + type: list + sample: + { + "fvTenant": { + "attributes": { + "descr": "Production environment" + } + } + } +previous: + description: The original configuration from the APIC before the module has started + returned: info + type: list + sample: + [ + { + "fvTenant": { + "attributes": { + "descr": "Production", + "dn": "uni/tn-production", + "name": "production", + "nameAlias": "", + "ownerKey": "", + "ownerTag": "" + } + } + } + ] +proposed: + description: The assembled configuration from the user-provided parameters + returned: info + type: dict + sample: + { + "fvTenant": { + "attributes": { + "descr": "Production environment", + "name": "production" + } + } + } +filter_string: + description: The filter string used for the request + returned: failure or debug + type: str + sample: ?rsp-prop-include=config-only +method: + description: The HTTP method used for the request to the APIC + returned: failure or debug + type: str + sample: POST +response: + description: The HTTP response from the APIC + returned: failure or debug + type: str + sample: OK (30 bytes) +status: + description: The HTTP status from the APIC + returned: failure or debug + type: int + sample: 200 +url: + description: The HTTP url used for the request to the APIC + returned: failure or debug + type: str + sample: https://10.11.12.13/api/mo/uni/tn-production.json +""" + +from ansible.module_utils.basic import AnsibleModule +from ansible_collections.cisco.aci.plugins.module_utils.aci import ACIModule, aci_argument_spec, aci_annotation_spec, aci_owner_spec +from ansible_collections.cisco.aci.plugins.module_utils.constants import ( + MATCH_EIGRP_INTERFACE_POLICY_DELAY_UNIT_MAPPING, + MATCH_EIGRP_INTERFACE_POLICY_CONTROL_STATE_MAPPING, +) + + +def main(): + argument_spec = aci_argument_spec() + argument_spec.update(aci_annotation_spec()) + argument_spec.update(aci_owner_spec()) + argument_spec.update( + tenant=dict(type="str", aliases=["tenant_name"]), # Not required for querying all objects + eigrp=dict(type="str", aliases=["eigrp_interface", "name"]), # Not required for querying all objects + description=dict(type="str", aliases=["descr"]), + bandwidth=dict(type="int"), + control_state=dict(type="list", elements="str", choices=["bfd", "nexthop_self", "passive", "split_horizon"]), + delay=dict(type="int"), + delay_unit=dict(type="str", choices=["picoseconds", "tens_of_microseconds"]), + hello_interval=dict(type="int"), + hold_interval=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", ["eigrp", "tenant"]], + ["state", "present", ["eigrp", "tenant"]], + ], + ) + + aci = ACIModule(module) + + tenant = module.params.get("tenant") + eigrp = module.params.get("eigrp") + delay = module.params.get("delay") + delay_unit = MATCH_EIGRP_INTERFACE_POLICY_DELAY_UNIT_MAPPING.get(module.params.get("delay_unit")) + description = module.params.get("description") + name_alias = module.params.get("name_alias") + state = module.params.get("state") + + bandwidth = module.params.get("bandwidth") + if bandwidth is not None and bandwidth not in range(2560000001): + module.fail_json(msg="Parameter 'bandwidth' is only valid in range between 0 and 2560000000.") + + 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 65535.") + + hold_interval = module.params.get("hold_interval") + if hold_interval is not None and hold_interval not in range(1, 65536): + module.fail_json(msg="Parameter 'hold_interval' is only valid in range between 1 and 65535.") + + if module.params.get("control_state"): + control_state = ",".join([MATCH_EIGRP_INTERFACE_POLICY_CONTROL_STATE_MAPPING.get(v) for v in module.params.get("control_state")]) + else: + control_state = 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="eigrpIfPol", + aci_rn="eigrpIfPol-{0}".format(eigrp), + module_object=eigrp, + target_filter={"name": eigrp}, + ), + ) + + aci.get_existing() + + if state == "present": + aci.payload( + aci_class="eigrpIfPol", + class_config=dict( + name=eigrp, + descr=description, + bw=bandwidth, + ctrl=control_state, + delay=delay, + delayUnit=delay_unit, + helloIntvl=hello_interval, + holdIntvl=hold_interval, + nameAlias=name_alias, + ), + ) + + aci.get_diff(aci_class="eigrpIfPol") + + aci.post_config() + + elif state == "absent": + aci.delete_config() + + aci.exit_json() + + +if __name__ == "__main__": + main() diff --git a/ansible_collections/cisco/aci/plugins/modules/aci_interface_policy_hsrp.py b/ansible_collections/cisco/aci/plugins/modules/aci_interface_policy_hsrp.py new file mode 100644 index 000000000..c94b5af42 --- /dev/null +++ b/ansible_collections/cisco/aci/plugins/modules/aci_interface_policy_hsrp.py @@ -0,0 +1,310 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- + +# Copyright: (c) 2023, Shreyas Srish (@shrsr) +# 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_hsrp +short_description: Manage HSRP interface policies (hsrp:IfPol) +description: +- Manage HSRP interface policies on Cisco ACI fabrics. +options: + tenant: + description: + - The name of the Tenant the HSRP interface policy should belong to. + type: str + aliases: [ tenant_name ] + hsrp: + description: + - The HSRP interface policy name. + type: str + aliases: [ hsrp_interface, name ] + description: + description: + - The description of the HSRP interface. + type: str + aliases: [ descr ] + controls: + description: + - The interface policy controls. + type: list + elements: str + choices: [ bfd, bia ] + delay: + description: + - The administrative port delay of HSRP interface policy. + - This is only valid in range between 1 and 10000. + type: int + reload_delay: + description: + - The option for reload delay of HSRP interface policy. + - This is only valid in range between 1 and 10000. + 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 +- cisco.aci.annotation +- cisco.aci.owner + +notes: +- The C(tenant) must exist before using this module in your playbook. + The M(cisco.aci.aci_tenant) can be used for this. +seealso: +- module: aci_tenant +- name: APIC Management Information Model reference + description: More information about the internal APIC class B(hsrp:IfPol). + link: https://developer.cisco.com/docs/apic-mim-ref/ +author: +- Shreyas Srish (@shrsr) +""" + +EXAMPLES = r""" +- name: Add a HSRP interface policy + cisco.aci.aci_interface_policy_hsrp: + host: apic + username: admin + password: SomeSecretPassword + tenant: production + hsrp: hsrp1 + controls: bfd + delay: 50 + reload_delay: 100 + state: present + delegate_to: localhost + +- name: Delete a HSRP interface policy + cisco.aci.aci_interface_policy_hsrp: + host: apic + username: admin + password: SomeSecretPassword + tenant: production + hsrp: hsrp1 + state: absent + delegate_to: localhost + +- name: Query a HSRP interface policy + cisco.aci.aci_interface_policy_hsrp: + host: apic + username: admin + password: SomeSecretPassword + tenant: production + hsrp: hsrp1 + state: query + delegate_to: localhost + register: query_result + +- name: Query all HSRP interface policies in tenant production + cisco.aci.aci_interface_policy_hsrp: + 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: '' +sent: + description: The actual/minimal configuration pushed to the APIC + returned: info + type: list + sample: + { + "fvTenant": { + "attributes": { + "descr": "Production environment" + } + } + } +previous: + description: The original configuration from the APIC before the module has started + returned: info + type: list + sample: + [ + { + "fvTenant": { + "attributes": { + "descr": "Production", + "dn": "uni/tn-production", + "name": "production", + "nameAlias": "", + "ownerKey": "", + "ownerTag": "" + } + } + } + ] +proposed: + description: The assembled configuration from the user-provided parameters + returned: info + type: dict + sample: + { + "fvTenant": { + "attributes": { + "descr": "Production environment", + "name": "production" + } + } + } +filter_string: + description: The filter string used for the request + returned: failure or debug + type: str + sample: ?rsp-prop-include=config-only +method: + description: The HTTP method used for the request to the APIC + returned: failure or debug + type: str + sample: POST +response: + description: The HTTP response from the APIC + returned: failure or debug + type: str + sample: OK (30 bytes) +status: + description: The HTTP status from the APIC + returned: failure or debug + type: int + sample: 200 +url: + description: The HTTP url used for the request to the APIC + returned: failure or debug + type: str + sample: https://10.11.12.13/api/mo/uni/tn-production.json +""" + +from ansible.module_utils.basic import AnsibleModule +from ansible_collections.cisco.aci.plugins.module_utils.aci import ACIModule, aci_argument_spec, aci_annotation_spec, aci_owner_spec + + +def main(): + argument_spec = aci_argument_spec() + argument_spec.update(aci_annotation_spec()) + argument_spec.update(aci_owner_spec()) + argument_spec.update( + tenant=dict(type="str", aliases=["tenant_name"]), # Not required for querying all objects + hsrp=dict(type="str", aliases=["hsrp_interface", "name"]), # Not required for querying all objects + description=dict(type="str", aliases=["descr"]), + controls=dict(type="list", elements="str", choices=["bfd", "bia"]), + reload_delay=dict(type="int"), + delay=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=[ + ["state", "absent", ["tenant", "hsrp"]], + ["state", "present", ["tenant", "hsrp"]], + ], + ) + + aci = ACIModule(module) + + tenant = module.params.get("tenant") + hsrp = module.params.get("hsrp") + description = module.params.get("description") + controls = ",".join(module.params.get("controls")) if module.params.get("controls") else None + + reload_delay = module.params.get("reload_delay") + if reload_delay is not None and reload_delay not in range(1, 10000): + module.fail_json(msg="Parameter 'reload_delay' is only valid in range between 1 and 10000.") + + delay = module.params.get("delay") + if delay is not None and delay not in range(1, 10000): + module.fail_json(msg="Parameter 'delay' is only valid in range between 1 and 10000.") + + state = module.params.get("state") + + 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="hsrpIfPol", + aci_rn="hsrpIfPol-{0}".format(hsrp), + module_object=hsrp, + target_filter={"name": hsrp}, + ), + ) + + aci.get_existing() + + if state == "present": + aci.payload( + aci_class="hsrpIfPol", + class_config=dict( + name=hsrp, + descr=description, + ctrl=controls, + reloadDelay=reload_delay, + delay=delay, + ), + ) + + aci.get_diff(aci_class="hsrpIfPol") + + aci.post_config() + + elif state == "absent": + aci.delete_config() + + aci.exit_json() + + +if __name__ == "__main__": + main() diff --git a/ansible_collections/cisco/aci/plugins/modules/aci_interface_policy_leaf_fc_policy_group.py b/ansible_collections/cisco/aci/plugins/modules/aci_interface_policy_leaf_fc_policy_group.py index 6c3436459..b77eb16fe 100644 --- a/ansible_collections/cisco/aci/plugins/modules/aci_interface_policy_leaf_fc_policy_group.py +++ b/ansible_collections/cisco/aci/plugins/modules/aci_interface_policy_leaf_fc_policy_group.py @@ -13,7 +13,7 @@ ANSIBLE_METADATA = {"metadata_version": "1.1", "status": ["preview"], "supported DOCUMENTATION = r""" --- module: aci_interface_policy_leaf_fc_policy_group -short_description: Manage Fibre Channel (FC) interface policy groups (infra:FcAccBndlGrp, infra:FcAccPortGrp) +short_description: Manage Fibre Channel (FC) interface policy groups (infra:FcAccBndlGrp and infra:FcAccPortGrp) description: - Manage Fibre Channel (FC) interface policy groups on Cisco ACI fabrics. options: diff --git a/ansible_collections/cisco/aci/plugins/modules/aci_interface_policy_leaf_policy_group.py b/ansible_collections/cisco/aci/plugins/modules/aci_interface_policy_leaf_policy_group.py index da2e90adf..d106df250 100644 --- a/ansible_collections/cisco/aci/plugins/modules/aci_interface_policy_leaf_policy_group.py +++ b/ansible_collections/cisco/aci/plugins/modules/aci_interface_policy_leaf_policy_group.py @@ -14,7 +14,7 @@ ANSIBLE_METADATA = {"metadata_version": "1.1", "status": ["preview"], "supported DOCUMENTATION = r""" --- module: aci_interface_policy_leaf_policy_group -short_description: Manage fabric interface policy leaf policy groups (infra:AccBndlGrp, infra:AccPortGrp) +short_description: Manage fabric interface policy leaf policy groups (infra:AccBndlGrp and infra:AccPortGrp) description: - Manage fabric interface policy leaf policy groups on Cisco ACI fabrics. options: @@ -624,34 +624,6 @@ def main(): ), ), ), - dict( - infraRsLinkFlapPol=dict( - attributes=dict( - tnFabricLinkFlapPolName=link_flap_policy, - ), - ), - ), - dict( - infraRsQosLlfcIfPol=dict( - attributes=dict( - tnQosLlfcIfPolName=link_level_flow_control, - ), - ), - ), - dict( - infraRsMacsecIfPol=dict( - attributes=dict( - tnMacsecIfPolName=mac_sec_interface_policy, - ), - ), - ), - dict( - infraRsCoppIfPol=dict( - attributes=dict( - tnCoppIfPolName=copp_policy, - ), - ), - ), ] child_classes = [ @@ -671,10 +643,6 @@ def main(): "infraRsQosSdIfPol", "infraRsStormctrlIfPol", "infraRsStpIfPol", - "infraRsLinkFlapPol", - "infraRsQosLlfcIfPol", - "infraRsMacsecIfPol", - "infraRsCoppIfPol", ] # Add infraRsattEntP binding only when aep is defined @@ -728,6 +696,7 @@ def main(): ) ) child_classes.append("infraRsOpticsIfPol") + if dwdm is not None: child_configs.append( dict( @@ -739,6 +708,7 @@ def main(): ) ) child_classes.append("infraRsDwdmIfPol") + if port_authentication is not None: child_configs.append( dict( @@ -750,6 +720,7 @@ def main(): ) ) child_classes.append("infraRsL2PortAuthPol") + if poe_interface_policy is not None: child_configs.append( dict( @@ -762,6 +733,54 @@ def main(): ) child_classes.append("infraRsPoeIfPol") + if link_flap_policy is not None: + child_configs.append( + dict( + infraRsLinkFlapPol=dict( + attributes=dict( + tnFabricLinkFlapPolName=link_flap_policy, + ), + ), + ), + ) + child_classes.append("infraRsLinkFlapPol") + + if link_level_flow_control is not None: + child_configs.append( + dict( + infraRsQosLlfcIfPol=dict( + attributes=dict( + tnQosLlfcIfPolName=link_level_flow_control, + ), + ), + ), + ) + child_classes.append("infraRsQosLlfcIfPol") + + if mac_sec_interface_policy is not None: + child_configs.append( + dict( + infraRsMacsecIfPol=dict( + attributes=dict( + tnMacsecIfPolName=mac_sec_interface_policy, + ), + ), + ), + ) + child_classes.append("infraRsMacsecIfPol") + + if copp_policy is not None: + child_configs.append( + dict( + infraRsCoppIfPol=dict( + attributes=dict( + tnCoppIfPolName=copp_policy, + ), + ), + ), + ) + child_classes.append("infraRsCoppIfPol") + aci.construct_url( root_class=dict( aci_class=aci_class_name, diff --git a/ansible_collections/cisco/aci/plugins/modules/aci_interface_policy_link_level.py b/ansible_collections/cisco/aci/plugins/modules/aci_interface_policy_link_level.py index 5c0120d4d..1980721cc 100644 --- a/ansible_collections/cisco/aci/plugins/modules/aci_interface_policy_link_level.py +++ b/ansible_collections/cisco/aci/plugins/modules/aci_interface_policy_link_level.py @@ -36,9 +36,10 @@ options: speed: description: - Determines the interface policy administrative port speed. + - The C(auto) option is only supported in APIC version 5.2 or later. - The APIC defaults to C(inherit) when unset during creation. type: str - choices: [ 100M, 1G, 10G, 25G, 40G, 50G, 100G, 200G, 400G, inherit ] + choices: [ 100M, 1G, 10G, 25G, 40G, 50G, 100G, 200G, 400G, auto, inherit ] default: inherit link_debounce_interval: description: @@ -231,7 +232,7 @@ def main(): 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"]), + speed=dict(type="str", default="inherit", choices=["100M", "1G", "10G", "25G", "40G", "50G", "100G", "200G", "400G", "auto", "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"] diff --git a/ansible_collections/cisco/aci/plugins/modules/aci_interface_policy_pim.py b/ansible_collections/cisco/aci/plugins/modules/aci_interface_policy_pim.py new file mode 100644 index 000000000..ad47fb836 --- /dev/null +++ b/ansible_collections/cisco/aci/plugins/modules/aci_interface_policy_pim.py @@ -0,0 +1,444 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- + +# Copyright: (c) 2023, Gaspard Micol (@gmicol) +# 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_pim +short_description: Manage Protocol-Independent Multicast (PIM) interface policies (pim:IfPol) +description: +- Manage Protocol Independent Multicast interface policies for Tenants on Cisco ACI fabrics. +options: + tenant: + description: + - The name of an existing Tenant. + type: str + aliases: [ tenant_name ] + pim: + description: + - The PIM interface policy name. + - The name cannot be changed after the object has been created. + type: str + aliases: [ pim_interface_policy, name ] + authentication_key: + description: + - The authentication key. + type: str + aliases: [ auth_key ] + authentication_type: + description: + - The authentication type. + type: str + choices: [ none, md5_hmac ] + aliases: [ auth_type ] + control_state: + description: + - The PIM interface policy control state. + - 'This is a list of one or more of the following controls:' + - C(multicast_domain_boundary) -- Boundary of Multicast domain. + - C(strict_rfc_compliant) -- Only listen to PIM protocol packets. + - C(passive) -- Do not send/receive PIM protocol packets. + type: list + elements: str + choices: [ multicast_domain_boundary, strict_rfc_compliant, passive ] + designated_router_delay: + description: + - The PIM designated router delay. + - Accepted values range between C(1) and C(65535). + - The APIC defaults to C(3) when unset during creation. + type: int + aliases: [ delay ] + designated_router_priority: + description: + - The PIM designated router priority. + - Accepted values range between C(1) and C(4294967295). + - The APIC defaults to C(1) when unset during creation. + type: int + aliases: [ prio ] + hello_interval: + description: + - The time interval in seconds between hello packets that PIM sends on the interface. + - The smaller the hello interval, the faster topological changes will be detected, but more routing traffic will ensue. + - Accepted values range between C(1) and C(18724286). + - The APIC defaults to C(30000) when unset during creation. + type: int + join_prune_interval: + description: + - The join prune interval in seconds. + - Accepted values range between C(60) and C(65520). + - The APIC defaults to C(60) when unset during creation. + type: int + aliases: [ jp_interval ] + inbound_join_prune_filter_policy: + description: + - The interface-level inbound join/prune filter policy. + - The M(cisco.aci.aci_pim_route_map_policy) can be used for this. + - To delete it, pass an empty string. + type: str + aliases: [ inbound_filter ] + outbound_join_prune_filter_policy: + description: + - The interface-level outbound join/prune filter policy. + - The M(cisco.aci.aci_pim_route_map_policy) can be used for this. + - To delete it, pass an empty string. + type: str + aliases: [ outbound_filter ] + neighbor_filter_policy: + description: + - The Interface-level neighbor filter policy. + - The M(cisco.aci.aci_pim_route_map_policy) can be used for this. + - To delete it, pass an empty string. + type: str + aliases: [ neighbor_filter ] + description: + description: + - The description of the PIM interface 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 +- cisco.aci.annotation +- cisco.aci.owner + +notes: +- The C(tenant) used must exist before using this module in your playbook. + The M(cisco.aci.aci_tenant) module can be used for this. +seealso: +- module: cisco.aci.aci_tenant +- module: cisco.aci.aci_pim_route_map_policy +- name: APIC Management Information Model reference + description: More information about the internal APIC class B(pim:IfPol). + link: https://developer.cisco.com/docs/apic-mim-ref/ +author: +- Gaspard Micol (@gmicol) +""" + +EXAMPLES = r""" +- name: Create a PIM interface policy + cisco.aci.aci_interface_policy_pim: + host: apic + username: admin + password: SomeSecretPassword + tenant: production + pim: my_pim_policy + control_state: [multicast_domain_boundary, strict_rfc_compliant] + designated_router_delay: 10 + designated_router_priority: tens_of_micro + hello_interval: 5 + join_prune_interval: 15 + inbound_join_prune_filter_policy: my_pim_route_map_policy_1 + outbound_join_prune_filter_policy: my_pim_route_map_policy_2 + neighbor_filter_policy: my_pim_route_map_policy_3 + state: present + delegate_to: localhost + +- name: Query a PIM interface policy + cisco.aci.aci_interface_policy_pim: + host: apic + username: admin + password: SomeSecretPassword + tenant: production + pim: my_pim_policy + state: query + delegate_to: localhost + register: query_result + +- name: Query all PIM interface policies in tenant production + cisco.aci.aci_interface_policy_pim: + host: apic + username: admin + password: SomeSecretPassword + tenant: production + state: query + delegate_to: localhost + register: query_result + +- name: Delete a PIM interface policy + cisco.aci.aci_interface_policy_pim: + host: apic + username: admin + password: SomeSecretPassword + tenant: production + pim: my_pim_policy + 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: '' +sent: + description: The actual/minimal configuration pushed to the APIC + returned: info + type: list + sample: + { + "fvTenant": { + "attributes": { + "descr": "Production environment" + } + } + } +previous: + description: The original configuration from the APIC before the module has started + returned: info + type: list + sample: + [ + { + "fvTenant": { + "attributes": { + "descr": "Production", + "dn": "uni/tn-production", + "name": "production", + "nameAlias": "", + "ownerKey": "", + "ownerTag": "" + } + } + } + ] +proposed: + description: The assembled configuration from the user-provided parameters + returned: info + type: dict + sample: + { + "fvTenant": { + "attributes": { + "descr": "Production environment", + "name": "production" + } + } + } +filter_string: + description: The filter string used for the request + returned: failure or debug + type: str + sample: ?rsp-prop-include=config-only +method: + description: The HTTP method used for the request to the APIC + returned: failure or debug + type: str + sample: POST +response: + description: The HTTP response from the APIC + returned: failure or debug + type: str + sample: OK (30 bytes) +status: + description: The HTTP status from the APIC + returned: failure or debug + type: int + sample: 200 +url: + description: The HTTP url used for the request to the APIC + returned: failure or debug + type: str + sample: https://10.11.12.13/api/mo/uni/tn-production.json +""" + +from ansible.module_utils.basic import AnsibleModule +from ansible_collections.cisco.aci.plugins.module_utils.aci import ACIModule, aci_argument_spec, aci_annotation_spec, aci_owner_spec +from ansible_collections.cisco.aci.plugins.module_utils.constants import ( + MATCH_PIM_INTERFACE_POLICY_CONTROL_STATE_MAPPING, + MATCH_PIM_INTERFACE_POLICY_AUTHENTICATION_TYPE_MAPPING, +) + + +def main(): + argument_spec = aci_argument_spec() + argument_spec.update(aci_annotation_spec()) + argument_spec.update(aci_owner_spec()) + argument_spec.update( + tenant=dict(type="str", aliases=["tenant_name"]), # Not required for querying all objects + pim=dict(type="str", aliases=["pim_interface_policy", "name"]), # Not required for querying all objects + description=dict(type="str", aliases=["descr"]), + authentication_key=dict(type="str", aliases=["auth_key"], no_log=True), + authentication_type=dict(type="str", choices=["none", "md5_hmac"], aliases=["auth_type"]), + control_state=dict(type="list", elements="str", choices=["multicast_domain_boundary", "strict_rfc_compliant", "passive"]), + designated_router_delay=dict(type="int", aliases=["delay"]), + designated_router_priority=dict(type="int", aliases=["prio"]), + hello_interval=dict(type="int"), + join_prune_interval=dict(type="int", aliases=["jp_interval"]), + inbound_join_prune_filter_policy=dict(type="str", aliases=["inbound_filter"]), + outbound_join_prune_filter_policy=dict(type="str", aliases=["outbound_filter"]), + neighbor_filter_policy=dict(type="str", aliases=["neighbor_filter"]), + 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", ["pim", "tenant"]], + ["state", "present", ["pim", "tenant"]], + ], + ) + + aci = ACIModule(module) + + tenant = module.params.get("tenant") + pim = module.params.get("pim") + authentication_key = module.params.get("authentication_key") + authentication_type = MATCH_PIM_INTERFACE_POLICY_AUTHENTICATION_TYPE_MAPPING.get(module.params.get("authentication_type")) + description = module.params.get("description") + name_alias = module.params.get("name_alias") + state = module.params.get("state") + + designated_router_delay = module.params.get("designated_router_delay") + if designated_router_delay is not None and designated_router_delay not in range(1, 65536): + module.fail_json(msg="Parameter 'designated_router_delay' is only valid in range between 1 and 65535.") + + designated_router_priority = module.params.get("designated_router_priority") + if designated_router_priority is not None and designated_router_priority not in range(1, 4294967296): + module.fail_json(msg="Parameter 'designated_router_priority' is only valid in range between 1 and 4294967295.") + + hello_interval = module.params.get("hello_interval") + if hello_interval is not None and hello_interval not in range(1, 18724287): + module.fail_json(msg="Parameter 'hello_interval' is only valid in range between 1 and 18724286.") + + join_prune_interval = module.params.get("join_prune_interval") + if join_prune_interval is not None and join_prune_interval not in range(60, 65521): + module.fail_json(msg="Parameter 'join_prune_interval' is only valid in range between 60 and 65520.") + + if module.params.get("control_state"): + control_state = ",".join([MATCH_PIM_INTERFACE_POLICY_CONTROL_STATE_MAPPING.get(v) for v in module.params.get("control_state")]) + else: + control_state = None + + child_classes = dict( + pimJPInbFilterPol=module.params.get("inbound_join_prune_filter_policy"), + pimJPOutbFilterPol=module.params.get("outbound_join_prune_filter_policy"), + pimNbrFilterPol=module.params.get("neighbor_filter_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="pimIfPol", + aci_rn="pimifpol-{0}".format(pim), + module_object=pim, + target_filter={"name": pim}, + ), + child_classes=list(child_classes.keys()), + ) + + aci.get_existing() + + if state == "present": + child_configs = [] + for class_name, class_input in child_classes.items(): + if class_input is not None: + if class_input == "" and isinstance(aci.existing, list) and len(aci.existing) > 0: + for child in aci.existing[0].get("pimIfPol", {}).get("children", {}): + if child.get(class_name): + child_configs.append(dict([(class_name, dict(attributes=dict(status="deleted")))])) + elif class_input != "": + child_configs.append( + dict( + [ + ( + class_name, + dict( + attributes=dict(), + children=[ + dict( + rtdmcRsFilterToRtMapPol=dict( + attributes=dict( + tDn="uni/tn-{0}/rtmap-{1}".format(tenant, class_input), + ), + ) + ) + ], + ), + ) + ] + ) + ) + + aci.payload( + aci_class="pimIfPol", + class_config=dict( + name=pim, + descr=description, + authKey=authentication_key, + authT=authentication_type, + ctrl=control_state, + drDelay=designated_router_delay, + drPrio=designated_router_priority, + helloItvl=hello_interval, + jpInterval=join_prune_interval, + nameAlias=name_alias, + ), + child_configs=child_configs, + ) + + aci.get_diff(aci_class="pimIfPol") + + aci.post_config() + + elif state == "absent": + aci.delete_config() + + aci.exit_json() + + +if __name__ == "__main__": + main() diff --git a/ansible_collections/cisco/aci/plugins/modules/aci_interface_policy_storm_control.py b/ansible_collections/cisco/aci/plugins/modules/aci_interface_policy_storm_control.py new file mode 100644 index 000000000..19b67070d --- /dev/null +++ b/ansible_collections/cisco/aci/plugins/modules/aci_interface_policy_storm_control.py @@ -0,0 +1,434 @@ +#!/usr/bin/python + +# Copyright: (c) 2023, Eric Girard <@netgirard> +# Copyright: (c) 2024, Gaspard Micol (@gmicol) +# 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_storm_control +short_description: Manage Storm Control interface policies (stormctrl:IfPol) +description: +- Manage Storm Control interface policies on Cisco ACI fabrics. +options: + storm_control_policy: + description: + - The Storm Control interface policy name. + type: str + aliases: [ storm_control, storm_control_name, name ] + description: + description: + - The description for the Storm interface policy name. + 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 + storm_control_action: + description: + - The storm control action to take when triggered. + type: str + choices: [drop, shutdown] + storm_control_soak_action: + description: + - The number of instances before triggering shutdown. + type: int + all_types_configuration: + description: + - The rates configuration for all packets type. + type: dict + aliases: [ all_types ] + suboptions: + rate: + description: + - The rate for all packet types. + type: str + burst_rate: + description: + - The burst rate of all packet types. + type: str + rate_type: + description: + - The type of rate of all packet types. + - Choice between percentage of the bandiwth C(percentage) or packet per second C(pps) + type: str + choices: [ percentage, pps ] + required: true + broadcast_configuration: + description: + - The rates configuration of broadcast packets. + type: dict + aliases: [ broadcast ] + suboptions: + rate: + description: + - The rate for broadcast packets. + type: str + burst_rate: + description: + - The burst rate of broadcast packets. + type: str + rate_type: + description: + - The type of rate of all packet types. + - Choice between percentage of the bandiwth C(percentage) or packet per second C(pps) + type: str + choices: [ percentage, pps ] + required: true + multicast_configuration: + description: + - The rates configuration of multicast packets. + type: dict + aliases: [ multicast ] + suboptions: + rate: + description: + - The rate for multicast packets. + type: str + burst_rate: + description: + - The burst rate of multicast packets. + type: str + rate_type: + description: + - The type of rate of all packet types. + - Choice between percentage of the bandiwth C(percentage) or packet per second C(pps) + type: str + choices: [ percentage, pps ] + required: true + unicast_configuration: + description: + - The rates configuration of unicast packets. + type: dict + aliases: [ unicast ] + suboptions: + rate: + description: + - The rate for unicast packets. + type: str + burst_rate: + description: + - The burst rate of unicast packets. + type: str + rate_type: + description: + - The type of rate of all packet types. + - Choice between percentage of the bandiwth C(percentage) or packet per second C(pps) + type: str + choices: [ percentage, pps ] + required: true +extends_documentation_fragment: +- cisco.aci.aci +- cisco.aci.annotation +- cisco.aci.owner + +seealso: +- name: APIC Management Information Model reference + description: More information about the internal APIC class B(stormctrl:IfPol). + link: https://developer.cisco.com/docs/apic-mim-ref/ +author: +- Eric Girard (@netgirard) +- Gaspard Micol (@gmicol) +""" + +EXAMPLES = r""" +- name: Add a new Storm Control Interface Policy + cisco.aci.aci_interface_policy_storm_control: + host: apic + username: admin + password: SomeSecretPassword + storm_control_policy: my_storm_control_policy + description: My Storm Control Policy + all_types_configuration: + rate: 80 + burst_rate: 100 + rate_type: percentage + storm_control_action: shutdown + storm_control_soak_action: 5 + state: present + delegate_to: localhost + +- name: Query a Storm Control Interface Policy + cisco.aci.aci_interface_policy_storm_control: + host: apic + username: admin + password: SomeSecretPassword + storm_control_policy: my_storm_control_policy + state: query + delegate_to: localhost + +- name: Query all Storm Control Interface Policies + cisco.aci.aci_interface_policy_storm_control: + host: apic + username: admin + password: SomeSecretPassword + state: query + delegate_to: localhost + +- name: Delete a Storm Control Interface Policy + cisco.aci.aci_interface_policy_storm_control: + host: apic + username: admin + password: SomeSecretPassword + tenant: my_tenant + storm_control_policy: my_storm_control_policy + 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: + [ + { + "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: '' +sent: + description: The actual/minimal configuration pushed to the APIC + returned: info + type: list + sample: + { + "fvTenant": { + "attributes": { + "descr": "Production environment" + } + } + } +previous: + description: The original configuration from the APIC before the module has started + returned: info + type: list + sample: + [ + { + "fvTenant": { + "attributes": { + "descr": "Production", + "dn": "uni/tn-production", + "name": "production", + "nameAlias": "", + "ownerKey": "", + "ownerTag": "" + } + } + } + ] +proposed: + description: The assembled configuration from the user-provided parameters + returned: info + type: dict + sample: + { + "fvTenant": { + "attributes": { + "descr": "Production environment", + "name": "production" + } + } + } +filter_string: + description: The filter string used for the request + returned: failure or debug + type: str + sample: ?rsp-prop-include=config-only +method: + description: The HTTP method used for the request to the APIC + returned: failure or debug + type: str + sample: POST +response: + description: The HTTP response from the APIC + returned: failure or debug + type: str + sample: OK (30 bytes) +status: + description: The HTTP status from the APIC + returned: failure or debug + type: int + sample: 200 +url: + description: The HTTP url used for the request to the APIC + returned: failure or debug + type: str + sample: https://10.11.12.13/api/mo/uni/tn-production.json +""" + +from ansible.module_utils.basic import AnsibleModule +from ansible_collections.cisco.aci.plugins.module_utils.aci import ( + ACIModule, + aci_argument_spec, + aci_annotation_spec, + aci_owner_spec, + storm_control_policy_rate_spec, +) + + +def get_rates_configuration(module, configuration, percentage, pps, burst_percentage, burst_pps): + if configuration is None: + return {} + rate = configuration.get("rate") + burst_rate = configuration.get("burst_rate") + rate_type = configuration.get("rate_type") + + if rate_type == "percentage": + for rate_name, rate_value in dict(rate=rate, burst_rate=burst_rate).items(): + if rate_value is None or not (0 <= float(rate_value) <= 100): + module.fail_json( + msg="If argument rate_type is percentage, the {0} needs to be a value between 0 and 100 inclusive, got {1}".format( + rate_name, + rate_value, + ) + ) + return { + percentage: "{0:.6f}".format(float(rate)), + pps: "unspecified", + burst_percentage: "{0:.6f}".format(float(burst_rate)), + burst_pps: "unspecified", + } + elif rate_type == "pps": + return {pps: rate, burst_pps: burst_rate} + + +def main(): + argument_spec = aci_argument_spec() + argument_spec.update(aci_annotation_spec()) + argument_spec.update(aci_owner_spec()) + argument_spec.update( + storm_control_policy=dict( + type="str", required=False, aliases=["name", "storm_control", "storm_control_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"), + all_types_configuration=dict(type="dict", options=storm_control_policy_rate_spec(), aliases=["all_types"]), + broadcast_configuration=dict(type="dict", options=storm_control_policy_rate_spec(), aliases=["broadcast"]), + multicast_configuration=dict(type="dict", options=storm_control_policy_rate_spec(), aliases=["multicast"]), + unicast_configuration=dict(type="dict", options=storm_control_policy_rate_spec(), aliases=["unicast"]), + storm_control_action=dict(type="str", choices=["drop", "shutdown"]), + storm_control_soak_action=dict(type="int"), + ) + + module = AnsibleModule( + argument_spec=argument_spec, + supports_check_mode=True, + required_if=[ + ["state", "absent", ["storm_control_policy"]], + ["state", "present", ["storm_control_policy"]], + ], + mutually_exclusive=[ + ("all_types_configuration", "broadcast_configuration"), + ("all_types_configuration", "multicast_configuration"), + ("all_types_configuration", "unicast_configuration"), + ], + ) + + aci = ACIModule(module) + + storm_control_policy = module.params.get("storm_control_policy") + description = module.params.get("description") + state = module.params.get("state") + name_alias = module.params.get("name_alias") + storm_control_action = module.params.get("storm_control_action") + storm_control_soak_action = module.params.get("storm_control_soak_action") + all_types_configuration = module.params.get("all_types_configuration") + broadcast_configuration = module.params.get("broadcast_configuration") + multicast_configuration = module.params.get("multicast_configuration") + unicast_configuration = module.params.get("unicast_configuration") + + rates_input = {} + + if all_types_configuration is not None: + rates_input.update(get_rates_configuration(module, all_types_configuration, "rate", "ratePps", "burstRate", "burstPps")) + storm_control_types = "Invalid" + elif any([broadcast_configuration, multicast_configuration, unicast_configuration]): + rates_input.update(get_rates_configuration(module, broadcast_configuration, "bcRate", "bcRatePps", "bcBurstRate", "bcBurstPps")) + rates_input.update(get_rates_configuration(module, multicast_configuration, "mcRate", "mcRatePps", "mcBurstRate", "mcBurstPps")) + rates_input.update(get_rates_configuration(module, unicast_configuration, "uucRate", "uucRatePps", "uucBurstRate", "uucBurstPps")) + storm_control_types = "Valid" + + aci.construct_url( + root_class=dict( + aci_class="infraInfra", + aci_rn="infra", + ), + subclass_1=dict( + aci_class="stormctrlIfPol", + aci_rn="stormctrlifp-{0}".format(storm_control_policy), + module_object=storm_control_policy, + target_filter={"name": storm_control_policy}, + ), + ) + + aci.get_existing() + + if state == "present": + class_config = dict( + name=storm_control_policy, + descr=description, + nameAlias=name_alias, + isUcMcBcStormPktCfgValid=storm_control_types, + stormCtrlAction=storm_control_action, + stormCtrlSoakInstCount=storm_control_soak_action, + ) + class_config.update(rates_input) + aci.payload( + aci_class="stormctrlIfPol", + class_config=class_config, + ) + + aci.get_diff(aci_class="stormctrlIfPol") + + aci.post_config() + + elif state == "absent": + aci.delete_config() + + aci.exit_json() + + +if __name__ == "__main__": + main() diff --git a/ansible_collections/cisco/aci/plugins/modules/aci_key_policy.py b/ansible_collections/cisco/aci/plugins/modules/aci_key_policy.py new file mode 100644 index 000000000..27ebe292a --- /dev/null +++ b/ansible_collections/cisco/aci/plugins/modules/aci_key_policy.py @@ -0,0 +1,325 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- + +# Copyright: (c) 2023, Gaspard Micol (@gmicol) +# 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_key_policy +short_description: Manage Key Policy (fv:KeyPol) +description: +- Manage Key Policies for KeyChain Policies on Cisco ACI fabrics. +options: + tenant: + description: + - The name of an existing tenant. + type: str + aliases: [ tenant_name ] + keychain_policy: + description: + - The name of an existing keychain policy. + type: str + aliases: [ keychain_policy_name ] + id: + description: + - The object identifier. + type: int + start_time: + description: + - The start time of the key policy. + - The APIC defaults to C(now) when unset during creation. + - The format is YYYY-MM-DD HH:MM:SS + type: str + end_time: + description: + - The end time of the key policy. + - The APIC defaults to C(infinite) when unset during creation. + - The format is YYYY-MM-DD HH:MM:SS + type: str + pre_shared_key: + description: + - The pre-shared authentifcation key. + - When using I(pre_shared_key) this module will always show as C(changed) as the module cannot know what the currently configured key is. + type: str + description: + description: + - The description for the keychain 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 +extends_documentation_fragment: +- cisco.aci.aci +- cisco.aci.annotation +- cisco.aci.owner + +notes: +- The C(tenant) and C(keychain_policy) must exist before using this module in your playbook. + The M(cisco.aci.aci_tenant) and M(cisco.aci.aci_keychain_policy) can be used for this. +seealso: +- module: cisco.aci.aci_tenant +- module: cisco.aci.aci_keychain_policy +- name: APIC Management Information Model reference + description: More information about the internal APIC classes + link: https://developer.cisco.com/docs/apic-mim-ref/ +author: +- Gaspard Micol (@gmicol) +""" + +EXAMPLES = r""" +- name: Add a new key policy + cisco.aci.aci_key_policy: + host: apic + username: admin + password: SomeSecretPassword + tenant: my_tenant + keychain_policy: my_keychain_policy + id: 1 + start_time: now + end_time: infinite + pre_shared_key: my_password + state: present + delegate_to: localhost + +- name: Delete an key policy + cisco.aci.aci_key_policy: + host: apic + username: admin + password: SomeSecretPassword + tenant: my_tenant + keychain_policy: my_keychain_policy + id: 1 + state: absent + delegate_to: localhost + +- name: Query an key policy + cisco.aci.aci_key_policy: + host: apic + username: admin + password: SomeSecretPassword + tenant: my_tenant + keychain_policy: my_keychain_policy + id: 1 + state: query + delegate_to: localhost + register: query_result + +- name: Query all key policies in my_keychain_policy + cisco.aci.aci_key_policy: + host: apic + username: admin + password: SomeSecretPassword + tenant: my_tenant + keychain_policy: my_keychain_policy + state: query + delegate_to: localhost + register: query_result +""" + +RETURN = r""" +current: + description: The existing configuration from the APIC after the module has finished + returned: success + type: list + sample: + [ + { + "fvTenant": { + "attributes": { + "descr": "Production environment", + "dn": "uni/tn-production", + "name": "production", + "nameAlias": "", + "ownerKey": "", + "ownerTag": "" + } + } + } + ] +error: + description: The error information as returned from the APIC + returned: failure + type: dict + sample: + { + "code": "122", + "text": "unknown managed object class foo" + } +raw: + description: The raw output returned by the APIC REST API (xml or json) + returned: parse error + type: str + sample: '' +sent: + description: The actual/minimal configuration pushed to the APIC + returned: info + type: list + sample: + { + "fvTenant": { + "attributes": { + "descr": "Production environment" + } + } + } +previous: + description: The original configuration from the APIC before the module has started + returned: info + type: list + sample: + [ + { + "fvTenant": { + "attributes": { + "descr": "Production", + "dn": "uni/tn-production", + "name": "production", + "nameAlias": "", + "ownerKey": "", + "ownerTag": "" + } + } + } + ] +proposed: + description: The assembled configuration from the user-provided parameters + returned: info + type: dict + sample: + { + "fvTenant": { + "attributes": { + "descr": "Production environment", + "name": "production" + } + } + } +filter_string: + description: The filter string used for the request + returned: failure or debug + type: str + sample: ?rsp-prop-include=config-only +method: + description: The HTTP method used for the request to the APIC + returned: failure or debug + type: str + sample: POST +response: + description: The HTTP response from the APIC + returned: failure or debug + type: str + sample: OK (30 bytes) +status: + description: The HTTP status from the APIC + returned: failure or debug + type: int + sample: 200 +url: + description: The HTTP url used for the request to the APIC + returned: failure or debug + type: str + sample: https://10.11.12.13/api/mo/uni/tn-production.json +""" + + +from ansible.module_utils.basic import AnsibleModule +from ansible_collections.cisco.aci.plugins.module_utils.aci import ACIModule, aci_argument_spec, aci_annotation_spec, aci_owner_spec + + +def main(): + argument_spec = aci_argument_spec() + argument_spec.update(aci_annotation_spec()) + argument_spec.update(aci_owner_spec()) + argument_spec.update( + tenant=dict(type="str", aliases=["tenant_name"]), + keychain_policy=dict(type="str", aliases=["keychain_policy_name"], no_log=False), + id=dict(type="int"), + start_time=dict(type="str"), + end_time=dict(type="str"), + pre_shared_key=dict(type="str", no_log=True), + description=dict(type="str", aliases=["descr"]), + state=dict(type="str", default="present", choices=["absent", "present", "query"]), + ) + + module = AnsibleModule( + argument_spec=argument_spec, + supports_check_mode=True, + required_if=[ + ["state", "absent", ["tenant", "keychain_policy", "id"]], + ["state", "present", ["tenant", "keychain_policy", "id"]], + ], + ) + + tenant = module.params.get("tenant") + keychain_policy = module.params.get("keychain_policy") + id = module.params.get("id") + start_time = module.params.get("start_time") + end_time = module.params.get("end_time") + pre_shared_key = module.params.get("pre_shared_key") + description = module.params.get("description") + 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="fvKeyChainPol", + aci_rn="keychainp-{0}".format(keychain_policy), + module_object=keychain_policy, + target_filter={"name": keychain_policy}, + ), + subclass_2=dict( + aci_class="fvKeyPol", + aci_rn="keyp-{0}".format(id), + module_object=id, + target_filter={"id": id}, + ), + ) + + aci.get_existing() + + if state == "present": + class_config = dict( + id=id, + startTime=start_time, + endTime=end_time, + descr=description, + ) + if pre_shared_key is not None: + class_config.update(preSharedKey=pre_shared_key) + + aci.payload( + aci_class="fvKeyPol", + class_config=class_config, + ) + + aci.get_diff(aci_class="fvKeyPol") + + aci.post_config() + + elif state == "absent": + aci.delete_config() + + aci.exit_json() + + +if __name__ == "__main__": + main() diff --git a/ansible_collections/cisco/aci/plugins/modules/aci_keychain_policy.py b/ansible_collections/cisco/aci/plugins/modules/aci_keychain_policy.py new file mode 100644 index 000000000..a9776cf59 --- /dev/null +++ b/ansible_collections/cisco/aci/plugins/modules/aci_keychain_policy.py @@ -0,0 +1,276 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- + +# Copyright: (c) 2023, Gaspard Micol (@gmicol) +# 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_keychain_policy +short_description: Manage KeyChain Policy (fv:KeyChainPol) +description: +- Manage KeyChain Policies for tenants on Cisco ACI fabrics. +options: + tenant: + description: + - The name of an existing tenant. + type: str + aliases: [ tenant_name ] + keychain_policy: + description: + - The name of the keychain policy. + type: str + aliases: [ keychain_policy_name, name ] + description: + description: + - The description for the keychain 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 +extends_documentation_fragment: +- cisco.aci.aci +- cisco.aci.annotation +- cisco.aci.owner + +notes: +- The C(tenant) must exist before using this module in your playbook. + The M(cisco.aci.aci_tenant) can be used for this. +seealso: +- module: cisco.aci.aci_tenant +- name: APIC Management Information Model reference + description: More information about the internal APIC classes + link: https://developer.cisco.com/docs/apic-mim-ref/ +author: +- Gaspard Micol (@gmicol) +""" + +EXAMPLES = r""" +- name: Add a new keychain policy + cisco.aci.aci_keychain_policy: + host: apic + username: admin + password: SomeSecretPassword + tenant: my_tenant + keychain_policy: my_keychain_policy + state: present + delegate_to: localhost + +- name: Delete an keychain policy + cisco.aci.aci_keychain_policy: + host: apic + username: admin + password: SomeSecretPassword + tenant: my_tenant + keychain_policy: my_keychain_policy + state: absent + delegate_to: localhost + +- name: Query an keychain policy + cisco.aci.aci_keychain_policy: + host: apic + username: admin + password: SomeSecretPassword + tenant: my_tenant + keychain_policy: my_keychain_policy + state: query + delegate_to: localhost + register: query_result + +- name: Query an keychain policy in my_tenant + cisco.aci.aci_keychain_policy: + host: apic + username: admin + password: SomeSecretPassword + tenant: my_tenant + state: query + delegate_to: localhost + register: query_result +""" + +RETURN = r""" +current: + description: The existing configuration from the APIC after the module has finished + returned: success + type: list + sample: + [ + { + "fvTenant": { + "attributes": { + "descr": "Production environment", + "dn": "uni/tn-production", + "name": "production", + "nameAlias": "", + "ownerKey": "", + "ownerTag": "" + } + } + } + ] +error: + description: The error information as returned from the APIC + returned: failure + type: dict + sample: + { + "code": "122", + "text": "unknown managed object class foo" + } +raw: + description: The raw output returned by the APIC REST API (xml or json) + returned: parse error + type: str + sample: '' +sent: + description: The actual/minimal configuration pushed to the APIC + returned: info + type: list + sample: + { + "fvTenant": { + "attributes": { + "descr": "Production environment" + } + } + } +previous: + description: The original configuration from the APIC before the module has started + returned: info + type: list + sample: + [ + { + "fvTenant": { + "attributes": { + "descr": "Production", + "dn": "uni/tn-production", + "name": "production", + "nameAlias": "", + "ownerKey": "", + "ownerTag": "" + } + } + } + ] +proposed: + description: The assembled configuration from the user-provided parameters + returned: info + type: dict + sample: + { + "fvTenant": { + "attributes": { + "descr": "Production environment", + "name": "production" + } + } + } +filter_string: + description: The filter string used for the request + returned: failure or debug + type: str + sample: ?rsp-prop-include=config-only +method: + description: The HTTP method used for the request to the APIC + returned: failure or debug + type: str + sample: POST +response: + description: The HTTP response from the APIC + returned: failure or debug + type: str + sample: OK (30 bytes) +status: + description: The HTTP status from the APIC + returned: failure or debug + type: int + sample: 200 +url: + description: The HTTP url used for the request to the APIC + returned: failure or debug + type: str + sample: https://10.11.12.13/api/mo/uni/tn-production.json +""" + + +from ansible.module_utils.basic import AnsibleModule +from ansible_collections.cisco.aci.plugins.module_utils.aci import ACIModule, aci_argument_spec, aci_annotation_spec, aci_owner_spec + + +def main(): + argument_spec = aci_argument_spec() + argument_spec.update(aci_annotation_spec()) + argument_spec.update(aci_owner_spec()) + argument_spec.update( + tenant=dict(type="str", aliases=["tenant_name"]), + keychain_policy=dict(type="str", aliases=["keychain_policy_name", "name"], no_log=False), + description=dict(type="str", aliases=["descr"]), + state=dict(type="str", default="present", choices=["absent", "present", "query"]), + ) + + module = AnsibleModule( + argument_spec=argument_spec, + supports_check_mode=True, + required_if=[ + ["state", "absent", ["tenant", "keychain_policy"]], + ["state", "present", ["tenant", "keychain_policy"]], + ], + ) + + tenant = module.params.get("tenant") + description = module.params.get("description") + keychain_policy = module.params.get("keychain_policy") + 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="fvKeyChainPol", + aci_rn="keychainp-{0}".format(keychain_policy), + module_object=keychain_policy, + target_filter={"name": keychain_policy}, + ), + ) + + aci.get_existing() + + if state == "present": + aci.payload( + aci_class="fvKeyChainPol", + class_config=dict( + name=keychain_policy, + descr=description, + ), + ) + + aci.get_diff(aci_class="fvKeyChainPol") + + aci.post_config() + + elif state == "absent": + aci.delete_config() + + aci.exit_json() + + +if __name__ == "__main__": + main() diff --git a/ansible_collections/cisco/aci/plugins/modules/aci_l2out.py b/ansible_collections/cisco/aci/plugins/modules/aci_l2out.py index 974c3c8e9..fdba63ef5 100644 --- a/ansible_collections/cisco/aci/plugins/modules/aci_l2out.py +++ b/ansible_collections/cisco/aci/plugins/modules/aci_l2out.py @@ -14,7 +14,7 @@ ANSIBLE_METADATA = {"metadata_version": "1.1", "status": ["preview"], "supported DOCUMENTATION = r""" --- module: aci_l2out -short_description: Manage Layer2 Out (L2Out) objects. +short_description: Manage Layer2 Out (L2Out) objects (l2ext:Out) description: - Manage Layer2 Out configuration on Cisco ACI fabrics. options: @@ -64,7 +64,7 @@ notes: 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). + description: More information about the internal APIC class B(l2ext:Out). link: https://developer.cisco.com/docs/apic-mim-ref/ author: - Sudhakar Shet Kudtarkar (@kudtarkar1) diff --git a/ansible_collections/cisco/aci/plugins/modules/aci_l2out_extepg.py b/ansible_collections/cisco/aci/plugins/modules/aci_l2out_extepg.py index 3df19e9da..d633a7aae 100644 --- a/ansible_collections/cisco/aci/plugins/modules/aci_l2out_extepg.py +++ b/ansible_collections/cisco/aci/plugins/modules/aci_l2out_extepg.py @@ -15,9 +15,9 @@ ANSIBLE_METADATA = {"metadata_version": "1.1", "status": ["preview"], "supported DOCUMENTATION = r""" --- module: aci_l2out_extepg -short_description: Manage External Network Instance (L2Out External EPG) objects (l2extInstP). +short_description: Manage External Network Instance (L2Out External EPG) objects (l2ext:InstP). description: -- Manage External Network Instance (L2Out External EPG) objects (l2extInstP) on ACI fabrics. +- Manage External Network Instance (L2Out External EPG) objects on ACI fabrics. options: tenant: description: @@ -63,7 +63,7 @@ notes: 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). + description: More information about the internal APIC class B(l2ext:InstP). link: https://developer.cisco.com/docs/apic-mim-ref/ author: - Sudhakar Shet Kudtarkar (@kudtarkar1) diff --git a/ansible_collections/cisco/aci/plugins/modules/aci_l2out_extepg_to_contract.py b/ansible_collections/cisco/aci/plugins/modules/aci_l2out_extepg_to_contract.py index 205be3795..0ed57326f 100644 --- a/ansible_collections/cisco/aci/plugins/modules/aci_l2out_extepg_to_contract.py +++ b/ansible_collections/cisco/aci/plugins/modules/aci_l2out_extepg_to_contract.py @@ -15,7 +15,7 @@ ANSIBLE_METADATA = {"metadata_version": "1.1", "status": ["preview"], "supported DOCUMENTATION = r""" --- module: aci_l2out_extepg_to_contract -short_description: Bind Contracts to L2 External End Point Groups (EPGs) +short_description: Bind Contracts to L2 External End Point Groups (EPGs) (fv:RsCons and fv:RsProv) description: - Bind Contracts to L2 External End Point Groups (EPGs) on ACI fabrics. options: @@ -69,7 +69,7 @@ notes: The M(cisco.aci.aci_tenant), M(cisco.aci.aci_l2out) and M(cisco.aci.aci_l2out_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(l2extInstP) and B(l2extOut). + description: More information about the internal APIC classes B((fv:RsCons) B(fv:RsProv). link: https://developer.cisco.com/docs/apic-mim-ref/ author: - Sudhakar Shet Kudtarkar (@kudtarkar1) diff --git a/ansible_collections/cisco/aci/plugins/modules/aci_l2out_logical_interface_path.py b/ansible_collections/cisco/aci/plugins/modules/aci_l2out_logical_interface_path.py index 6be588bcd..0d8130139 100644 --- a/ansible_collections/cisco/aci/plugins/modules/aci_l2out_logical_interface_path.py +++ b/ansible_collections/cisco/aci/plugins/modules/aci_l2out_logical_interface_path.py @@ -12,7 +12,7 @@ ANSIBLE_METADATA = {"metadata_version": "1.1", "status": ["preview"], "supported DOCUMENTATION = r""" --- module: aci_l2out_logical_interface_path -short_description: Manage Layer 2 Outside (L2Out) logical interface path (l2extRsPathL2OutAtt) +short_description: Manage Layer 2 Outside (L2Out) logical interface path (l2ext:RsPathL2OutAtt) description: - Manage interface path entry of L2 outside node (BD extension) on Cisco ACI fabrics. options: @@ -79,7 +79,7 @@ seealso: - module: aci_l2out_logical_interface_profile - module: aci_l2out_extepg - name: APIC Management Information Model reference - description: More information about the internal APIC classes + description: More information about the internal APIC class B(l2ext:RsPathL2OutAtt). link: https://developer.cisco.com/docs/apic-mim-ref/ author: - Oleksandr Kreshchenko (@alexkross) diff --git a/ansible_collections/cisco/aci/plugins/modules/aci_l2out_logical_interface_profile.py b/ansible_collections/cisco/aci/plugins/modules/aci_l2out_logical_interface_profile.py index 93e8fd195..c1d0b3d61 100644 --- a/ansible_collections/cisco/aci/plugins/modules/aci_l2out_logical_interface_profile.py +++ b/ansible_collections/cisco/aci/plugins/modules/aci_l2out_logical_interface_profile.py @@ -55,7 +55,7 @@ seealso: - module: aci_l2out_logical_interface_path - module: aci_l2out_extepg - name: APIC Management Information Model reference - description: More information about the internal APIC classes + description: More information about the internal APIC class B(l2ext:LIfP). link: https://developer.cisco.com/docs/apic-mim-ref/ author: - Oleksandr Kreshchenko (@alexkross) diff --git a/ansible_collections/cisco/aci/plugins/modules/aci_l2out_logical_node_profile.py b/ansible_collections/cisco/aci/plugins/modules/aci_l2out_logical_node_profile.py index 12a1aa6f5..6fa04db01 100644 --- a/ansible_collections/cisco/aci/plugins/modules/aci_l2out_logical_node_profile.py +++ b/ansible_collections/cisco/aci/plugins/modules/aci_l2out_logical_node_profile.py @@ -49,7 +49,7 @@ seealso: - module: aci_l2out_logical_interface_path - module: aci_l2out_extepg - name: APIC Management Information Model reference - description: More information about the internal APIC classes + description: More information about the internal APIC class B(l2ext:LNodeP). link: https://developer.cisco.com/docs/apic-mim-ref/ author: - Oleksandr Kreshchenko (@alexkross) diff --git a/ansible_collections/cisco/aci/plugins/modules/aci_l3out.py b/ansible_collections/cisco/aci/plugins/modules/aci_l3out.py index 56f158b3d..73d51fc63 100644 --- a/ansible_collections/cisco/aci/plugins/modules/aci_l3out.py +++ b/ansible_collections/cisco/aci/plugins/modules/aci_l3out.py @@ -2,6 +2,7 @@ # -*- coding: utf-8 -*- # Copyright: (c) 2023, Gaspard Micol (@gmicol) +# Copyright: (c) 2023, Akini Ross (@akinross) # 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 @@ -34,6 +35,7 @@ options: vrf: description: - Name of the VRF being associated with the L3Out. + - SR-MPLS Infra L3out requires the VRF to be 'overlay-1'. type: str aliases: [ vrf_name ] domain: @@ -60,6 +62,8 @@ options: description: - Indicate whether MPLS (Multi-Protocol Label Switching) is enabled or not. - The APIC defaults to C(no) when unset during creation. + - SR-MPLS is only supported in APIC v5.0 and above. + - The child classes C(mplsExtP), C(mplsRsLabelPol) and C(l3extProvLbl) will be displayed in output only when C(yes). type: str choices: [ "no", "yes" ] l3protocol: @@ -70,6 +74,7 @@ options: - First example, to add BGP protocol to an l3out with OSPF protocol, the user must enter C([ bgp, ospf ]) even though "ospf" was provided before. - Second example, to change the protocol from OSPF to EIGRP, the user must simply enter C([ eigrp ]) and the previous OSPF protocol will be deleted. - To remove all existing protocols, the user must enter C([ static ]). + - SR-MPLS Infra L3out requires the l3protocol to be 'bgp'. type: list elements: str choices: [ bgp, eigrp, ospf, pim, static ] @@ -165,6 +170,7 @@ seealso: author: - Rostyslav Davydenko (@rost-d) - Gaspard Micol (@gmicol) +- Akini Ross (@akinross) """ EXAMPLES = r""" @@ -444,39 +450,17 @@ def main(): dict(l3extRsL3DomAtt=dict(attributes=dict(tDn="uni/l3dom-{0}".format(domain)))), dict(l3extRsEctx=dict(attributes=dict(tnFvCtxName=vrf))), ] - if l3protocol is not None: - l3protocol_child_configs = dict( - bgp=dict(bgpExtP=dict(attributes=dict(status="deleted"))), - eigrp=dict(eigrpExtP=dict(attributes=dict(status="deleted"))), - ospf=dict(ospfExtP=dict(attributes=dict(status="deleted"))), - pim=dict(pimExtP=dict(attributes=dict(status="deleted"))), + + if tenant == "infra" and mpls == "yes": + if l3protocol != ["bgp"] and state == "present": + module.fail_json(msg="The l3protocol parameter must be 'bgp' when tenant is 'infra' and mpls is 'yes'") + if vrf != "overlay-1" and state == "present": + module.fail_json(msg="The vrf parameter must be 'overlay-1' when tenant is 'infra' and mpls is 'yes'") + child_classes += ["mplsExtP", "mplsRsLabelPol", "l3extProvLbl"] + child_configs.append( + dict(mplsExtP=dict(attributes=dict(), children=[dict(mplsRsLabelPol=dict(attributes=dict(tDn="uni/tn-infra/mplslabelpol-default")))])) ) - for protocol in l3protocol: - if protocol == "bgp": - l3protocol_child_configs["bgp"] = dict(bgpExtP=dict(attributes=dict(descr=""))) - elif protocol == "eigrp": - l3protocol_child_configs["eigrp"] = dict(eigrpExtP=dict(attributes=dict(asn=asn))) - elif protocol == "ospf": - if isinstance(ospf, dict): - ospf["area_ctrl"] = ",".join(ospf.get("area_ctrl")) - l3protocol_child_configs["ospf"] = dict( - ospfExtP=dict( - attributes=dict( - areaCost=ospf.get("area_cost"), - areaCtrl=ospf.get("area_ctrl"), - areaId=ospf.get("area_id"), - areaType=ospf.get("area_type"), - descr=ospf.get("description"), - multipodInternal=ospf.get("multipod_internal"), - nameAlias=ospf.get("name_alias"), - ) - ) - ) - else: - l3protocol_child_configs["ospf"] = dict(ospfExtP=dict(attributes=dict(descr=""))) - elif protocol == "pim": - l3protocol_child_configs["pim"] = dict(pimExtP=dict(attributes=dict(descr=""))) - child_configs.extend(list(l3protocol_child_configs.values())) + child_configs.append(dict(l3extProvLbl=dict(attributes=dict(name=l3out)))) aci.construct_url( root_class=dict( @@ -497,6 +481,46 @@ def main(): aci.get_existing() if state == "present": + if l3protocol is not None: + if isinstance(aci.existing, list) and len(aci.existing) > 0: + for child in aci.existing[0].get("l3extOut", {}).get("children", {}): + if child.get("bgpExtP") and "bgp" not in l3protocol: + child_configs.append(dict(bgpExtP=dict(attributes=dict(status="deleted")))) + if child.get("eigrpExtP") and "eigrp" not in l3protocol: + child_configs.append(dict(eigrpExtP=dict(attributes=dict(status="deleted")))) + if child.get("ospfExtP") and "ospf" not in l3protocol: + child_configs.append(dict(ospfExtP=dict(attributes=dict(status="deleted")))) + if child.get("pimExtP") and "pim" not in l3protocol: + child_configs.append(dict(pimExtP=dict(attributes=dict(status="deleted")))) + + for protocol in l3protocol: + if protocol == "bgp": + child_configs.append(dict(bgpExtP=dict(attributes=dict(descr="")))) + elif protocol == "eigrp": + child_configs.append(dict(eigrpExtP=dict(attributes=dict(asn=asn)))) + elif protocol == "ospf": + if isinstance(ospf, dict): + ospf["area_ctrl"] = ",".join(ospf.get("area_ctrl")) + child_configs.append( + dict( + ospfExtP=dict( + attributes=dict( + areaCost=ospf.get("area_cost"), + areaCtrl=ospf.get("area_ctrl"), + areaId=ospf.get("area_id"), + areaType=ospf.get("area_type"), + descr=ospf.get("description"), + multipodInternal=ospf.get("multipod_internal"), + nameAlias=ospf.get("name_alias"), + ) + ) + ) + ) + else: + child_configs.append(dict(ospfExtP=dict(attributes=dict(descr="")))) + elif protocol == "pim": + child_configs.append(dict(pimExtP=dict(attributes=dict(descr="")))) + aci.payload( aci_class="l3extOut", class_config=dict( diff --git a/ansible_collections/cisco/aci/plugins/modules/aci_l3out_bfd_interface_profile.py b/ansible_collections/cisco/aci/plugins/modules/aci_l3out_bfd_interface_profile.py new file mode 100644 index 000000000..193ff0c1d --- /dev/null +++ b/ansible_collections/cisco/aci/plugins/modules/aci_l3out_bfd_interface_profile.py @@ -0,0 +1,367 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- + +# Copyright: (c) 2023, Anvitha Jain (@anvjain) +# 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_bfd_interface_profile +short_description: Manage L3Out BFD Interface profiles (bfd:IfP) +description: +- Manage L3Out BFD Interface profile configuration on Cisco ACI fabrics +- Only available in APIC version 5.2 or later and for non-cloud APICs +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 ] + l3out_logical_node_profile: + description: + - Name of an existing L3Out Logical Node profile + type: str + aliases: [ logical_node_profile, logical_node_profile_name ] + l3out_logical_interface_profile: + description: + - Name of an existing L3Out Logical Interface profile + type: str + aliases: [ logical_interface_profile, logical_interface_profile_name ] + name: + description: + - Name of the L3Out BFD Interface profile object + type: str + aliases: [ bfd_multihop_interface_profile ] + name_alias: + description: + - Name Alias of the L3Out BFD Interface profile object + type: str + description: + description: + - Description of the L3Out BFD Interface profile object + type: str + aliases: [ descr ] + authentication_type: + description: + - Authentication Type of the L3Out BFD Interface profile object + - APIC sets the default value to none + type: str + choices: [ none, sha1 ] + key: + description: + - Authentication Key of the L3Out BFD Interface profile object + type: str + key_id: + description: + - Authentication Key ID of the L3Out BFD Interface profile object + - APIC sets the default value to 3 + - Allowed range is 1-255 + type: int + bfd_interface_policy: + description: + - The name of the Interface policy + type: str + aliases: [ interface_policy, interface_policy_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 +- cisco.aci.annotation + +notes: +- The C(tenant), c(l3out), C(l3out_logical_node_profile) and C(l3out_logical_interface_profile) 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(bfd:IfP) + link: https://developer.cisco.com/docs/apic-mim-ref/ +- module: cisco.aci.aci_tenant +- module: cisco.aci.aci_l3out +- module: cisco.aci.aci_l3out_logical_node_profile +- module: cisco.aci.aci_l3out_logical_interface_profile +- module: cisco.aci.aci_interface_policy_bfd +author: +- Anvitha Jain (@anvjain) +""" + +EXAMPLES = r""" +- name: Add a new L3Out BFD Interface Profile + cisco.aci.aci_l3out_bfd_interface_profile: + username: admin + password: SomeSecretPassword + tenant: ansible_tenant + l3out: ansible_l3out + l3out_logical_node_profile: ansible_node_profile + l3out_logical_interface_profile: ansible_interface_profile + state: present + delegate_to: localhost + +- name: Query a new L3Out BFD Interface Profile + cisco.aci.aci_l3out_bfd_interface_profile: + username: admin + password: SomeSecretPassword + tenant: ansible_tenant + l3out: ansible_l3out + l3out_logical_node_profile: ansible_node_profile + l3out_logical_interface_profile: ansible_interface_profile + state: query + delegate_to: localhost + +- name: Query all L3Out BFD Interface Profile + cisco.aci.aci_l3out_bfd_interface_profile: + username: admin + password: SomeSecretPassword + state: query + delegate_to: localhost + +- name: Delete L3Out BFD Interface Profile + cisco.aci.aci_l3out_bfd_interface_profile: + username: admin + password: SomeSecretPassword + tenant: ansible_tenant + l3out: ansible_l3out + l3out_logical_node_profile: ansible_node_profile + l3out_logical_interface_profile: ansible_interface_profile + 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: '' + sent: + description: The actual/minimal configuration pushed to the APIC + returned: info + type: list + sample: + { + "fvTenant": { + "attributes": { + "descr": "Production environment" + } + } + } + previous: + description: The original configuration from the APIC before the module has started + returned: info + type: list + sample: + [ + { + "fvTenant": { + "attributes": { + "descr": "Production", + "dn": "uni/tn-production", + "name": "production", + "nameAlias": "", + "ownerKey": "", + "ownerTag": "" + } + } + } + ] + proposed: + description: The assembled configuration from the user-provided parameters + returned: info + type: dict + sample: + { + "fvTenant": { + "attributes": { + "descr": "Production environment", + "name": "production" + } + } + } + filter_string: + description: The filter string used for the request + returned: failure or debug + type: str + sample: ?rsp-prop-include=config-only + method: + description: The HTTP method used for the request to the APIC + returned: failure or debug + type: str + sample: POST + response: + description: The HTTP response from the APIC + returned: failure or debug + type: str + sample: OK (30 bytes) + status: + description: The HTTP status from the APIC + returned: failure or debug + type: int + sample: 200 + url: + description: The HTTP url used for the request to the APIC + returned: failure or debug + type: str + sample: https://10.11.12.13/api/mo/uni/tn-production.json + """ + +from ansible.module_utils.basic import AnsibleModule +from ansible_collections.cisco.aci.plugins.module_utils.aci import ACIModule, aci_argument_spec, aci_annotation_spec + + +def main(): + argument_spec = aci_argument_spec() + argument_spec.update(aci_annotation_spec()) + argument_spec.update( + tenant=dict(type="str", aliases=["tenant_name"]), + l3out=dict(type="str", aliases=["l3out_name"]), + l3out_logical_node_profile=dict(type="str", aliases=["logical_node_profile_name", "logical_node_profile"]), + l3out_logical_interface_profile=dict(type="str", aliases=["logical_interface_profile_name", "logical_interface_profile"]), + name=dict(type="str", aliases=["bfd_multihop_interface_profile"]), + name_alias=dict(type="str"), + description=dict(type="str", aliases=["descr"]), + authentication_type=dict(type="str", choices=["none", "sha1"]), + key=dict(type="str", no_log=True), + key_id=dict(type="int"), + bfd_interface_policy=dict(type="str", aliases=["interface_policy", "interface_policy_name"]), + state=dict(type="str", default="present", choices=["absent", "present", "query"]), + ) + + module = AnsibleModule( + argument_spec=argument_spec, + supports_check_mode=True, + required_if=[ + ["state", "absent", ["tenant", "l3out", "l3out_logical_node_profile", "l3out_logical_interface_profile"]], + ["state", "present", ["tenant", "l3out", "l3out_logical_node_profile", "l3out_logical_interface_profile", "bfd_interface_policy"]], + ["authentication_type", "sha1", ["key"]], + ], + ) + + tenant = module.params.get("tenant") + l3out = module.params.get("l3out") + l3out_logical_node_profile = module.params.get("l3out_logical_node_profile") + l3out_logical_interface_profile = module.params.get("l3out_logical_interface_profile") + name = module.params.get("name") + name_alias = module.params.get("name_alias") + description = module.params.get("description") + authentication_type = module.params.get("authentication_type") + key = module.params.get("key") + key_id = module.params.get("key_id") + bfd_interface_policy = module.params.get("bfd_interface_policy") + 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="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(l3out_logical_node_profile), + module_object=l3out_logical_node_profile, + target_filter={"name": l3out_logical_node_profile}, + ), + subclass_3=dict( + aci_class="l3extLIfP", + aci_rn="lifp-{0}".format(l3out_logical_interface_profile), + module_object=l3out_logical_interface_profile, + target_filter={"name": l3out_logical_interface_profile}, + ), + subclass_4=dict( + aci_class="bfdIfP", + aci_rn="bfdIfP", + module_object="bfdIfP", + target_filter={"name": name}, + ), + child_classes=["bfdRsIfPol"], + ) + + aci.get_existing() + + if state == "present": + child_configs = [] + class_config = dict( + name=name, + nameAlias=name_alias, + descr=description, + key=key, + type=authentication_type, + ) + + if key_id and key_id not in range(1, 255): + module.fail_json(msg='The "key_id" must be a value between 1 and 255') + else: + class_config["keyId"] = key_id + + if bfd_interface_policy is not None: + child_configs.append(dict(bfdRsIfPol=dict(attributes=dict(tnBfdIfPolName=bfd_interface_policy)))) + + aci.payload( + aci_class="bfdIfP", + class_config=class_config, + child_configs=child_configs, + ) + + aci.get_diff(aci_class="bfdIfP") + + aci.post_config() + + elif state == "absent": + aci.delete_config() + + aci.exit_json() + + +if __name__ == "__main__": + main() diff --git a/ansible_collections/cisco/aci/plugins/modules/aci_l3out_bfd_multihop_interface_profile.py b/ansible_collections/cisco/aci/plugins/modules/aci_l3out_bfd_multihop_interface_profile.py new file mode 100644 index 000000000..f7dd66c3e --- /dev/null +++ b/ansible_collections/cisco/aci/plugins/modules/aci_l3out_bfd_multihop_interface_profile.py @@ -0,0 +1,366 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- + +# Copyright: (c) 2023, Anvitha Jain (@anvjain) +# 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_bfd_multihop_interface_profile +short_description: Manage BFD Multihop Interface profiles (bfd:MhIfP) +description: +- Manage BFD Multihop Interface profile configuration on Cisco ACI fabrics +- Only available in APIC version 5.2 or later and for non-cloud APICs +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 ] + l3out_logical_node_profile: + description: + - Name of an existing L3Out Logical Node profile + type: str + aliases: [ logical_node_profile, logical_node_profile_name ] + l3out_logical_interface_profile: + description: + - Name of an existing L3Out Logical Interface profile + type: str + aliases: [ logical_interface_profile, logical_interface_profile_name ] + name: + description: + - Name of the BFD Multihop Interface Profile object + type: str + aliases: [ bfd_multihop_interface_profile ] + name_alias: + description: + - Name Alias of the BFD Multihop Interface Profile object + type: str + description: + description: + - Description of the BFD Multihop Interface Profile object + type: str + aliases: [ descr ] + authentication_type: + description: + - Authentication Type of the BFD Multihop Interface Profile object + - APIC sets the default value to none. + type: str + choices: [ none, sha1 ] + key: + description: + - Authentication Key of the BFD Multihop Interface Profile object + type: str + key_id: + description: + - Authentication Key ID of the BFD Multihop Interface Profile object + - APIC sets the default value to 3 + - Allowed range is 1-255 + type: int + bfd_multihop_interface_policy: + description: + - The name of the BFD Multihop Interface policy + type: str + aliases: [ multihop_interface_policy, multihop_interface_policy_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 +- cisco.aci.annotation + +notes: +- The C(tenant), c(l3out), C(l3out_logical_node_profile) and C(l3out_logical_interface_profile) 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(bfd:MhIfP) + link: https://developer.cisco.com/docs/apic-mim-ref/ +- module: cisco.aci.aci_tenant +- module: cisco.aci.aci_l3out +- module: cisco.aci.aci_l3out_logical_node_profile +- module: cisco.aci.aci_l3out_logical_interface_profile +- module: cisco.aci.aci_interface_policy_bfd_multihop +author: +- Anvitha Jain (@anvjain) +""" + +EXAMPLES = r""" +- name: Add a new L3Out BFD Multihop Interface Profile + cisco.aci.aci_l3out_bfd_multihop_interface_profile: + username: admin + password: SomeSecretPassword + tenant: ansible_tenant + l3out: ansible_l3out + l3out_logical_node_profile: ansible_node_profile + l3out_logical_interface_profile: ansible_interface_profile + state: present + delegate_to: localhost + +- name: Query a new L3Out BFD Multihop Interface Profile + cisco.aci.aci_l3out_bfd_multihop_interface_profile: + username: admin + password: SomeSecretPassword + tenant: ansible_tenant + l3out: ansible_l3out + l3out_logical_node_profile: ansible_node_profile + l3out_logical_interface_profile: ansible_interface_profile + state: query + delegate_to: localhost + +- name: Query all L3Out BFD Multihop Interface Profile + cisco.aci.aci_l3out_bfd_multihop_interface_profile: + username: admin + password: SomeSecretPassword + state: query + delegate_to: localhost + +- name: Delete L3Out BFD Multihop Interface Profile + cisco.aci.aci_l3out_bfd_multihop_interface_profile: + username: admin + password: SomeSecretPassword + tenant: ansible_tenant + l3out: ansible_l3out + l3out_logical_node_profile: ansible_node_profile + l3out_logical_interface_profile: ansible_interface_profile + 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: '' + sent: + description: The actual/minimal configuration pushed to the APIC + returned: info + type: list + sample: + { + "fvTenant": { + "attributes": { + "descr": "Production environment" + } + } + } + previous: + description: The original configuration from the APIC before the module has started + returned: info + type: list + sample: + [ + { + "fvTenant": { + "attributes": { + "descr": "Production", + "dn": "uni/tn-production", + "name": "production", + "nameAlias": "", + "ownerKey": "", + "ownerTag": "" + } + } + } + ] + proposed: + description: The assembled configuration from the user-provided parameters + returned: info + type: dict + sample: + { + "fvTenant": { + "attributes": { + "descr": "Production environment", + "name": "production" + } + } + } + filter_string: + description: The filter string used for the request + returned: failure or debug + type: str + sample: ?rsp-prop-include=config-only + method: + description: The HTTP method used for the request to the APIC + returned: failure or debug + type: str + sample: POST + response: + description: The HTTP response from the APIC + returned: failure or debug + type: str + sample: OK (30 bytes) + status: + description: The HTTP status from the APIC + returned: failure or debug + type: int + sample: 200 + url: + description: The HTTP url used for the request to the APIC + returned: failure or debug + type: str + sample: https://10.11.12.13/api/mo/uni/tn-production.json + """ + +from ansible.module_utils.basic import AnsibleModule +from ansible_collections.cisco.aci.plugins.module_utils.aci import ACIModule, aci_argument_spec, aci_annotation_spec + + +def main(): + argument_spec = aci_argument_spec() + argument_spec.update(aci_annotation_spec()) + argument_spec.update( + tenant=dict(type="str", aliases=["tenant_name"]), + l3out=dict(type="str", aliases=["l3out_name"]), + l3out_logical_node_profile=dict(type="str", aliases=["logical_node_profile_name", "logical_node_profile"]), + l3out_logical_interface_profile=dict(type="str", aliases=["logical_interface_profile_name", "logical_interface_profile"]), + name=dict(type="str", aliases=["bfd_multihop_interface_profile"]), + name_alias=dict(type="str"), + description=dict(type="str", aliases=["descr"]), + authentication_type=dict(type="str", choices=["none", "sha1"]), + key=dict(type="str", no_log=True), + key_id=dict(type="int"), + bfd_multihop_interface_policy=dict(type="str", aliases=["multihop_interface_policy", "multihop_interface_policy_name"]), + state=dict(type="str", default="present", choices=["absent", "present", "query"]), + ) + + module = AnsibleModule( + argument_spec=argument_spec, + supports_check_mode=True, + required_if=[ + ["state", "absent", ["tenant", "l3out", "l3out_logical_node_profile", "l3out_logical_interface_profile"]], + ["state", "present", ["tenant", "l3out", "l3out_logical_node_profile", "l3out_logical_interface_profile", "bfd_multihop_interface_policy"]], + ], + ) + + tenant = module.params.get("tenant") + l3out = module.params.get("l3out") + l3out_logical_node_profile = module.params.get("l3out_logical_node_profile") + l3out_logical_interface_profile = module.params.get("l3out_logical_interface_profile") + name = module.params.get("name") + name_alias = module.params.get("name_alias") + description = module.params.get("description") + authentication_type = module.params.get("authentication_type") + key = module.params.get("key") + key_id = module.params.get("key_id") + bfd_multihop_interface_policy = module.params.get("bfd_multihop_interface_policy") + 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="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(l3out_logical_node_profile), + module_object=l3out_logical_node_profile, + target_filter={"name": l3out_logical_node_profile}, + ), + subclass_3=dict( + aci_class="l3extLIfP", + aci_rn="lifp-{0}".format(l3out_logical_interface_profile), + module_object=l3out_logical_interface_profile, + target_filter={"name": l3out_logical_interface_profile}, + ), + subclass_4=dict( + aci_class="bfdMhIfP", + aci_rn="bfdMhIfP", + module_object="bfdMhIfP", + target_filter={"name": name}, + ), + child_classes=["bfdRsMhIfPol"], + ) + + aci.get_existing() + aci.stdout = str(aci.get_existing()) + if state == "present": + child_configs = [] + class_config = dict( + name=name, + nameAlias=name_alias, + descr=description, + type=authentication_type, + key=key, + ) + + if key_id and key_id not in range(1, 255): + module.fail_json(msg='The "key_id" must be a value between 1 and 255') + else: + class_config["keyId"] = key_id + + if bfd_multihop_interface_policy is not None: + child_configs.append(dict(bfdRsMhIfPol=dict(attributes=dict(tnBfdMhIfPolName=bfd_multihop_interface_policy)))) + + aci.payload( + aci_class="bfdMhIfP", + class_config=class_config, + child_configs=child_configs, + ) + + aci.get_diff(aci_class="bfdMhIfP") + + aci.post_config() + + elif state == "absent": + aci.delete_config() + + aci.exit_json() + + +if __name__ == "__main__": + main() diff --git a/ansible_collections/cisco/aci/plugins/modules/aci_l3out_bgp_peer.py b/ansible_collections/cisco/aci/plugins/modules/aci_l3out_bgp_peer.py index 4719c42ca..79776fdb6 100644 --- a/ansible_collections/cisco/aci/plugins/modules/aci_l3out_bgp_peer.py +++ b/ansible_collections/cisco/aci/plugins/modules/aci_l3out_bgp_peer.py @@ -16,7 +16,7 @@ ANSIBLE_METADATA = { DOCUMENTATION = r""" --- module: aci_l3out_bgp_peer -short_description: Manage Layer 3 Outside (L3Out) BGP Peers (bgp:PeerP) +short_description: Manage Layer 3 Outside (L3Out) BGP Peers (bgp:PeerP and bgp:InfraPeerP) description: - Manage L3Out BGP Peers on Cisco ACI fabrics. options: @@ -68,7 +68,7 @@ options: - BGP Controls type: list elements: str - choices: [ send-com, send-ext-com, allow-self-as, as-override, dis-peer-as-check, nh-self ] + choices: [ send-com, send-ext-com, allow-self-as, as-override, dis-peer-as-check, nh-self, send-domain-path ] peer_controls: description: - Peer Controls @@ -143,6 +143,36 @@ options: - The APIC defaults to 0 when unset during creation. type: int aliases: [ local_as_num ] + bgp_password: + description: + - Password for the BGP Peer. + type: str + description: + description: + - Description for the BGP Peer. + type: str + aliases: [ descr ] + transport_data_plane: + description: + - Transport Data Plane type. + type: str + choices: [ mpls, sr_mpls ] + bgp_peer_prefix_policy: + description: + - BGP Peer Prefix Policy. + - BGP Peer Prefix Policy is only allowed to be configured when I(bgp_infra_peer=true). + type: str + aliases: [ bgp_peer_prefix_policy_name ] + peer_type: + description: + - BGP Peer type. + type: str + choices: [ sr_mpls ] + bgp_infra_peer: + description: + - BGP Infra peer (bgp:InfraPeerP). + type: bool + aliases: [ infra ] state: description: - Use C(present) or C(absent) for adding or removing. @@ -158,10 +188,11 @@ seealso: - module: aci_l3out - module: aci_l3out_logical_node_profile - name: APIC Management Information Model reference - description: More information about the internal APIC classes B(bgp:peerP) + description: More information about the internal APIC classes B(bgp:peerP) and B(bgp:InfraPeerP) link: https://developer.cisco.com/docs/apic-mim-ref/ author: - Tim Cragg (@timcragg) +- Akini Ross (@akinross) """ EXAMPLES = r""" @@ -215,6 +246,28 @@ EXAMPLES = r""" state: present delegate_to: localhost +- name: Create Infra BGP Peer with password + aci_l3out_bgp_peer: &infra_bgp_peer + host: apic + username: admin + password: SomeSecretPassword + tenant: infra + l3out: ansible_infra_l3out + node_profile: ansible_infra_l3out_node_profile + ttl: 2 + bgp_infra_peer: true + bgp_password: ansible_test_password + peer_ip: 192.168.50.2 + remote_asn: 65450 + local_as_number: 65460 + peer_type: sr_mpls + bgp_controls: + - send-domain-path + transport_data_plane: sr_mpls + bgp_peer_prefix_policy: ansible_peer_prefix_profile + state: present + delegate_to: localhost + - name: Shutdown a BGP peer cisco.aci.aci_l3out_bgp_peer: host: apic @@ -266,6 +319,7 @@ EXAMPLES = r""" direction: "export" l3out: "anstest_l3out" state: present + delegate_to: localhost - name: Query a BGP peer cisco.aci.aci_l3out_bgp_peer: @@ -293,6 +347,15 @@ EXAMPLES = r""" delegate_to: localhost register: query_all +- name: Query all BGP infra peer + cisco.aci.aci_l3out_bgp_peer: + host: apic + username: admin + password: SomeSecretPassword + bgp_infra_peer: true + state: query + delegate_to: localhost + register: query_all """ RETURN = r""" @@ -416,6 +479,7 @@ def main(): argument_spec.update( tenant=dict(type="str", aliases=["tenant_name"]), l3out=dict(type="str", aliases=["l3out_name"]), + description=dict(type="str", aliases=["descr"]), node_profile=dict(type="str", aliases=["node_profile_name", "logical_node"]), interface_profile=dict(type="str", aliases=["interface_profile_name", "logical_interface"]), state=dict(type="str", default="present", choices=["absent", "present", "query"]), @@ -434,6 +498,7 @@ def main(): "as-override", "dis-peer-as-check", "nh-self", + "send-domain-path", ], ), peer_controls=dict(type="list", elements="str", choices=["bfd", "dis-conn-check"]), @@ -454,6 +519,11 @@ def main(): ), local_as_number_config=dict(type="str", choices=["dual-as", "no-prepend", "none", "replace-as"], aliases=["local_as_num_config"]), local_as_number=dict(type="int", aliases=["local_as_num"]), + bgp_password=dict(type="str", no_log=True), + transport_data_plane=dict(type="str", choices=["mpls", "sr_mpls"]), + bgp_peer_prefix_policy=dict(type="str", aliases=["bgp_peer_prefix_policy_name"]), + peer_type=dict(type="str", choices=["sr_mpls"]), + bgp_infra_peer=dict(type="bool", aliases=["infra"]), ) module = AnsibleModule( @@ -468,6 +538,7 @@ def main(): tenant = module.params.get("tenant") l3out = module.params.get("l3out") + description = module.params.get("description") node_profile = module.params.get("node_profile") interface_profile = module.params.get("interface_profile") state = module.params.get("state") @@ -487,6 +558,11 @@ def main(): route_control_profiles = module.params.get("route_control_profiles") local_as_number_config = module.params.get("local_as_number_config") local_as_number = module.params.get("local_as_number") + bgp_password = module.params.get("bgp_password") + transport_data_plane = module.params.get("transport_data_plane") + peer_type = module.params.get("peer_type") + bgp_infra_peer = module.params.get("bgp_infra_peer") + bgp_peer_prefix_policy = module.params.get("bgp_peer_prefix_policy") aci = ACIModule(module) if node_id: @@ -499,24 +575,23 @@ def main(): child_configs = [] child_classes = ["bgpRsPeerPfxPol", "bgpAsP", "bgpLocalAsnP"] + aci_class = "bgpInfraPeerP" if bgp_infra_peer else "bgpPeerP" - if remote_asn: - child_configs.append( - dict( - bgpAsP=dict( - attributes=dict(asn=remote_asn), - ), - ) - ) + if remote_asn is not None: + bgp_as_p = dict(bgpAsP=dict(attributes=dict(asn=remote_asn))) + if remote_asn == 0: + bgp_as_p["bgpAsP"]["attributes"]["status"] = "deleted" + child_configs.append(bgp_as_p) - if local_as_number_config or local_as_number: - child_configs.append( - dict( - bgpLocalAsnP=dict( - attributes=dict(asnPropagate=local_as_number_config, localAsn=local_as_number), - ), - ) - ) + if local_as_number_config is not None or local_as_number is not None: + bgp_local_asn_p = dict(bgpLocalAsnP=dict(attributes=dict(asnPropagate=local_as_number_config, localAsn=local_as_number))) + if local_as_number == 0: + bgp_local_asn_p["bgpLocalAsnP"]["attributes"]["status"] = "deleted" + child_configs.append(bgp_local_asn_p) + + # BGP Peer Prefix Policy is ony configurable on Infra BGP Peer Profile + if bgp_peer_prefix_policy is not None: + child_configs.append(dict(bgpRsPeerPfxPol=dict(attributes=dict(tnBgpPeerPfxPolName=bgp_peer_prefix_policy)))) if route_control_profiles: child_classes.append("bgpRsPeerToProfile") @@ -541,8 +616,8 @@ def main(): ) bgp_peer_profile_dict = dict( - aci_class="bgpPeerP", - aci_rn="peerP-[{0}]".format(peer_ip), + aci_class=aci_class, + aci_rn="infraPeerP-[{0}]".format(peer_ip) if bgp_infra_peer else "peerP-{0}".format(peer_ip), module_object=peer_ip, target_filter={"addr": peer_ip}, ) @@ -594,32 +669,46 @@ def main(): aci.get_existing() if state == "present": - ctrl, peerCtrl, addrTCtrl, privateASctrl = None, None, None, None + ctrl, ctrl_ext, peerCtrl, addrTCtrl, privateASctrl = None, None, None, None, None if bgp_controls: + if transport_data_plane == "mpls": + bgp_controls.append("segment-routing-disable") + + if "send-domain-path" in bgp_controls: + ctrl_ext = "send-domain-path" + bgp_controls.remove("send-domain-path") + ctrl = ",".join(bgp_controls) + if peer_controls: peerCtrl = ",".join(peer_controls) if address_type_controls: addrTCtrl = ",".join(address_type_controls) if private_asn_controls: privateASctrl = ",".join(private_asn_controls) - aci.payload( - aci_class="bgpPeerP", - class_config=dict( - addr=peer_ip, - ctrl=ctrl, - peerCtrl=peerCtrl, - addrTCtrl=addrTCtrl, - privateASctrl=privateASctrl, - ttl=ttl, - weight=weight, - adminSt=admin_state, - allowedSelfAsCnt=allow_self_as_count, - ), - child_configs=child_configs, + + class_config = dict( + descr=description, + addr=peer_ip, + ctrl=ctrl, + ctrlExt=ctrl_ext, + peerCtrl=peerCtrl, + addrTCtrl=addrTCtrl, + privateASctrl=privateASctrl, + ttl=ttl, + weight=weight, + adminSt=admin_state, + allowedSelfAsCnt=allow_self_as_count, + peerT=peer_type.replace("_", "-") if peer_type else None, ) - aci.get_diff(aci_class="bgpPeerP") + # Only add bgp_password if it is set to handle changed status properly because password is not part of existing config + if bgp_password: + class_config["password"] = bgp_password + + aci.payload(aci_class=aci_class, class_config=class_config, child_configs=child_configs) + + aci.get_diff(aci_class=aci_class) aci.post_config() diff --git a/ansible_collections/cisco/aci/plugins/modules/aci_l3out_dhcp_relay_label.py b/ansible_collections/cisco/aci/plugins/modules/aci_l3out_dhcp_relay_label.py new file mode 100644 index 000000000..3b9885c23 --- /dev/null +++ b/ansible_collections/cisco/aci/plugins/modules/aci_l3out_dhcp_relay_label.py @@ -0,0 +1,354 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- + +# Copyright: (c) 2023, Gaspard Micol (@gmicol) +# 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_dhcp_relay_label +short_description: Manage Layer 3 Outside (L3Out) DHCP Relay Label (dhcp:Lbl) +description: +- Manage DHCP Relay Labels for L3Out Logical Interface Profiles on Cisco ACI fabrics. +- A DHCP Relay Label contains the name of an existing DHCP Relay Policy for the label, + the scope, and a DHCP Option Policy. +options: + tenant: + description: + - The name of an existing tenant. + type: str + aliases: [ tenant_name ] + l3out: + description: + - The name of an existing L3Out. + type: str + aliases: [ l3out_name ] + node_profile: + description: + - The name of an existing node profile. + type: str + aliases: [ node_profile_name, logical_node ] + interface_profile: + description: + - The name of an existing interface profile. + type: str + aliases: [ interface_profile_name, logical_interface ] + dhcp_relay_label: + description: + - The name/label of an existing DHCP Relay Policy. + type: str + aliases: [ name, relay_policy ] + scope: + description: + - The scope is the owner of the relay server. + - The APIC defaults to C(infra) when unset during creation. + type: str + choices: [ infra, tenant ] + aliases: [ owner ] + dhcp_option_policy: + description: + - The name of an existing DHCP Option Policy to be associated with the DCHP Relay Policy. + - The DHCP option policy supplies DHCP clients with configuration parameters + such as domain, nameserver, and subnet router addresses. + - Passing an empty string will delete the current linked DHCP Option Policy. + However, this will associate the DHCP Relay Label to the default DHCP Option Policy + from the common Tenant. + type: str + aliases: [ dhcp_option_policy_name ] + description: + description: + - The description of the DHCP Relay Label. + 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 +extends_documentation_fragment: +- cisco.aci.aci +- cisco.aci.annotation +- cisco.aci.owner + +notes: +- The C(tenant), C(l3out), C(node_profile), C(interface_profile) and C(relay_policy) must exist before using this module in your playbook. + The M(cisco.aci.aci_tenant), M(cisco.aci.aci_l3out), M(cisco.aci.aci_l3out_logical_node_profile), M(cisco.aci.aci_l3out_logical_interface_profile) + and M(cisco.aci.aci_dhcp_relay) can be used for this. +- If C(dhcp_option_policy) is used, it must exist before using this module in your playbook. + The M(cisco.aci.aci_dhcp_option_policy) can be used for this. +seealso: +- module: cisco.aci.aci_tenant +- module: cisco.aci.aci_l3out +- module: cisco.aci.aci_l3out_logical_node_profile +- module: cisco.aci.aci_l3out_logical_interface_profile +- module: cisco.aci.aci_dhcp_relay +- module: cisco.aci.aci_dhcp_option_policy +- name: APIC Management Information Model reference + description: More information about the internal APIC classes + link: https://developer.cisco.com/docs/apic-mim-ref/ +author: +- Gaspard Micol (@gmicol) +""" + +EXAMPLES = r""" +- name: Add a new L3Out DHCP Relay Label + cisco.aci.aci_l3out_eigrp_interface_profile: + host: apic + username: admin + password: SomeSecretPassword + tenant: my_tenant + l3out: my_l3out + node_profile: my_node_profile + interface_profile: my_interface_profile + dhcp_relay_label: my_dhcp_relay_label + scope: tenant + dhcp_option_policy: my_dhcp_option_policy + state: present + delegate_to: localhost + +- name: Delete an L3Out DHCP Relay Label + cisco.aci.aci_l3out_eigrp_interface_profile: + host: apic + username: admin + password: SomeSecretPassword + tenant: my_tenant + l3out: my_l3out + node_profile: my_node_profile + interface_profile: my_interface_profile + dhcp_relay_label: my_dhcp_relay_label + state: absent + delegate_to: localhost + +- name: Query an L3Out DHCP Relay Label + cisco.aci.aci_l3out_eigrp_interface_profile: + host: apic + username: admin + password: SomeSecretPassword + tenant: my_tenant + l3out: my_l3out + node_profile: my_node_profile + interface_profile: my_interface_profile + dhcp_relay_label: my_dhcp_relay_label + state: query + delegate_to: localhost + register: query_result +""" + +RETURN = r""" +current: + description: The existing configuration from the APIC after the module has finished + returned: success + type: list + sample: + [ + { + "fvTenant": { + "attributes": { + "descr": "Production environment", + "dn": "uni/tn-production", + "name": "production", + "nameAlias": "", + "ownerKey": "", + "ownerTag": "" + } + } + } + ] +error: + description: The error information as returned from the APIC + returned: failure + type: dict + sample: + { + "code": "122", + "text": "unknown managed object class foo" + } +raw: + description: The raw output returned by the APIC REST API (xml or json) + returned: parse error + type: str + sample: '' +sent: + description: The actual/minimal configuration pushed to the APIC + returned: info + type: list + sample: + { + "fvTenant": { + "attributes": { + "descr": "Production environment" + } + } + } +previous: + description: The original configuration from the APIC before the module has started + returned: info + type: list + sample: + [ + { + "fvTenant": { + "attributes": { + "descr": "Production", + "dn": "uni/tn-production", + "name": "production", + "nameAlias": "", + "ownerKey": "", + "ownerTag": "" + } + } + } + ] +proposed: + description: The assembled configuration from the user-provided parameters + returned: info + type: dict + sample: + { + "fvTenant": { + "attributes": { + "descr": "Production environment", + "name": "production" + } + } + } +filter_string: + description: The filter string used for the request + returned: failure or debug + type: str + sample: ?rsp-prop-include=config-only +method: + description: The HTTP method used for the request to the APIC + returned: failure or debug + type: str + sample: POST +response: + description: The HTTP response from the APIC + returned: failure or debug + type: str + sample: OK (30 bytes) +status: + description: The HTTP status from the APIC + returned: failure or debug + type: int + sample: 200 +url: + description: The HTTP url used for the request to the APIC + returned: failure or debug + type: str + sample: https://10.11.12.13/api/mo/uni/tn-production.json +""" + + +from ansible.module_utils.basic import AnsibleModule +from ansible_collections.cisco.aci.plugins.module_utils.aci import ACIModule, aci_argument_spec, aci_annotation_spec, aci_owner_spec + + +def main(): + argument_spec = aci_argument_spec() + argument_spec.update(aci_annotation_spec()) + argument_spec.update(aci_owner_spec()) + argument_spec.update( + tenant=dict(type="str", aliases=["tenant_name"]), + l3out=dict(type="str", aliases=["l3out_name"]), + node_profile=dict(type="str", aliases=["node_profile_name", "logical_node"]), + interface_profile=dict(type="str", aliases=["interface_profile_name", "logical_interface"]), + dhcp_relay_label=dict(type="str", aliases=["name", "relay_policy"]), + scope=dict(type="str", choices=["infra", "tenant"], aliases=["owner"]), + dhcp_option_policy=dict(type="str", aliases=["dhcp_option_policy_name"]), + description=dict(type="str", aliases=["descr"]), + state=dict(type="str", default="present", choices=["absent", "present", "query"]), + ) + + module = AnsibleModule( + argument_spec=argument_spec, + supports_check_mode=True, + required_if=[ + ["state", "absent", ["tenant", "l3out", "node_profile", "interface_profile", "dhcp_relay_label"]], + ["state", "present", ["tenant", "l3out", "node_profile", "interface_profile", "dhcp_relay_label"]], + ], + ) + + tenant = module.params.get("tenant") + l3out = module.params.get("l3out") + node_profile = module.params.get("node_profile") + interface_profile = module.params.get("interface_profile") + dhcp_relay_label = module.params.get("dhcp_relay_label") + scope = module.params.get("scope") + dhcp_option_policy = module.params.get("dhcp_option_policy") + description = module.params.get("description") + state = module.params.get("state") + + aci = ACIModule(module) + + child_classes = ["dhcpRsDhcpOptionPol"] + + 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(node_profile), + module_object=node_profile, + target_filter={"name": node_profile}, + ), + subclass_3=dict( + aci_class="l3extLIfP", + aci_rn="lifp-[{0}]".format(interface_profile), + module_object=interface_profile, + target_filter={"name": interface_profile}, + ), + subclass_4=dict( + aci_class="dhcpLbl", + aci_rn="dhcplbl-[{0}]".format(dhcp_relay_label), + module_object=dhcp_relay_label, + target_filter={"name": dhcp_relay_label}, + ), + child_classes=child_classes, + ) + + aci.get_existing() + + if state == "present": + child_configs = [dict(dhcpRsDhcpOptionPol=dict(attributes=dict(tnDhcpOptionPolName=dhcp_option_policy)))] + + aci.payload( + aci_class="dhcpLbl", + class_config=dict( + descr=description, + name=dhcp_relay_label, + owner=scope, + ), + child_configs=child_configs, + ) + + 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/ansible_collections/cisco/aci/plugins/modules/aci_l3out_eigrp_interface_profile.py b/ansible_collections/cisco/aci/plugins/modules/aci_l3out_eigrp_interface_profile.py new file mode 100644 index 000000000..d1359e500 --- /dev/null +++ b/ansible_collections/cisco/aci/plugins/modules/aci_l3out_eigrp_interface_profile.py @@ -0,0 +1,392 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- + +# Copyright: (c) 2023, Gaspard Micol (@gmicol) +# 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_eigrp_interface_profile +short_description: Manage Layer 3 Outside (L3Out) EIGRP interface profile (eigrp:IfP) +description: +- Manage L3Out logical interface profile EIGRP policies on Cisco ACI fabrics. +options: + tenant: + description: + - The name of an existing tenant. + type: str + aliases: [ tenant_name ] + l3out: + description: + - The name of an existing L3Out. + type: str + aliases: [ l3out_name ] + node_profile: + description: + - The name of the node profile. + type: str + aliases: [ node_profile_name, logical_node ] + interface_profile: + description: + - The name of an existing interface profile. + type: str + aliases: [ interface_profile_name, logical_interface ] + eigrp_policy: + description: + - The name of an existing EIGRP interface policy. + type: str + aliases: [ name, eigrp_policy_name ] + eigrp_keychain_policy: + description: + - The name of an existing EIGRP keychain policy. + - Pass an empty string to disable Authentification. + type: str + aliases: [ keychain_policy, keychain_policy_name ] + description: + description: + - The description of the EIGRP 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 +extends_documentation_fragment: +- cisco.aci.aci +- cisco.aci.annotation +- cisco.aci.owner + +notes: +- The C(tenant), C(l3out), C(node_profile), C(interface_profile) and C(eigrp_policy) must exist before using this module in your playbook. + The M(cisco.aci.aci_tenant), M(cisco.aci.aci_l3out), M(cisco.aci.aci_l3out_logical_node_profile), M(cisco.aci.aci_l3out_logical_interface_profile) + and M(cisco.aci.aci_interface_policy_eigrp) can be used for this. +- if C(eigrp_keychain_policy) is used, it must exist before using this module in your playbook. + The M(cisco.aci.aci_keychain_policy) can be used for this. +seealso: +- module: cisco.aci.aci_tenant +- module: cisco.aci.aci_l3out +- module: cisco.aci.aci_l3out_logical_node_profile +- module: cisco.aci.aci_l3out_logical_interface_profile +- module: cisco.aci.aci_interface_policy_eigrp +- module: cisco.aci.aci_keychain_policy +- name: APIC Management Information Model reference + description: More information about the internal APIC classes + link: https://developer.cisco.com/docs/apic-mim-ref/ +author: +- Gaspard Micol (@gmicol) +""" + +EXAMPLES = r""" +- name: Add a new interface profile EIGRP policy + cisco.aci.aci_l3out_eigrp_interface_profile: + host: apic + username: admin + password: SomeSecretPassword + tenant: my_tenant + l3out: my_l3out + node_profile: my_node_profile + interface_profile: my_interface_profile + eigrp_policy: my_eigrp_interface_policy + state: present + delegate_to: localhost + +- name: Add a new interface profile EIGRP policy with authentication + cisco.aci.aci_l3out_eigrp_interface_profile: + host: apic + username: admin + password: SomeSecretPassword + tenant: my_tenant + l3out: my_l3out + node_profile: my_node_profile + interface_profile: my_interface_profile + eigrp_policy: my_eigrp_interface_policy + eigrp_keychain_policy: my_keychain_policy + state: present + delegate_to: localhost + +- name: Disable authentification from an interface profile EIGRP policy + cisco.aci.aci_l3out_eigrp_interface_profile: + host: apic + username: admin + password: SomeSecretPassword + tenant: my_tenant + l3out: my_l3out + node_profile: my_node_profile + interface_profile: my_interface_profile + eigrp_policy: my_eigrp_interface_policy + eigrp_keychain_policy: "" + state: present + delegate_to: localhost + +- name: Delete an interface profile EIGRP policy + cisco.aci.aci_l3out_eigrp_interface_profile: + host: apic + username: admin + password: SomeSecretPassword + tenant: my_tenant + l3out: my_l3out + node_profile: my_node_profile + interface_profile: my_interface_profile + eigrp_policy: my_eigrp_interface_policy + state: absent + delegate_to: localhost + +- name: Query an interface profile EIGRP policy + cisco.aci.aci_l3out_eigrp_interface_profile: + host: apic + username: admin + password: SomeSecretPassword + tenant: my_tenant + l3out: my_l3out + node_profile: my_node_profile + interface_profile: my_interface_profile + eigrp_policy: my_eigrp_interface_policy + state: query + delegate_to: localhost + register: query_result +""" + +RETURN = r""" +current: + description: The existing configuration from the APIC after the module has finished + returned: success + type: list + sample: + [ + { + "fvTenant": { + "attributes": { + "descr": "Production environment", + "dn": "uni/tn-production", + "name": "production", + "nameAlias": "", + "ownerKey": "", + "ownerTag": "" + } + } + } + ] +error: + description: The error information as returned from the APIC + returned: failure + type: dict + sample: + { + "code": "122", + "text": "unknown managed object class foo" + } +raw: + description: The raw output returned by the APIC REST API (xml or json) + returned: parse error + type: str + sample: '' +sent: + description: The actual/minimal configuration pushed to the APIC + returned: info + type: list + sample: + { + "fvTenant": { + "attributes": { + "descr": "Production environment" + } + } + } +previous: + description: The original configuration from the APIC before the module has started + returned: info + type: list + sample: + [ + { + "fvTenant": { + "attributes": { + "descr": "Production", + "dn": "uni/tn-production", + "name": "production", + "nameAlias": "", + "ownerKey": "", + "ownerTag": "" + } + } + } + ] +proposed: + description: The assembled configuration from the user-provided parameters + returned: info + type: dict + sample: + { + "fvTenant": { + "attributes": { + "descr": "Production environment", + "name": "production" + } + } + } +filter_string: + description: The filter string used for the request + returned: failure or debug + type: str + sample: ?rsp-prop-include=config-only +method: + description: The HTTP method used for the request to the APIC + returned: failure or debug + type: str + sample: POST +response: + description: The HTTP response from the APIC + returned: failure or debug + type: str + sample: OK (30 bytes) +status: + description: The HTTP status from the APIC + returned: failure or debug + type: int + sample: 200 +url: + description: The HTTP url used for the request to the APIC + returned: failure or debug + type: str + sample: https://10.11.12.13/api/mo/uni/tn-production.json +""" + + +from ansible.module_utils.basic import AnsibleModule +from ansible_collections.cisco.aci.plugins.module_utils.aci import ACIModule, aci_argument_spec, aci_annotation_spec, aci_owner_spec + + +def main(): + argument_spec = aci_argument_spec() + argument_spec.update(aci_annotation_spec()) + argument_spec.update(aci_owner_spec()) + argument_spec.update( + tenant=dict(type="str", aliases=["tenant_name"]), + l3out=dict(type="str", aliases=["l3out_name"]), + node_profile=dict(type="str", aliases=["node_profile_name", "logical_node"]), + interface_profile=dict(type="str", aliases=["interface_profile_name", "logical_interface"]), + eigrp_policy=dict(type="str", aliases=["name", "eigrp_policy_name"]), + eigrp_keychain_policy=dict(type="str", aliases=["keychain_policy", "keychain_policy_name"], no_log=False), + description=dict(type="str", aliases=["descr"]), + state=dict(type="str", default="present", choices=["absent", "present", "query"]), + ) + + module = AnsibleModule( + argument_spec=argument_spec, + supports_check_mode=True, + required_if=[ + ["state", "absent", ["tenant", "l3out", "node_profile", "interface_profile"]], + ["state", "present", ["tenant", "l3out", "node_profile", "interface_profile", "eigrp_policy"]], + ], + ) + + tenant = module.params.get("tenant") + l3out = module.params.get("l3out") + node_profile = module.params.get("node_profile") + interface_profile = module.params.get("interface_profile") + eigrp_policy = module.params.get("eigrp_policy") + eigrp_keychain_policy = module.params.get("eigrp_keychain_policy") + description = module.params.get("description") + state = module.params.get("state") + + aci = ACIModule(module) + + child_classes = ["eigrpRsIfPol", "eigrpAuthIfP"] + + 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(node_profile), + module_object=node_profile, + target_filter={"name": node_profile}, + ), + subclass_3=dict( + aci_class="l3extLIfP", + aci_rn="lifp-[{0}]".format(interface_profile), + module_object=interface_profile, + target_filter={"name": interface_profile}, + ), + subclass_4=dict( + aci_class="eigrpIfP", + aci_rn="eigrpIfP", + module_object=interface_profile, + target_filter={"name": interface_profile}, + ), + child_classes=child_classes, + ) + + aci.get_existing() + + if state == "present": + child_configs = [dict(eigrpRsIfPol=dict(attributes=dict(tnEigrpIfPolName=eigrp_policy)))] + + if eigrp_keychain_policy is not None: + if eigrp_keychain_policy == "" and isinstance(aci.existing, list) and len(aci.existing) > 0: + for child in aci.existing[0].get("eigrpIfP", {}).get("children", {}): + if child.get("eigrpAuthIfP"): + child_configs.append( + dict( + eigrpAuthIfP=dict( + attributes=dict(status="deleted"), + ), + ) + ) + elif eigrp_keychain_policy != "": + child_configs.append( + dict( + eigrpAuthIfP=dict( + attributes=dict(), + children=[ + dict( + eigrpRsKeyChainPol=dict( + attributes=dict( + tnFvKeyChainPolName=eigrp_keychain_policy, + ), + ) + ) + ], + ) + ) + ) + + aci.payload( + aci_class="eigrpIfP", + class_config=dict( + descr=description, + ), + child_configs=child_configs, + ) + + aci.get_diff(aci_class="eigrpIfP") + + aci.post_config() + + elif state == "absent": + aci.delete_config() + + aci.exit_json() + + +if __name__ == "__main__": + main() diff --git a/ansible_collections/cisco/aci/plugins/modules/aci_l3out_extepg.py b/ansible_collections/cisco/aci/plugins/modules/aci_l3out_extepg.py index acaa7ea9e..3180e6752 100644 --- a/ansible_collections/cisco/aci/plugins/modules/aci_l3out_extepg.py +++ b/ansible_collections/cisco/aci/plugins/modules/aci_l3out_extepg.py @@ -14,7 +14,7 @@ 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) +- Manage External Network Instance Profile (ExtEpg) objects. options: tenant: description: @@ -104,7 +104,7 @@ seealso: - 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). + description: More information about the internal APIC class B(l3extInstP:instP). link: https://developer.cisco.com/docs/apic-mim-ref/ author: - Rostyslav Davydenko (@rost-d) diff --git a/ansible_collections/cisco/aci/plugins/modules/aci_l3out_extepg_to_contract.py b/ansible_collections/cisco/aci/plugins/modules/aci_l3out_extepg_to_contract.py index ba5df29c5..eb9f6da17 100644 --- a/ansible_collections/cisco/aci/plugins/modules/aci_l3out_extepg_to_contract.py +++ b/ansible_collections/cisco/aci/plugins/modules/aci_l3out_extepg_to_contract.py @@ -3,6 +3,7 @@ # Copyright: (c) 2020, Sudhakar Shet Kudtarkar (@kudtarkar1) # Copyright: (c) 2020, Shreyas Srish +# Copyright: (c) 2023, Akini Ross (@akinross) # 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 @@ -14,7 +15,7 @@ ANSIBLE_METADATA = {"metadata_version": "1.1", "status": ["preview"], "supported DOCUMENTATION = r""" --- module: aci_l3out_extepg_to_contract -short_description: Bind Contracts to External End Point Groups (EPGs) +short_description: Bind Contracts to External End Point Groups (EPGs) (fv:RsCons, fv:RsProv, fv:RsProtBy, fv:RsConsIf, and fv:RsIntraEpg) description: - Bind Contracts to External End Point Groups (EPGs) on ACI fabrics. options: @@ -26,32 +27,43 @@ options: description: - Name of the l3out. type: str - aliases: ['l3out_name'] + aliases: [ l3out_name ] extepg: description: - Name of the external end point group. type: str - aliases: ['extepg_name', 'external_epg'] + aliases: [ extepg_name, external_epg] contract: description: - - Name of the contract. + - The name of the contract or contract interface. type: str + aliases: [ contract_name, contract_interface ] contract_type: description: - - The type of contract. + - Determines the type of the Contract. type: str required: true - choices: ['consumer', 'provider'] + choices: [ consumer, provider, taboo, interface, intra_epg ] priority: description: - - This has four levels of priority. + - QoS class. + - The APIC defaults to C(unspecified) when unset during creation. type: str - choices: ['level1', 'level2', 'level3', 'unspecified'] + choices: [ level1, level2, level3, level4, level5, level6, unspecified ] provider_match: description: - - This is configurable for provided contracts. + - 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 ] + contract_label: + description: + - Contract label to match. + type: str + subject_label: + description: + - Subject label to match. type: str - choices: ['all', 'at_least_one', 'at_most_one', 'none'] state: description: - Use C(present) or C(absent) for adding or removing. @@ -64,15 +76,16 @@ extends_documentation_fragment: - cisco.aci.annotation 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. +- The C(tenant), C(l3out), C(extepg), and C(Contract) must exist before using this module in your playbook. + The M(cisco.aci.aci_tenant), M(cisco.aci.aci_l3out), M(cisco.aci.aci_l3out_extepg), and M(cisco.aci.aci_contract) 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). + description: More information about the internal APIC class B(fv:RsCons), B(fv:RsProv), B(fv:RsProtBy, B(fv:RsConsIf, and B(fv:RsIntraEpg). link: https://developer.cisco.com/docs/apic-mim-ref/ author: - Sudhakar Shet Kudtarkar (@kudtarkar1) - Shreyas Srish (@shrsr) +- Akini Ross (@akinross) """ EXAMPLES = r""" @@ -234,38 +247,23 @@ RETURN = r""" from ansible.module_utils.basic import AnsibleModule from ansible_collections.cisco.aci.plugins.module_utils.aci import ACIModule, aci_argument_spec, aci_annotation_spec - -ACI_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", -) +from ansible_collections.cisco.aci.plugins.module_utils.constants import ACI_CLASS_MAPPING, CONTRACT_LABEL_MAPPING, PROVIDER_MATCH_MAPPING, SUBJ_LABEL_MAPPING def main(): argument_spec = aci_argument_spec() argument_spec.update(aci_annotation_spec()) argument_spec.update( - contract_type=dict(type="str", required=True, choices=["consumer", "provider"]), + contract_type=dict(type="str", required=True, choices=["consumer", "provider", "taboo", "interface", "intra_epg"]), l3out=dict(type="str", aliases=["l3out_name"]), - contract=dict(type="str"), - priority=dict(type="str", choices=["level1", "level2", "level3", "unspecified"]), + contract=dict(type="str", aliases=["contract_name", "contract_interface"]), # Not required for querying all objects + priority=dict(type="str", choices=["level1", "level2", "level3", "level4", "level5", "level6", "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"]), + contract_label=dict(type="str"), + subject_label=dict(type="str"), ) module = AnsibleModule( argument_spec=argument_spec, @@ -286,13 +284,25 @@ def main(): provider_match = PROVIDER_MATCH_MAPPING.get(provider_match) state = module.params.get("state") tenant = module.params.get("tenant") + contract_label = module.params.get("contract_label") + subject_label = module.params.get("subject_label") - aci_class = ACI_CLASS_MAPPING.get(contract_type)["class"] - aci_rn = ACI_CLASS_MAPPING.get(contract_type)["rn"] + aci_class = ACI_CLASS_MAPPING[contract_type]["class"] + aci_rn = ACI_CLASS_MAPPING[contract_type]["rn"] + aci_name = ACI_CLASS_MAPPING[contract_type]["name"] + child_classes = [] - if contract_type == "consumer" and provider_match is not None: + if contract_type != "provider" and provider_match is not None: module.fail_json(msg="the 'provider_match' is only configurable for Provided Contracts") + if contract_type in ["taboo", "interface", "intra_epg"] and (contract_label is not None or subject_label is not None): + module.fail_json(msg="the 'contract_label' and 'subject_label' are not configurable for {0} contracts".format(contract_type)) + + if contract_type not in ["taboo", "interface", "intra_epg"]: + contract_label_class = CONTRACT_LABEL_MAPPING.get(contract_type) + subject_label_class = SUBJ_LABEL_MAPPING.get(contract_type) + child_classes = [subject_label_class, contract_label_class] + aci = ACIModule(module) aci.construct_url( root_class=dict( @@ -317,20 +327,23 @@ def main(): aci_class=aci_class, aci_rn="{0}{1}".format(aci_rn, contract), module_object=contract, - target_filter={"tnVzBrCPName": contract}, + target_filter={aci_name: contract}, ), + child_classes=child_classes, ) aci.get_existing() if state == "present": + child_configs = [] + if contract_label is not None: + child_configs.append({contract_label_class: {"attributes": {"name": contract_label}}}) + if subject_label is not None: + child_configs.append({subject_label_class: {"attributes": {"name": subject_label}}}) aci.payload( aci_class=aci_class, - class_config=dict( - matchT=provider_match, - prio=priority, - tnVzBrCPName=contract, - ), + class_config={"matchT": provider_match, "prio": priority, aci_name: contract}, + child_configs=child_configs, ) aci.get_diff(aci_class=aci_class) diff --git a/ansible_collections/cisco/aci/plugins/modules/aci_l3out_extsubnet.py b/ansible_collections/cisco/aci/plugins/modules/aci_l3out_extsubnet.py index 6ecb3b27c..9d94ee44f 100644 --- a/ansible_collections/cisco/aci/plugins/modules/aci_l3out_extsubnet.py +++ b/ansible_collections/cisco/aci/plugins/modules/aci_l3out_extsubnet.py @@ -12,9 +12,9 @@ ANSIBLE_METADATA = {"metadata_version": "1.1", "status": ["preview"], "supported DOCUMENTATION = r""" --- module: aci_l3out_extsubnet -short_description: Manage External Subnet objects (l3extSubnet:extsubnet) +short_description: Manage External Subnet objects (l3ext:Subnet) description: -- Manage External Subnet objects (l3extSubnet:extsubnet) +- Manage External Subnet objects. options: tenant: description: @@ -99,7 +99,7 @@ seealso: - 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). + description: More information about the internal APIC class B(l3ext:Subnet). link: https://developer.cisco.com/docs/apic-mim-ref/ author: - Rostyslav Davydenko (@rost-d) diff --git a/ansible_collections/cisco/aci/plugins/modules/aci_l3out_floating_svi.py b/ansible_collections/cisco/aci/plugins/modules/aci_l3out_floating_svi.py new file mode 100644 index 000000000..b0e3ca7e3 --- /dev/null +++ b/ansible_collections/cisco/aci/plugins/modules/aci_l3out_floating_svi.py @@ -0,0 +1,475 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- + +# Copyright: (c) 2023, Shreyas Srish +# 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_floating_svi +short_description: Manage Layer 3 Outside (L3Out) interfaces (l3ext:VirtualLIfP) +description: +- Manage L3Out interfaces on Cisco ACI fabrics. +options: + tenant: + description: + - Name of an existing tenant. + type: str + aliases: [ tenant_name ] + required: true + l3out: + description: + - Name of an existing L3Out. + type: str + aliases: [ l3out_name ] + required: true + node_profile: + description: + - Name of the node profile. + type: str + aliases: [ node_profile_name, logical_node ] + required: true + interface_profile: + description: + - Name of the interface profile. + type: str + aliases: [ interface_profile_name, logical_interface ] + required: true + pod_id: + description: + - Pod ID to build the interface on. + type: str + node_id: + description: + - Node ID to build the interface on for Port-channels and single ports. + type: str + encap: + description: + - Encapsulation on the interface (e.g. "vlan-500") + type: str + encap_scope: + description: + - Encapsulation scope. + choices: [ vrf, local ] + type: str + address: + description: + - IP address. + type: str + aliases: [ addr, ip_address ] + mac_address: + description: + - The MAC address option of the interface. + type: str + link_local_address: + description: + - The link local address option of the interface. + type: str + mtu: + description: + - Interface MTU. + type: str + ipv6_dad: + description: + - IPv6 Duplicate Address Detection (DAD) feature. + type: str + choices: [ enabled, disabled] + mode: + description: + - The mode option for ext-svi interface. + type: str + choices: [ regular, native, untagged ] + 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_dscp ] + external_bridge_group_profile: + description: + - The external bridge group profile. + - Pass "" as the value to remove an existing external bridge group profile (See Examples). + - This is only supported in APIC v5.0 and above. + 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 + auto_state: + description: + - SVI auto state. + type: str + choices: [ enabled, disabled ] +extends_documentation_fragment: +- cisco.aci.aci +- cisco.aci.annotation + +notes: +- The C(tenant), C(l3out), C(logical_node_profile) and C(logical_interface_profile) must exist before using this module in your playbook. + The M(cisco.aci.aci_tenant), M(cisco.aci.aci_l3out), M(cisco.aci.aci_l3out_logical_node_profile), M(cisco.aci.aci_l3out_logical_interface_profile) \ + modules can be used for this. +seealso: +- module: cisco.aci.aci_tenant +- module: cisco.aci.aci_l3out +- module: cisco.aci.aci_l3out_logical_node_profile +- module: cisco.aci.aci_l3out_logical_interface_profile +- name: APIC Management Information Model reference + description: More information about the internal APIC class B(l3ext:VirtualLIfP) + link: https://developer.cisco.com/docs/apic-mim-ref/ +author: +- Shreyas Srish (@shrsr) +""" + +EXAMPLES = r""" +- name: Create a Floating SVI + cisco.aci.aci_l3out_floating_svi: + host: apic + username: admin + password: SomeSecretPassword + tenant: my_tenant + l3out: my_l3out + node_profile: my_node_profile + interface_profile: my_interface_profile + pod_id: 1 + node_id: 201 + encap: vlan-1 + address: 23.45.67.90/24 + external_bridge_group_profile: bridge1 + state: present + delegate_to: localhost + +- name: Remove an external bridge group profile + cisco.aci.aci_l3out_floating_svi: + host: apic + username: admin + password: SomeSecretPassword + tenant: my_tenant + l3out: my_l3out + node_profile: my_node_profile + interface_profile: my_interface_profile + pod_id: 1 + node_id: 201 + encap: vlan-1 + address: 23.45.67.90/24 + external_bridge_group_profile: "" + state: present + delegate_to: localhost + +- name: Remove a Floating SVI + cisco.aci.aci_l3out_floating_svi: + host: apic + username: admin + password: SomeSecretPassword + tenant: my_tenant + l3out: my_l3out + node_profile: my_node_profile + interface_profile: my_interface_profile + pod_id: 1 + node_id: 201 + encap: vlan-1 + state: absent + delegate_to: localhost + +- name: Query a Floating SVI + cisco.aci.aci_l3out_floating_svi: + host: apic + username: admin + password: SomeSecretPassword + tenant: my_tenant + l3out: my_l3out + node_profile: my_node_profile + interface_profile: my_interface_profile + pod_id: 1 + node_id: 201 + encap: vlan-1 + state: query + delegate_to: localhost + register: query_result + +- name: Query all the Floating SVIs under an interface profile + cisco.aci.aci_l3out_floating_svi: + host: apic + username: admin + password: SomeSecretPassword + tenant: my_tenant + l3out: my_l3out + node_profile: my_node_profile + interface_profile: my_interface_profile + state: query + delegate_to: localhost + register: query_results +""" + +RETURN = r""" +current: + description: The existing configuration from the APIC after the module has finished + returned: success + type: list + sample: + [ + { + "fvTenant": { + "attributes": { + "descr": "Production environment", + "dn": "uni/tn-production", + "name": "production", + "nameAlias": "", + "ownerKey": "", + "ownerTag": "" + } + } + } + ] +error: + description: The error information as returned from the APIC + returned: failure + type: dict + sample: + { + "code": "122", + "text": "unknown managed object class foo" + } +raw: + description: The raw output returned by the APIC REST API (xml or json) + returned: parse error + type: str + sample: '' +sent: + description: The actual/minimal configuration pushed to the APIC + returned: info + type: list + sample: + { + "fvTenant": { + "attributes": { + "descr": "Production environment" + } + } + } +previous: + description: The original configuration from the APIC before the module has started + returned: info + type: list + sample: + [ + { + "fvTenant": { + "attributes": { + "descr": "Production", + "dn": "uni/tn-production", + "name": "production", + "nameAlias": "", + "ownerKey": "", + "ownerTag": "" + } + } + } + ] +proposed: + description: The assembled configuration from the user-provided parameters + returned: info + type: dict + sample: + { + "fvTenant": { + "attributes": { + "descr": "Production environment", + "name": "production" + } + } + } +filter_string: + description: The filter string used for the request + returned: failure or debug + type: str + sample: ?rsp-prop-include=config-only +method: + description: The HTTP method used for the request to the APIC + returned: failure or debug + type: str + sample: POST +response: + description: The HTTP response from the APIC + returned: failure or debug + type: str + sample: OK (30 bytes) +status: + description: The HTTP status from the APIC + returned: failure or debug + type: int + sample: 200 +url: + description: The HTTP url used for the request to the APIC + returned: failure or debug + type: str + sample: https://10.11.12.13/api/mo/uni/tn-production.json +""" + + +from ansible.module_utils.basic import AnsibleModule +from ansible_collections.cisco.aci.plugins.module_utils.aci import ACIModule, aci_argument_spec, aci_annotation_spec, aci_contract_dscp_spec + + +def main(): + argument_spec = aci_argument_spec() + argument_spec.update(aci_annotation_spec()) + argument_spec.update( + tenant=dict(type="str", aliases=["tenant_name"], required=True), + l3out=dict(type="str", aliases=["l3out_name"], required=True), + node_profile=dict(type="str", aliases=["node_profile_name", "logical_node"], required=True), + interface_profile=dict(type="str", aliases=["interface_profile_name", "logical_interface"], required=True), + state=dict(type="str", default="present", choices=["absent", "present", "query"]), + pod_id=dict(type="str"), + node_id=dict(type="str"), + address=dict(type="str", aliases=["addr", "ip_address"]), + link_local_address=dict(type="str"), + mac_address=dict(type="str"), + mtu=dict(type="str"), + ipv6_dad=dict(type="str", choices=["enabled", "disabled"]), + mode=dict(type="str", choices=["regular", "native", "untagged"]), + encap=dict(type="str"), + encap_scope=dict(type="str", choices=["vrf", "local"]), + auto_state=dict(type="str", choices=["enabled", "disabled"]), + external_bridge_group_profile=dict(type="str"), + dscp=aci_contract_dscp_spec(direction="dscp"), + ) + + module = AnsibleModule( + argument_spec=argument_spec, + supports_check_mode=True, + required_if=[ + ["state", "present", ["pod_id", "node_id", "encap", "address"]], + ["state", "absent", ["pod_id", "node_id", "encap"]], + ], + ) + + tenant = module.params.get("tenant") + l3out = module.params.get("l3out") + node_profile = module.params.get("node_profile") + interface_profile = module.params.get("interface_profile") + state = module.params.get("state") + pod_id = module.params.get("pod_id") + node_id = module.params.get("node_id") + address = module.params.get("address") + mtu = module.params.get("mtu") + ipv6_dad = module.params.get("ipv6_dad") + link_local_address = module.params.get("link_local_address") + mac_address = module.params.get("mac_address") + mode = module.params.get("mode") + encap = module.params.get("encap") + encap_scope = "ctx" if module.params.get("encap_scope") == "vrf" else module.params.get("encap_scope") + auto_state = module.params.get("auto_state") + external_bridge_group_profile = module.params.get("external_bridge_group_profile") + + aci = ACIModule(module) + + node_dn = None + if pod_id and node_id: + node_dn = "topology/pod-{0}/node-{1}".format(pod_id, node_id) + + child_classes = [] + if external_bridge_group_profile is not None: + child_classes.append("l3extBdProfileCont") + + 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(node_profile), + module_object=node_profile, + target_filter={"name": node_profile}, + ), + subclass_3=dict( + aci_class="l3extLIfP", + aci_rn="lifp-{0}".format(interface_profile), + module_object=interface_profile, + target_filter={"name": interface_profile}, + ), + subclass_4=dict( + aci_class="l3extVirtualLIfP", aci_rn="vlifp-[{0}]-[{1}]".format(node_dn, encap), module_object=node_dn, target_filter={"nodeDn": node_dn} + ), + child_classes=child_classes, + ) + + aci.get_existing() + + if state == "present": + child_configs = [] + if external_bridge_group_profile is not None: + if external_bridge_group_profile == "" and isinstance(aci.existing, list) and len(aci.existing) > 0: + if aci.existing[0].get("l3extVirtualLIfP", {}).get("children") is not None: + child_configs.append( + dict( + l3extBdProfileCont=dict( + attributes=dict(status="deleted"), + ), + ) + ) + elif external_bridge_group_profile != "": + child_configs.append( + dict( + l3extBdProfileCont=dict( + attributes=dict(), + children=[ + dict( + l3extRsBdProfile=dict( + attributes=dict( + tDn="uni/tn-{0}/bdprofile-{1}".format(tenant, external_bridge_group_profile), + ), + ) + ) + ], + ) + ) + ) + + aci.payload( + aci_class="l3extVirtualLIfP", + class_config=dict( + addr=address, + ipv6Dad=ipv6_dad, + mtu=mtu, + ifInstT="ext-svi", + mode=mode, + encap=encap, + encapScope=encap_scope, + autostate=auto_state, + llAddr=link_local_address, + mac=mac_address, + ), + child_configs=child_configs, + ) + + aci.get_diff(aci_class="l3extVirtualLIfP") + + aci.post_config() + + elif state == "absent": + aci.delete_config() + + aci.exit_json() + + +if __name__ == "__main__": + main() diff --git a/ansible_collections/cisco/aci/plugins/modules/aci_l3out_floating_svi_path.py b/ansible_collections/cisco/aci/plugins/modules/aci_l3out_floating_svi_path.py new file mode 100644 index 000000000..3d7c45a33 --- /dev/null +++ b/ansible_collections/cisco/aci/plugins/modules/aci_l3out_floating_svi_path.py @@ -0,0 +1,491 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- + +# Copyright: (c) 2023, Shreyas Srish +# 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_floating_svi_path +short_description: Manage Layer 3 Outside (L3Out) Floating SVI Path Attributes (l3ext:RsDynPathAtt) +description: +- Manages L3Out Floating SVI path attributes on Cisco ACI fabrics. +options: + tenant: + description: + - Name of an existing tenant. + type: str + aliases: [ tenant_name ] + required: true + l3out: + description: + - Name of an existing L3Out. + type: str + aliases: [ l3out_name ] + required: true + node_profile: + description: + - Name of the node profile. + type: str + aliases: [ node_profile_name, logical_node ] + required: true + interface_profile: + description: + - Name of the interface profile. + type: str + aliases: [ interface_profile_name, logical_interface ] + required: true + pod_id: + description: + - Pod to build the interface on. + type: str + required: true + node_id: + description: + - Node to build the interface on for Port-channels and single ports. + type: str + required: true + encap: + description: + - Encapsulation on the interface (e.g. "vlan-500") + type: str + required: true + domain: + description: + - This option allows virtual machines to send frames with a mac address. + type: str + domain_type: + description: + - The domain type of the path. + - The physical domain type is only supported in APIC v5.0 and above. + type: str + choices: [ physical, vmware ] + access_encap: + description: + - The port encapsulation option. + type: str + floating_ip: + description: + - The floating IP address. + type: str + aliases: [ floating_address ] + forged_transmit: + description: + - This option allows virtual machines to send frames with a mac address. + - This is only supported in APIC v5.0 and above. + type: str + choices: [ enabled, disabled ] + mac_change: + description: + - The status of the mac address change support for port groups in an external VMM controller. + - This is only supported in APIC v5.0 and above. + type: str + choices: [ enabled, disabled ] + promiscuous_mode: + description: + - The status of promiscuous mode for port groups in an external VMM controller. + - This is only supported in APIC v5.0 and above. + type: str + choices: [ enabled, disabled ] + enhanced_lag_policy: + description: + - The enhanced lag policy of the path. + - Pass "" as the value to remove an existing enhanced lag policy (See Examples). + type: str + state: + description: + - Use C(present) or C(absent) for adding or removing. + - Use C(query) for listing an object or multiple objects. + type: str + choices: [ absent, present, query ] + default: present +extends_documentation_fragment: +- cisco.aci.aci +- cisco.aci.annotation + +notes: +- The C(tenant), C(l3out), C(logical_node_profile), C(logical_interface_profile) and C(floating_svi) must exist before using this module in your playbook. + The M(cisco.aci.aci_tenant), M(cisco.aci.aci_l3out), M(cisco.aci.aci_l3out_logical_node_profile), M(cisco.aci.aci_l3out_logical_interface_profile) and + M(cisco.aci.aci_l3out_floating_svi) can be used for this. +seealso: +- module: cisco.aci.aci_tenant +- module: cisco.aci.aci_l3out +- module: cisco.aci.aci_l3out_logical_node_profile +- module: cisco.aci.aci_l3out_logical_interface_profile +- module: cisco.aci.aci_l3out_floating_svi +- name: APIC Management Information Model reference + description: More information about the internal APIC class B(l3ext:RsDynPathAtt)) + link: https://developer.cisco.com/docs/apic-mim-ref/ +author: +- Shreyas Srish (@shrsr) +""" + +EXAMPLES = r""" +- name: Create a Floating SVI path attribute + cisco.aci.aci_l3out_floating_svi_path: + host: apic + username: admin + password: SomeSecretPassword + tenant: my_tenant + l3out: my_l3out + node_profile: my_node_profile + interface_profile: my_interface_profile + pod_id: 1 + node_id: 201 + encap: vlan-1 + floating_ip: 23.45.67.90/24 + domain_type: virtual + domain: anstest + enhanced_lag_policy: enhanced + state: present + delegate_to: localhost + +- name: Remove enhanced lag policy from the path + cisco.aci.aci_l3out_floating_svi_path: + host: apic + username: admin + password: SomeSecretPassword + tenant: my_tenant + l3out: my_l3out + node_profile: my_node_profile + interface_profile: my_interface_profile + pod_id: 1 + node_id: 201 + encap: vlan-1 + floating_ip: 23.45.67.90/24 + domain_type: virtual + domain: anstest + enhanced_lag_policy: "" + state: present + delegate_to: localhost + +- name: Remove a Floating SVI path attribute + cisco.aci.aci_l3out_floating_svi_path: + host: apic + username: admin + password: SomeSecretPassword + tenant: my_tenant + l3out: my_l3out + node_profile: my_node_profile + interface_profile: my_interface_profile + pod_id: 1 + node_id: 201 + encap: vlan-1 + domain_type: virtual + domain: anstest + state: absent + delegate_to: localhost + +- name: Query a Floating SVI path attribute + cisco.aci.aci_l3out_floating_svi_path: + host: apic + username: admin + password: SomeSecretPassword + tenant: my_tenant + l3out: my_l3out + node_profile: my_node_profile + interface_profile: my_interface_profile + pod_id: 1 + node_id: 201 + encap: vlan-1 + domain_type: virtual + domain: anstest + state: query + delegate_to: localhost + register: query_result + +- name: Query all the Floating SVI path attributes + cisco.aci.aci_l3out_floating_svi_path: + host: apic + username: admin + password: SomeSecretPassword + tenant: my_tenant + l3out: my_l3out + node_profile: my_node_profile + interface_profile: my_interface_profile + pod_id: 1 + node_id: 201 + encap: vlan-1 + state: query + delegate_to: localhost + register: query_results +""" + +RETURN = r""" +current: + description: The existing configuration from the APIC after the module has finished + returned: success + type: list + sample: + [ + { + "fvTenant": { + "attributes": { + "descr": "Production environment", + "dn": "uni/tn-production", + "name": "production", + "nameAlias": "", + "ownerKey": "", + "ownerTag": "" + } + } + } + ] +error: + description: The error information as returned from the APIC + returned: failure + type: dict + sample: + { + "code": "122", + "text": "unknown managed object class foo" + } +raw: + description: The raw output returned by the APIC REST API (xml or json) + returned: parse error + type: str + sample: '' +sent: + description: The actual/minimal configuration pushed to the APIC + returned: info + type: list + sample: + { + "fvTenant": { + "attributes": { + "descr": "Production environment" + } + } + } +previous: + description: The original configuration from the APIC before the module has started + returned: info + type: list + sample: + [ + { + "fvTenant": { + "attributes": { + "descr": "Production", + "dn": "uni/tn-production", + "name": "production", + "nameAlias": "", + "ownerKey": "", + "ownerTag": "" + } + } + } + ] +proposed: + description: The assembled configuration from the user-provided parameters + returned: info + type: dict + sample: + { + "fvTenant": { + "attributes": { + "descr": "Production environment", + "name": "production" + } + } + } +filter_string: + description: The filter string used for the request + returned: failure or debug + type: str + sample: ?rsp-prop-include=config-only +method: + description: The HTTP method used for the request to the APIC + returned: failure or debug + type: str + sample: POST +response: + description: The HTTP response from the APIC + returned: failure or debug + type: str + sample: OK (30 bytes) +status: + description: The HTTP status from the APIC + returned: failure or debug + type: int + sample: 200 +url: + description: The HTTP url used for the request to the APIC + returned: failure or debug + type: str + sample: https://10.11.12.13/api/mo/uni/tn-production.json +""" + + +from ansible.module_utils.basic import AnsibleModule +from ansible_collections.cisco.aci.plugins.module_utils.aci import ACIModule, aci_argument_spec, aci_annotation_spec + + +def main(): + argument_spec = aci_argument_spec() + argument_spec.update(aci_annotation_spec()) + argument_spec.update( + tenant=dict(type="str", aliases=["tenant_name"], required=True), + l3out=dict(type="str", aliases=["l3out_name"], required=True), + node_profile=dict(type="str", aliases=["node_profile_name", "logical_node"], required=True), + interface_profile=dict(type="str", aliases=["interface_profile_name", "logical_interface"], required=True), + state=dict(type="str", default="present", choices=["absent", "present", "query"]), + pod_id=dict(type="str", required=True), + node_id=dict(type="str", required=True), + encap=dict(type="str", required=True), + floating_ip=dict(type="str", aliases=["floating_address"]), + forged_transmit=dict(type="str", choices=["enabled", "disabled"]), + mac_change=dict(type="str", choices=["enabled", "disabled"]), + promiscuous_mode=dict(type="str", choices=["enabled", "disabled"]), + domain_type=dict(type="str", choices=["physical", "vmware"]), + domain=dict(type="str"), + enhanced_lag_policy=dict(type="str"), + access_encap=dict(type="str"), + ) + + module = AnsibleModule( + argument_spec=argument_spec, + supports_check_mode=True, + required_if=[ + ["state", "present", ["domain_type", "domain", "floating_ip"]], + ["state", "absent", ["domain_type", "domain"]], + ], + ) + + tenant = module.params.get("tenant") + l3out = module.params.get("l3out") + node_profile = module.params.get("node_profile") + interface_profile = module.params.get("interface_profile") + state = module.params.get("state") + pod_id = module.params.get("pod_id") + node_id = module.params.get("node_id") + floating_ip = module.params.get("floating_ip") + encap = module.params.get("encap") + forged_transmit = module.params.get("forged_transmit").capitalize() if module.params.get("forged_transmit") else None + mac_change = module.params.get("mac_change").capitalize() if module.params.get("mac_change") else None + promiscuous_mode = module.params.get("promiscuous_mode").capitalize() if module.params.get("promiscuous_mode") else None + domain_type = module.params.get("domain_type") + domain = module.params.get("domain") + enhanced_lag_policy = module.params.get("enhanced_lag_policy") + access_encap = module.params.get("access_encap") + + aci = ACIModule(module) + + node_dn = "topology/pod-{0}/node-{1}".format(pod_id, node_id) + + tDn = None + if domain_type == "physical": + tDn = "uni/phys-{0}".format(domain) + elif domain_type == "vmware": + tDn = "uni/vmmp-VMware/dom-{0}".format(domain) + + 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(node_profile), + module_object=node_profile, + target_filter={"name": node_profile}, + ), + subclass_3=dict( + aci_class="l3extLIfP", + aci_rn="lifp-{0}".format(interface_profile), + module_object=interface_profile, + target_filter={"name": interface_profile}, + ), + subclass_4=dict( + aci_class="l3extVirtualLIfP", aci_rn="vlifp-[{0}]-[{1}]".format(node_dn, encap), module_object=node_dn, target_filter={"nodeDn": node_dn} + ), + subclass_5=dict( + aci_class="l3extRsDynPathAtt", + aci_rn="rsdynPathAtt-[{0}]".format(tDn), + module_object=tDn, + target_filter={"tDn": tDn}, + ), + child_classes=["l3extVirtualLIfPLagPolAtt"], + ) + + aci.get_existing() + + if state == "present": + child_configs = [] + if enhanced_lag_policy is not None and domain_type == "vmware": + existing_enhanced_lag_policy = "" + if isinstance(aci.existing, list) and len(aci.existing) > 0: + for child in aci.existing[0].get("l3extRsDynPathAtt", {}).get("children", {}): + if child.get("l3extVirtualLIfPLagPolAtt"): + try: + existing_enhanced_lag_policy = child["l3extVirtualLIfPLagPolAtt"]["children"][0]["l3extRsVSwitchEnhancedLagPol"]["attributes"][ + "tDn" + ].split("enlacplagp-")[1] + except (AttributeError, IndexError, KeyError): + existing_enhanced_lag_policy = "" + + if enhanced_lag_policy == "": + child_configs.append( + dict( + l3extVirtualLIfPLagPolAtt=dict( + attributes=dict(status="deleted"), + ), + ) + ) + + if enhanced_lag_policy != "": + child = [ + dict( + l3extRsVSwitchEnhancedLagPol=dict( + attributes=dict(tDn="{0}/vswitchpolcont/enlacplagp-{1}".format(tDn, enhanced_lag_policy)), + ) + ), + ] + if enhanced_lag_policy != existing_enhanced_lag_policy and existing_enhanced_lag_policy != "": + child.append( + dict( + l3extRsVSwitchEnhancedLagPol=dict( + attributes=dict(status="deleted", tDn="{0}/vswitchpolcont/enlacplagp-{1}".format(tDn, existing_enhanced_lag_policy)), + ) + ) + ) + child_configs.append(dict(l3extVirtualLIfPLagPolAtt=dict(attributes=dict(), children=child))) + + aci.payload( + aci_class="l3extRsDynPathAtt", + class_config=dict( + floatingAddr=floating_ip, + forgedTransmit=forged_transmit, + macChange=mac_change, + promMode=promiscuous_mode, + encap=access_encap, + ), + child_configs=child_configs, + ) + + aci.get_diff(aci_class="l3extRsDynPathAtt") + + aci.post_config() + + elif state == "absent": + aci.delete_config() + + aci.exit_json() + + +if __name__ == "__main__": + main() diff --git a/ansible_collections/cisco/aci/plugins/modules/aci_l3out_floating_svi_path_secondary_ip.py b/ansible_collections/cisco/aci/plugins/modules/aci_l3out_floating_svi_path_secondary_ip.py new file mode 100644 index 000000000..b49c18169 --- /dev/null +++ b/ansible_collections/cisco/aci/plugins/modules/aci_l3out_floating_svi_path_secondary_ip.py @@ -0,0 +1,398 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- + +# Copyright: (c) 2023, Shreyas Srish +# 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_floating_svi_path_secondary_ip +short_description: Manages Layer 3 Outside (L3Out) Floating SVI Path Attribute's Secondary IP addresses (l3ext:Ip) +description: +- Manages L3Out Floating SVI path attribute's secondary IP addresses on Cisco ACI fabrics. +options: + tenant: + description: + - Name of an existing tenant. + type: str + aliases: [ tenant_name ] + required: true + l3out: + description: + - Name of an existing L3Out. + type: str + aliases: [ l3out_name ] + required: true + node_profile: + description: + - Name of the node profile. + type: str + aliases: [ node_profile_name, logical_node ] + required: true + interface_profile: + description: + - Name of the interface profile. + type: str + aliases: [ interface_profile_name, logical_interface ] + required: true + pod_id: + description: + - Pod to build the interface on. + type: str + required: true + node_id: + description: + - Node to build the interface on for Port-channels and single ports. + type: str + required: true + encap: + description: + - Encapsulation on the interface (e.g. "vlan-500") + type: str + required: true + domain: + description: + - This option allows virtual machines to send frames with a mac address. + type: str + required: true + domain_type: + description: + - The domain type of the path. + type: str + choices: [ physical, vmware ] + required: true + secondary_ip: + description: + - The secondary floating IP address. + type: str + aliases: [ secondary_floating_address ] + state: + description: + - Use C(present) or C(absent) for adding or removing. + - Use C(query) for listing an object or multiple objects. + type: str + choices: [ absent, present, query ] + default: present +extends_documentation_fragment: +- cisco.aci.aci +- cisco.aci.annotation + +notes: +- The C(tenant), C(l3out), C(logical_node_profile), C(logical_interface_profile) and C(floating_svi) must exist before using this module in your playbook. + The M(cisco.aci.aci_tenant), M(cisco.aci.aci_l3out), M(cisco.aci.aci_l3out_logical_node_profile), M(cisco.aci.aci_l3out_logical_interface_profile), \ + M(cisco.aci.aci_l3out_floating_svi) and M(cisco.aci.aci_l3out_floating_svi_path) can be used for this. +seealso: +- module: cisco.aci.aci_tenant +- module: cisco.aci.aci_l3out +- module: cisco.aci.aci_l3out_logical_node_profile +- module: cisco.aci.aci_l3out_logical_interface_profile +- module: cisco.aci.aci_l3out_floating_svi +- module: cisco.aci.aci_l3out_floating_svi_path +- name: APIC Management Information Model reference + description: More information about the internal APIC class B(l3ext:Ip) + link: https://developer.cisco.com/docs/apic-mim-ref/ +author: +- Shreyas Srish (@shrsr) +""" + +EXAMPLES = r""" +- name: Create a Floating SVI path attribute secondary IP + cisco.aci.aci_l3out_floating_svi_path_secondary_ip: + host: apic + username: admin + password: SomeSecretPassword + tenant: my_tenant + l3out: my_l3out + node_profile: my_node_profile + interface_profile: my_interface_profile + pod_id: 1 + node_id: 201 + encap: vlan-1 + secondary_ip: 23.45.67.90/24 + domain_type: virtual + domain: anstest + state: present + delegate_to: localhost + +- name: Remove a Floating SVI path attribute secondary IP + cisco.aci.aci_l3out_floating_svi_path_secondary_ip: + host: apic + username: admin + password: SomeSecretPassword + tenant: my_tenant + l3out: my_l3out + node_profile: my_node_profile + interface_profile: my_interface_profile + pod_id: 1 + node_id: 201 + encap: vlan-1 + secondary_ip: 23.45.67.90/24 + domain_type: virtual + domain: anstest + state: absent + delegate_to: localhost + +- name: Query a Floating SVI path attribute secondary IP + cisco.aci.aci_l3out_floating_svi_path_secondary_ip: + host: apic + username: admin + password: SomeSecretPassword + tenant: my_tenant + l3out: my_l3out + node_profile: my_node_profile + interface_profile: my_interface_profile + pod_id: 1 + node_id: 201 + encap: vlan-1 + domain_type: virtual + domain: anstest + secondary_ip: 23.45.67.90/24 + state: query + delegate_to: localhost + register: query_result + +- name: Query all the secondary IPs under a Floating SVI path attribute + cisco.aci.aci_l3out_floating_svi_path_secondary_ip: + host: apic + username: admin + password: SomeSecretPassword + tenant: my_tenant + l3out: my_l3out + node_profile: my_node_profile + interface_profile: my_interface_profile + pod_id: 1 + node_id: 201 + encap: vlan-1 + domain_type: virtual + domain: anstest + state: query + delegate_to: localhost + register: query_results +""" + +RETURN = r""" +current: + description: The existing configuration from the APIC after the module has finished + returned: success + type: list + sample: + [ + { + "fvTenant": { + "attributes": { + "descr": "Production environment", + "dn": "uni/tn-production", + "name": "production", + "nameAlias": "", + "ownerKey": "", + "ownerTag": "" + } + } + } + ] +error: + description: The error information as returned from the APIC + returned: failure + type: dict + sample: + { + "code": "122", + "text": "unknown managed object class foo" + } +raw: + description: The raw output returned by the APIC REST API (xml or json) + returned: parse error + type: str + sample: '' +sent: + description: The actual/minimal configuration pushed to the APIC + returned: info + type: list + sample: + { + "fvTenant": { + "attributes": { + "descr": "Production environment" + } + } + } +previous: + description: The original configuration from the APIC before the module has started + returned: info + type: list + sample: + [ + { + "fvTenant": { + "attributes": { + "descr": "Production", + "dn": "uni/tn-production", + "name": "production", + "nameAlias": "", + "ownerKey": "", + "ownerTag": "" + } + } + } + ] +proposed: + description: The assembled configuration from the user-provided parameters + returned: info + type: dict + sample: + { + "fvTenant": { + "attributes": { + "descr": "Production environment", + "name": "production" + } + } + } +filter_string: + description: The filter string used for the request + returned: failure or debug + type: str + sample: ?rsp-prop-include=config-only +method: + description: The HTTP method used for the request to the APIC + returned: failure or debug + type: str + sample: POST +response: + description: The HTTP response from the APIC + returned: failure or debug + type: str + sample: OK (30 bytes) +status: + description: The HTTP status from the APIC + returned: failure or debug + type: int + sample: 200 +url: + description: The HTTP url used for the request to the APIC + returned: failure or debug + type: str + sample: https://10.11.12.13/api/mo/uni/tn-production.json +""" + +from ansible_collections.cisco.aci.plugins.module_utils.aci import ACIModule, aci_argument_spec, aci_annotation_spec +from ansible.module_utils.basic import AnsibleModule + + +def main(): + argument_spec = aci_argument_spec() + argument_spec.update(aci_annotation_spec()) + argument_spec.update( + tenant=dict(type="str", aliases=["tenant_name"], required=True), + l3out=dict(type="str", aliases=["l3out_name"], required=True), + node_profile=dict(type="str", aliases=["node_profile_name", "logical_node"], required=True), + interface_profile=dict(type="str", aliases=["interface_profile_name", "logical_interface"], required=True), + state=dict(type="str", default="present", choices=["absent", "present", "query"]), + pod_id=dict(type="str", required=True), + node_id=dict(type="str", required=True), + encap=dict(type="str", required=True), + domain_type=dict(type="str", choices=["physical", "vmware"], required=True), + domain=dict(type="str", required=True), + secondary_ip=dict(type="str", aliases=["secondary_floating_address"]), + ) + + module = AnsibleModule( + argument_spec=argument_spec, + supports_check_mode=True, + required_if=[ + ["state", "absent", ["secondary_ip"]], + ["state", "present", ["secondary_ip"]], + ], + ) + + tenant = module.params.get("tenant") + l3out = module.params.get("l3out") + node_profile = module.params.get("node_profile") + interface_profile = module.params.get("interface_profile") + pod_id = module.params.get("pod_id") + node_id = module.params.get("node_id") + encap = module.params.get("encap") + secondary_ip = module.params.get("secondary_ip") + domain_type = module.params.get("domain_type") + domain = module.params.get("domain") + state = module.params.get("state") + + aci = ACIModule(module) + + node_dn = "topology/pod-{0}/node-{1}".format(pod_id, node_id) + + tDn = None + if domain_type == "physical": + tDn = "uni/phys-{0}".format(domain) + else: + tDn = "uni/vmmp-VMware/dom-{0}".format(domain) + + 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(node_profile), + module_object=node_profile, + target_filter={"name": node_profile}, + ), + subclass_3=dict( + aci_class="l3extLIfP", + aci_rn="lifp-{0}".format(interface_profile), + module_object=interface_profile, + target_filter={"name": interface_profile}, + ), + subclass_4=dict( + aci_class="l3extVirtualLIfP", aci_rn="vlifp-[{0}]-[{1}]".format(node_dn, encap), module_object=node_dn, target_filter={"nodeDn": node_dn} + ), + subclass_5=dict( + aci_class="l3extRsDynPathAtt", + aci_rn="rsdynPathAtt-[{0}]".format(tDn), + module_object=tDn, + target_filter={"tDn": tDn}, + ), + subclass_6=dict( + aci_class="l3extIp", + aci_rn="addr-[{0}]".format(secondary_ip), + module_object=secondary_ip, + target_filter={"addr": secondary_ip}, + ), + ) + + aci.get_existing() + + if state == "present": + aci.payload(aci_class="l3extIp", class_config=dict(addr=secondary_ip, ipv6Dad="disabled")) + + aci.get_diff(aci_class="l3extIp") + + aci.post_config() + + elif state == "absent": + aci.delete_config() + + aci.exit_json() + + +if __name__ == "__main__": + main() diff --git a/ansible_collections/cisco/aci/plugins/modules/aci_l3out_floating_svi_secondary_ip.py b/ansible_collections/cisco/aci/plugins/modules/aci_l3out_floating_svi_secondary_ip.py new file mode 100644 index 000000000..ea71376dd --- /dev/null +++ b/ansible_collections/cisco/aci/plugins/modules/aci_l3out_floating_svi_secondary_ip.py @@ -0,0 +1,362 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- + +# Copyright: (c) 2023, Shreyas Srish +# 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_floating_svi_secondary_ip +short_description: Manages Layer 3 Outside (L3Out) Floating SVI Secondary IP addresses (l3ext:Ip) +description: +- Manages L3Out Floating SVI secondary IP addresses on Cisco ACI fabrics. +options: + tenant: + description: + - Name of an existing tenant. + type: str + aliases: [ tenant_name ] + required: true + l3out: + description: + - Name of an existing L3Out. + type: str + aliases: [ l3out_name ] + required: true + node_profile: + description: + - Name of the node profile. + type: str + aliases: [ node_profile_name, logical_node ] + required: true + interface_profile: + description: + - Name of the interface profile. + type: str + aliases: [ interface_profile_name, logical_interface ] + required: true + pod_id: + description: + - Pod to build the interface on. + type: str + required: true + node_id: + description: + - Node to build the interface on for Port-channels and single ports. + type: str + required: true + encap: + description: + - Encapsulation on the interface (e.g. "vlan-500") + type: str + required: true + secondary_ip: + description: + - The secondary floating IP address. + type: str + aliases: [ secondary_floating_address ] + state: + description: + - Use C(present) or C(absent) for adding or removing. + - Use C(query) for listing an object or multiple objects. + type: str + choices: [ absent, present, query ] + default: present +extends_documentation_fragment: +- cisco.aci.aci +- cisco.aci.annotation + +notes: +- The C(tenant), C(l3out), C(logical_node_profile), C(logical_interface_profile) and C(floating_svi) must exist before using this module in your playbook. + The M(cisco.aci.aci_tenant), M(cisco.aci.aci_l3out), M(cisco.aci.aci_l3out_logical_node_profile), M(cisco.aci.aci_l3out_logical_interface_profile) and \ + M(cisco.aci.aci_l3out_floating_svi) can be used for this. +seealso: +- module: cisco.aci.aci_tenant +- module: cisco.aci.aci_l3out +- module: cisco.aci.aci_l3out_logical_node_profile +- module: cisco.aci.aci_l3out_logical_interface_profile +- module: cisco.aci.aci_l3out_floating_svi +- name: APIC Management Information Model reference + description: More information about the internal APIC class B(l3ext:Ip) + link: https://developer.cisco.com/docs/apic-mim-ref/ +author: +- Shreyas Srish (@shrsr) +""" + +EXAMPLES = r""" +- name: Create a Floating SVI secondary IP + cisco.aci.aci_l3out_floating_svi_secondary_ip: + host: apic + username: admin + password: SomeSecretPassword + tenant: my_tenant + l3out: my_l3out + node_profile: my_node_profile + interface_profile: my_interface_profile + pod_id: 1 + node_id: 201 + encap: vlan-1 + secondary_ip: 23.45.67.90/24 + state: present + delegate_to: localhost + +- name: Remove a Floating SVI secondary IP + cisco.aci.aci_l3out_floating_svi_secondary_ip: + host: apic + username: admin + password: SomeSecretPassword + tenant: my_tenant + l3out: my_l3out + node_profile: my_node_profile + interface_profile: my_interface_profile + pod_id: 1 + node_id: 201 + encap: vlan-1 + secondary_ip: 23.45.67.90/24 + state: absent + delegate_to: localhost + +- name: Query a Floating SVI secondary IP + cisco.aci.aci_l3out_floating_svi_secondary_ip: + host: apic + username: admin + password: SomeSecretPassword + tenant: my_tenant + l3out: my_l3out + node_profile: my_node_profile + interface_profile: my_interface_profile + pod_id: 1 + node_id: 201 + encap: vlan-1 + secondary_ip: 23.45.67.90/24 + state: query + delegate_to: localhost + register: query_result + +- name: Query all the secondary IPs under a Floating SVI + cisco.aci.aci_l3out_floating_svi_secondary_ip: + host: apic + username: admin + password: SomeSecretPassword + tenant: my_tenant + l3out: my_l3out + node_profile: my_node_profile + interface_profile: my_interface_profile + pod_id: 1 + node_id: 201 + encap: vlan-1 + state: query + delegate_to: localhost + register: query_results +""" + +RETURN = r""" +current: + description: The existing configuration from the APIC after the module has finished + returned: success + type: list + sample: + [ + { + "fvTenant": { + "attributes": { + "descr": "Production environment", + "dn": "uni/tn-production", + "name": "production", + "nameAlias": "", + "ownerKey": "", + "ownerTag": "" + } + } + } + ] +error: + description: The error information as returned from the APIC + returned: failure + type: dict + sample: + { + "code": "122", + "text": "unknown managed object class foo" + } +raw: + description: The raw output returned by the APIC REST API (xml or json) + returned: parse error + type: str + sample: '' +sent: + description: The actual/minimal configuration pushed to the APIC + returned: info + type: list + sample: + { + "fvTenant": { + "attributes": { + "descr": "Production environment" + } + } + } +previous: + description: The original configuration from the APIC before the module has started + returned: info + type: list + sample: + [ + { + "fvTenant": { + "attributes": { + "descr": "Production", + "dn": "uni/tn-production", + "name": "production", + "nameAlias": "", + "ownerKey": "", + "ownerTag": "" + } + } + } + ] +proposed: + description: The assembled configuration from the user-provided parameters + returned: info + type: dict + sample: + { + "fvTenant": { + "attributes": { + "descr": "Production environment", + "name": "production" + } + } + } +filter_string: + description: The filter string used for the request + returned: failure or debug + type: str + sample: ?rsp-prop-include=config-only +method: + description: The HTTP method used for the request to the APIC + returned: failure or debug + type: str + sample: POST +response: + description: The HTTP response from the APIC + returned: failure or debug + type: str + sample: OK (30 bytes) +status: + description: The HTTP status from the APIC + returned: failure or debug + type: int + sample: 200 +url: + description: The HTTP url used for the request to the APIC + returned: failure or debug + type: str + sample: https://10.11.12.13/api/mo/uni/tn-production.json +""" + +from ansible_collections.cisco.aci.plugins.module_utils.aci import ACIModule, aci_argument_spec, aci_annotation_spec +from ansible.module_utils.basic import AnsibleModule + + +def main(): + argument_spec = aci_argument_spec() + argument_spec.update(aci_annotation_spec()) + argument_spec.update( + tenant=dict(type="str", aliases=["tenant_name"], required=True), + l3out=dict(type="str", aliases=["l3out_name"], required=True), + node_profile=dict(type="str", aliases=["node_profile_name", "logical_node"], required=True), + interface_profile=dict(type="str", aliases=["interface_profile_name", "logical_interface"], required=True), + state=dict(type="str", default="present", choices=["absent", "present", "query"]), + pod_id=dict(type="str", required=True), + node_id=dict(type="str", required=True), + encap=dict(type="str", required=True), + secondary_ip=dict(type="str", aliases=["secondary_floating_address"]), + ) + + module = AnsibleModule( + argument_spec=argument_spec, + supports_check_mode=True, + required_if=[ + ["state", "absent", ["secondary_ip"]], + ["state", "present", ["secondary_ip"]], + ], + ) + + tenant = module.params.get("tenant") + l3out = module.params.get("l3out") + node_profile = module.params.get("node_profile") + interface_profile = module.params.get("interface_profile") + pod_id = module.params.get("pod_id") + node_id = module.params.get("node_id") + encap = module.params.get("encap") + secondary_ip = module.params.get("secondary_ip") + state = module.params.get("state") + + aci = ACIModule(module) + + node_dn = "topology/pod-{0}/node-{1}".format(pod_id, node_id) + + 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(node_profile), + module_object=node_profile, + target_filter={"name": node_profile}, + ), + subclass_3=dict( + aci_class="l3extLIfP", + aci_rn="lifp-{0}".format(interface_profile), + module_object=interface_profile, + target_filter={"name": interface_profile}, + ), + subclass_4=dict( + aci_class="l3extVirtualLIfP", aci_rn="vlifp-[{0}]-[{1}]".format(node_dn, encap), module_object=node_dn, target_filter={"nodeDn": node_dn} + ), + subclass_5=dict( + aci_class="l3extIp", + aci_rn="addr-[{0}]".format(secondary_ip), + module_object=secondary_ip, + target_filter={"addr": secondary_ip}, + ), + ) + + aci.get_existing() + + if state == "present": + aci.payload(aci_class="l3extIp", class_config=dict(addr=secondary_ip, ipv6Dad="enabled")) + + aci.get_diff(aci_class="l3extIp") + + aci.post_config() + + elif state == "absent": + aci.delete_config() + + aci.exit_json() + + +if __name__ == "__main__": + main() diff --git a/ansible_collections/cisco/aci/plugins/modules/aci_l3out_hsrp_group.py b/ansible_collections/cisco/aci/plugins/modules/aci_l3out_hsrp_group.py new file mode 100644 index 000000000..c6f7316b2 --- /dev/null +++ b/ansible_collections/cisco/aci/plugins/modules/aci_l3out_hsrp_group.py @@ -0,0 +1,393 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- + +# Copyright: (c) 2023, Shreyas Srish (@shrsr) +# 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_hsrp_group +short_description: Manage HSRP group (hsrp:GroupP) of the HSRP interface profile (hsrp:IfP) +description: +- Manage HSRP group of the HSRP interface profile on Cisco ACI fabrics. +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 ] + node_profile: + description: + - Name of the node profile. + type: str + aliases: [ node_profile_name, logical_node ] + interface_profile: + description: + - Name of an existing interface profile. + type: str + aliases: [ interface_profile_name, logical_interface ] + hsrp_interface_group: + description: + - Name of the HSRP interface group. + type: str + aliases: [ name, hsrp_group ] + group_id: + description: + - The group id of the HSRP interface group. + type: int + ip: + description: + - The virtual IP address of the HSRP interface group. + type: str + mac: + description: + - The MAC address of the HSRP interface group. + type: str + group_name: + description: + - The group name is used to define and manage the specific HSRP interface group, facilitating high availability in the network. + type: str + description: + description: + - The description of the HSRP interface group. + type: str + aliases: [ descr ] + group_type: + description: + - The type of the HSRP interface group. + type: str + choices: [ ipv4, ipv6 ] + ip_obtain_mode: + description: + - The mode of method used to obtain the IP address. + type: str + choices: [ admin, auto, learn ] + group_policy: + description: + - The group policy of the HSRP interface 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 +extends_documentation_fragment: +- cisco.aci.aci +- cisco.aci.annotation +- cisco.aci.owner + +notes: +- The C(tenant), C(l3out), C(logical_node_profile), C(logical_interface_profile) and C(hsrp_interface_profile) must exist before using this module in + your playbook. The M(cisco.aci.aci_tenant), M(cisco.aci.aci_l3out), M(cisco.aci.aci_l3out_logical_node_profile), + M(cisco.aci.aci_l3out_logical_interface_profile) and M(cisco.aci.aci_l3out_hsrp_interface_profile) can be used for this. +seealso: +- module: aci_tenant +- module: aci_l3out +- module: aci_l3out_logical_node_profile +- module: aci_l3out_logical_interface_profile +- module: aci_l3out_hsrp_interface_profile +- name: APIC Management Information Model reference + description: More information about the internal APIC class B(hsrp:IfP). + link: https://developer.cisco.com/docs/apic-mim-ref/ +author: +- Shreyas Srish (@shrsr) +""" + +EXAMPLES = r""" +- name: Add a new HSRP group + cisco.aci.aci_l3out_hsrp_group: + host: apic + username: admin + password: SomeSecretPassword + tenant: my_tenant + l3out: my_l3out + node_profile: my_node_profile + interface_profile: my_interface_profile + hsrp_interface_group: group1 + ip: 12.34.56.32 + group_type: ipv4 + ip_obtain_mode: admin + group_policy: default + state: present + delegate_to: localhost + +- name: Delete a HSRP group + cisco.aci.aci_l3out_hsrp_group: + host: apic + username: admin + password: SomeSecretPassword + tenant: my_tenant + l3out: my_l3out + node_profile: my_node_profile + interface_profile: my_interface_profile + hsrp_interface_group: group1 + ip: 12.34.56.32 + group_type: ipv4 + ip_obtain_mode: admin + group_policy: default + state: absent + delegate_to: localhost + +- name: Query a HSRP group + cisco.aci.aci_l3out_hsrp_group: + host: apic + username: admin + password: SomeSecretPassword + tenant: my_tenant + l3out: my_l3out + node_profile: my_node_profile + interface_profile: my_interface_profile + hsrp_interface_group: group1 + ip: 12.34.56.32 + group_type: ipv4 + ip_obtain_mode: admin + group_policy: default + state: query + delegate_to: localhost + register: query_result + +- name: Query all HSRP groups + cisco.aci.aci_l3out_hsrp_group: + host: apic + username: admin + password: SomeSecretPassword + tenant: my_tenant + l3out: my_l3out + node_profile: my_node_profile + interface_profile: my_interface_profile + state: query + delegate_to: localhost + register: query_result +""" + +RETURN = r""" +current: + description: The existing configuration from the APIC after the module has finished + returned: success + type: list + sample: + [ + { + "fvTenant": { + "attributes": { + "descr": "Production environment", + "dn": "uni/tn-production", + "name": "production", + "nameAlias": "", + "ownerKey": "", + "ownerTag": "" + } + } + } + ] +error: + description: The error information as returned from the APIC + returned: failure + type: dict + sample: + { + "code": "122", + "text": "unknown managed object class foo" + } +raw: + description: The raw output returned by the APIC REST API (xml or json) + returned: parse error + type: str + sample: '' +sent: + description: The actual/minimal configuration pushed to the APIC + returned: info + type: list + sample: + { + "fvTenant": { + "attributes": { + "descr": "Production environment" + } + } + } +previous: + description: The original configuration from the APIC before the module has started + returned: info + type: list + sample: + [ + { + "fvTenant": { + "attributes": { + "descr": "Production", + "dn": "uni/tn-production", + "name": "production", + "nameAlias": "", + "ownerKey": "", + "ownerTag": "" + } + } + } + ] +proposed: + description: The assembled configuration from the user-provided parameters + returned: info + type: dict + sample: + { + "fvTenant": { + "attributes": { + "descr": "Production environment", + "name": "production" + } + } + } +filter_string: + description: The filter string used for the request + returned: failure or debug + type: str + sample: ?rsp-prop-include=config-only +method: + description: The HTTP method used for the request to the APIC + returned: failure or debug + type: str + sample: POST +response: + description: The HTTP response from the APIC + returned: failure or debug + type: str + sample: OK (30 bytes) +status: + description: The HTTP status from the APIC + returned: failure or debug + type: int + sample: 200 +url: + description: The HTTP url used for the request to the APIC + returned: failure or debug + type: str + sample: https://10.11.12.13/api/mo/uni/tn-production.json +""" + + +from ansible.module_utils.basic import AnsibleModule +from ansible_collections.cisco.aci.plugins.module_utils.aci import ACIModule, aci_argument_spec, aci_annotation_spec, aci_owner_spec + + +def main(): + argument_spec = aci_argument_spec() + argument_spec.update(aci_annotation_spec()) + argument_spec.update(aci_owner_spec()) + argument_spec.update( + tenant=dict(type="str", aliases=["tenant_name"]), + l3out=dict(type="str", aliases=["l3out_name"]), + node_profile=dict(type="str", aliases=["node_profile_name", "logical_node"]), + interface_profile=dict(type="str", aliases=["interface_profile_name", "logical_interface"]), + hsrp_interface_group=dict(type="str", aliases=["name", "hsrp_group"]), + group_id=dict(type="int"), + ip=dict(type="str"), + mac=dict(type="str"), + group_name=dict(type="str"), + description=dict(type="str", aliases=["descr"]), + group_type=dict(type="str", choices=["ipv4", "ipv6"]), + ip_obtain_mode=dict(type="str", choices=["admin", "auto", "learn"]), + group_policy=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", ["tenant", "l3out", "node_profile", "interface_profile", "hsrp_interface_group"]], + ["state", "present", ["tenant", "l3out", "node_profile", "interface_profile", "hsrp_interface_group"]], + ], + ) + + tenant = module.params.get("tenant") + l3out = module.params.get("l3out") + node_profile = module.params.get("node_profile") + interface_profile = module.params.get("interface_profile") + hsrp_interface_group = module.params.get("hsrp_interface_group") + group_id = module.params.get("group_id") + ip = module.params.get("ip") + mac = module.params.get("mac") + group_name = module.params.get("group_name") + description = module.params.get("description") + group_type = module.params.get("group_type") + ip_obtain_mode = module.params.get("ip_obtain_mode") + group_policy = module.params.get("group_policy") + 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="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(node_profile), + module_object=node_profile, + target_filter={"name": node_profile}, + ), + subclass_3=dict( + aci_class="l3extLIfP", + aci_rn="lifp-[{0}]".format(interface_profile), + module_object=interface_profile, + target_filter={"name": interface_profile}, + ), + subclass_4=dict( + aci_class="hsrpIfP", + aci_rn="hsrpIfP", + module_object=interface_profile, + target_filter={"name": interface_profile}, + ), + subclass_5=dict( + aci_class="hsrpGroupP", + aci_rn="hsrpGroupP-{0}".format(hsrp_interface_group), + module_object=hsrp_interface_group, + target_filter={"name": hsrp_interface_group}, + ), + child_classes=["hsrpRsGroupPol"], + ) + + aci.get_existing() + + if state == "present": + aci.payload( + aci_class="hsrpGroupP", + class_config=dict(groupAf=group_type, groupId=group_id, groupName=group_name, ip=ip, ipObtainMode=ip_obtain_mode, mac=mac, descr=description), + child_configs=[dict(hsrpRsGroupPol=dict(attributes=dict(tnHsrpGroupPolName=group_policy)))] if group_policy is not None else [], + ) + + aci.get_diff(aci_class="hsrpGroupP") + + aci.post_config() + + elif state == "absent": + aci.delete_config() + + aci.exit_json() + + +if __name__ == "__main__": + main() diff --git a/ansible_collections/cisco/aci/plugins/modules/aci_l3out_hsrp_interface_profile.py b/ansible_collections/cisco/aci/plugins/modules/aci_l3out_hsrp_interface_profile.py new file mode 100644 index 000000000..634a7f2f5 --- /dev/null +++ b/ansible_collections/cisco/aci/plugins/modules/aci_l3out_hsrp_interface_profile.py @@ -0,0 +1,320 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- + +# Copyright: (c) 2023, Shreyas Srish (@shrsr) +# 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_hsrp_interface_profile +short_description: Manages Layer 3 Outside (L3Out) HSRP interface profile (hsrp:IfP) +description: +- Manages L3Out HSRP interface profile on Cisco ACI fabrics. +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 ] + node_profile: + description: + - Name of the node profile. + type: str + aliases: [ node_profile_name, logical_node ] + interface_profile: + description: + - Name of an existing interface profile. + type: str + aliases: [ interface_profile_name, logical_interface ] + hsrp_policy: + description: + - Name of an existing HSRP interface policy. + type: str + aliases: [ name, hsrp_policy_name ] + version: + description: + - The version of the compatibility catalog. + type: str + choices: [ v1, v2 ] + state: + description: + - Use C(present) or C(absent) for adding or removing. + - Use C(query) for listing an object or multiple objects. + type: str + choices: [ absent, present, query ] + default: present +extends_documentation_fragment: +- cisco.aci.aci +- cisco.aci.annotation +- cisco.aci.owner + +notes: +- The C(tenant), C(l3out), C(logical_node_profile) and C(logical_interface_profile) must exist before using this module in your playbook. + The M(cisco.aci.aci_tenant), M(cisco.aci.aci_l3out), M(cisco.aci.aci_l3out_logical_node_profile) and M(cisco.aci.aci_l3out_logical_interface_profile) + can be used for this. +- If C(hsrp_policy) is used, it must exist before using this module in your playbook. + The M(cisco.aci.aci_interface_policy_hsrp) can be used for this. +seealso: +- module: aci_tenant +- module: aci_l3out +- module: aci_l3out_logical_node_profile +- module: aci_l3out_logical_interface_profile +- module: aci_interface_policy_hsrp +- name: APIC Management Information Model reference + description: More information about the internal APIC class B(hsrp:IfP). + link: https://developer.cisco.com/docs/apic-mim-ref/ +author: +- Shreyas Srish (@shrsr) +""" + +EXAMPLES = r""" +- name: Add a new HSRP interface profile + cisco.aci.aci_l3out_hsrp_interface_profile: + host: apic + username: admin + password: SomeSecretPassword + tenant: my_tenant + l3out: my_l3out + node_profile: my_node_profile + interface_profile: my_interface_profile + hsrp_policy: default + state: present + delegate_to: localhost + +- name: Delete a HSRP interface profile + cisco.aci.aci_l3out_hsrp_interface_profile: + host: apic + username: admin + password: SomeSecretPassword + tenant: my_tenant + l3out: my_l3out + node_profile: my_node_profile + interface_profile: my_interface_profile + hsrp_policy: default + state: absent + delegate_to: localhost + +- name: Query a HSRP interface profile + cisco.aci.aci_l3out_hsrp_interface_profile: + host: apic + username: admin + password: SomeSecretPassword + tenant: my_tenant + l3out: my_l3out + node_profile: my_node_profile + interface_profile: my_interface_profile + hsrp_policy: default + state: query + delegate_to: localhost + register: query_result +""" + +RETURN = r""" +current: + description: The existing configuration from the APIC after the module has finished + returned: success + type: list + sample: + [ + { + "fvTenant": { + "attributes": { + "descr": "Production environment", + "dn": "uni/tn-production", + "name": "production", + "nameAlias": "", + "ownerKey": "", + "ownerTag": "" + } + } + } + ] +error: + description: The error information as returned from the APIC + returned: failure + type: dict + sample: + { + "code": "122", + "text": "unknown managed object class foo" + } +raw: + description: The raw output returned by the APIC REST API (xml or json) + returned: parse error + type: str + sample: '' +sent: + description: The actual/minimal configuration pushed to the APIC + returned: info + type: list + sample: + { + "fvTenant": { + "attributes": { + "descr": "Production environment" + } + } + } +previous: + description: The original configuration from the APIC before the module has started + returned: info + type: list + sample: + [ + { + "fvTenant": { + "attributes": { + "descr": "Production", + "dn": "uni/tn-production", + "name": "production", + "nameAlias": "", + "ownerKey": "", + "ownerTag": "" + } + } + } + ] +proposed: + description: The assembled configuration from the user-provided parameters + returned: info + type: dict + sample: + { + "fvTenant": { + "attributes": { + "descr": "Production environment", + "name": "production" + } + } + } +filter_string: + description: The filter string used for the request + returned: failure or debug + type: str + sample: ?rsp-prop-include=config-only +method: + description: The HTTP method used for the request to the APIC + returned: failure or debug + type: str + sample: POST +response: + description: The HTTP response from the APIC + returned: failure or debug + type: str + sample: OK (30 bytes) +status: + description: The HTTP status from the APIC + returned: failure or debug + type: int + sample: 200 +url: + description: The HTTP url used for the request to the APIC + returned: failure or debug + type: str + sample: https://10.11.12.13/api/mo/uni/tn-production.json +""" + + +from ansible.module_utils.basic import AnsibleModule +from ansible_collections.cisco.aci.plugins.module_utils.aci import ACIModule, aci_argument_spec, aci_annotation_spec, aci_owner_spec + + +def main(): + argument_spec = aci_argument_spec() + argument_spec.update(aci_annotation_spec()) + argument_spec.update(aci_owner_spec()) + argument_spec.update( + tenant=dict(type="str", aliases=["tenant_name"]), + l3out=dict(type="str", aliases=["l3out_name"]), + node_profile=dict(type="str", aliases=["node_profile_name", "logical_node"]), + interface_profile=dict(type="str", aliases=["interface_profile_name", "logical_interface"]), + hsrp_policy=dict(type="str", aliases=["name", "hsrp_policy_name"]), + version=dict(type="str", choices=["v1", "v2"]), + state=dict(type="str", default="present", choices=["absent", "present", "query"]), + ) + + module = AnsibleModule( + argument_spec=argument_spec, + supports_check_mode=True, + required_if=[ + ["state", "absent", ["tenant", "l3out", "node_profile", "interface_profile"]], + ["state", "present", ["tenant", "l3out", "node_profile", "interface_profile"]], + ], + ) + + tenant = module.params.get("tenant") + l3out = module.params.get("l3out") + node_profile = module.params.get("node_profile") + interface_profile = module.params.get("interface_profile") + hsrp_policy = module.params.get("hsrp_policy") + version = module.params.get("version") + 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="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(node_profile), + module_object=node_profile, + target_filter={"name": node_profile}, + ), + subclass_3=dict( + aci_class="l3extLIfP", + aci_rn="lifp-[{0}]".format(interface_profile), + module_object=interface_profile, + target_filter={"name": interface_profile}, + ), + subclass_4=dict( + aci_class="hsrpIfP", + aci_rn="hsrpIfP", + module_object=interface_profile, + target_filter={"name": interface_profile}, + ), + child_classes=["hsrpRsIfPol"], + ) + + aci.get_existing() + + if state == "present": + child_configs = [] + if hsrp_policy is not None: + child_configs = [dict(hsrpRsIfPol=dict(attributes=dict(tnHsrpIfPolName=hsrp_policy)))] + + aci.payload(aci_class="hsrpIfP", class_config=dict(version=version), child_configs=child_configs) + + aci.get_diff(aci_class="hsrpIfP") + + aci.post_config() + + elif state == "absent": + aci.delete_config() + + aci.exit_json() + + +if __name__ == "__main__": + main() diff --git a/ansible_collections/cisco/aci/plugins/modules/aci_l3out_hsrp_secondary_vip.py b/ansible_collections/cisco/aci/plugins/modules/aci_l3out_hsrp_secondary_vip.py new file mode 100644 index 000000000..c9902ba76 --- /dev/null +++ b/ansible_collections/cisco/aci/plugins/modules/aci_l3out_hsrp_secondary_vip.py @@ -0,0 +1,344 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- + +# Copyright: (c) 2023, Shreyas Srish (@shrsr) +# 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_hsrp_secondary_vip +short_description: Manage HSRP Secondary Virtual IP of a HSRP group (hsrp:SecVip) +description: +- Manage HSRP Secondary Virtual IP of a HSRP group on Cisco ACI fabrics. +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 ] + node_profile: + description: + - Name of the node profile. + type: str + aliases: [ node_profile_name, logical_node ] + interface_profile: + description: + - Name of an existing interface profile. + type: str + aliases: [ name, interface_profile_name, logical_interface ] + hsrp_interface_group: + description: + - Name of an existing HSRP group. + type: str + aliases: [ name, hsrp_group ] + secondary_virtual_ip: + description: + - The version of the compatibility catalog. + type: str + aliases: [ vip, secondary_vip ] + state: + description: + - Use C(present) or C(absent) for adding or removing. + - Use C(query) for listing an object or multiple objects. + type: str + choices: [ absent, present, query ] + default: present +extends_documentation_fragment: +- cisco.aci.aci +- cisco.aci.annotation +- cisco.aci.owner + +notes: +- The C(tenant), C(l3out), C(logical_node_profile), C(logical_interface_profile), C(hsrp_interface_profile) and C(hsrp_group) must exist before using + this module in your playbook. The M(cisco.aci.aci_tenant), M(cisco.aci.aci_l3out), M(cisco.aci.aci_l3out_logical_node_profile), + M(cisco.aci.aci_l3out_logical_interface_profile), M(cisco.aci.aci_l3out_hsrp_interface_profile) and M(cisco.aci.aci_l3out_hsrp_group) can be used for + this. +seealso: +- module: aci_tenant +- module: aci_l3out +- module: aci_l3out_logical_node_profile +- module: aci_l3out_logical_interface_profile +- module: aci_l3out_hsrp_interface_profile +- module: aci_l3out_hsrp_group +- name: APIC Management Information Model reference + description: More information about the internal APIC class B(hsrp:SecVip). + link: https://developer.cisco.com/docs/apic-mim-ref/ +author: +- Shreyas Srish (@shrsr) +""" + +EXAMPLES = r""" +- name: Add a HSRP secondary virtual ip + cisco.aci.aci_l3out_hsrp_secondary_vip: + host: apic + username: admin + password: SomeSecretPassword + tenant: my_tenant + l3out: my_l3out + node_profile: my_node_profile + interface_profile: my_interface_profile + hsrp_group: my_hsrp_group + secondary_virtual_ip: 191.1.1.1 + state: present + delegate_to: localhost + +- name: Delete a HSRP secondary virtual ip + cisco.aci.aci_l3out_hsrp_secondary_vip: + host: apic + username: admin + password: SomeSecretPassword + tenant: my_tenant + l3out: my_l3out + node_profile: my_node_profile + interface_profile: my_interface_profile + hsrp_group: my_hsrp_interface_group + secondary_virtual_ip: 191.1.1.1 + state: absent + delegate_to: localhost + +- name: Query a HSRP secondary virtual ip + cisco.aci.aci_l3out_hsrp_secondary_vip: + host: apic + username: admin + password: SomeSecretPassword + tenant: my_tenant + l3out: my_l3out + node_profile: my_node_profile + interface_profile: my_interface_profile + hsrp_group: my_hsrp_group + secondary_virtual_ip: 191.1.1.1 + state: query + delegate_to: localhost + register: query_result + +- name: Query all HSRP secondary virtual ips + cisco.aci.aci_l3out_hsrp_secondary_vip: + host: apic + username: admin + password: SomeSecretPassword + tenant: my_tenant + l3out: my_l3out + node_profile: my_node_profile + interface_profile: my_interface_profile + hsrp_group: my_hsrp_group + state: query + delegate_to: localhost + register: query_result +""" + +RETURN = r""" +current: + description: The existing configuration from the APIC after the module has finished + returned: success + type: list + sample: + [ + { + "fvTenant": { + "attributes": { + "descr": "Production environment", + "dn": "uni/tn-production", + "name": "production", + "nameAlias": "", + "ownerKey": "", + "ownerTag": "" + } + } + } + ] +error: + description: The error information as returned from the APIC + returned: failure + type: dict + sample: + { + "code": "122", + "text": "unknown managed object class foo" + } +raw: + description: The raw output returned by the APIC REST API (xml or json) + returned: parse error + type: str + sample: '' +sent: + description: The actual/minimal configuration pushed to the APIC + returned: info + type: list + sample: + { + "fvTenant": { + "attributes": { + "descr": "Production environment" + } + } + } +previous: + description: The original configuration from the APIC before the module has started + returned: info + type: list + sample: + [ + { + "fvTenant": { + "attributes": { + "descr": "Production", + "dn": "uni/tn-production", + "name": "production", + "nameAlias": "", + "ownerKey": "", + "ownerTag": "" + } + } + } + ] +proposed: + description: The assembled configuration from the user-provided parameters + returned: info + type: dict + sample: + { + "fvTenant": { + "attributes": { + "descr": "Production environment", + "name": "production" + } + } + } +filter_string: + description: The filter string used for the request + returned: failure or debug + type: str + sample: ?rsp-prop-include=config-only +method: + description: The HTTP method used for the request to the APIC + returned: failure or debug + type: str + sample: POST +response: + description: The HTTP response from the APIC + returned: failure or debug + type: str + sample: OK (30 bytes) +status: + description: The HTTP status from the APIC + returned: failure or debug + type: int + sample: 200 +url: + description: The HTTP url used for the request to the APIC + returned: failure or debug + type: str + sample: https://10.11.12.13/api/mo/uni/tn-production.json +""" + + +from ansible.module_utils.basic import AnsibleModule +from ansible_collections.cisco.aci.plugins.module_utils.aci import ACIModule, aci_argument_spec, aci_annotation_spec, aci_owner_spec + + +def main(): + argument_spec = aci_argument_spec() + argument_spec.update(aci_annotation_spec()) + argument_spec.update(aci_owner_spec()) + argument_spec.update( + tenant=dict(type="str", aliases=["tenant_name"]), + l3out=dict(type="str", aliases=["l3out_name"]), + node_profile=dict(type="str", aliases=["node_profile_name", "logical_node"]), + interface_profile=dict(type="str", aliases=["interface_profile_name", "logical_interface"]), + hsrp_interface_group=dict(type="str", aliases=["name", "hsrp_group"]), + secondary_virtual_ip=dict(type="str", aliases=["vip", "secondary_vip"]), + state=dict(type="str", default="present", choices=["absent", "present", "query"]), + ) + + module = AnsibleModule( + argument_spec=argument_spec, + supports_check_mode=True, + required_if=[ + ["state", "absent", ["tenant", "l3out", "node_profile", "interface_profile", "hsrp_interface_group", "secondary_virtual_ip"]], + ["state", "present", ["tenant", "l3out", "node_profile", "interface_profile", "hsrp_interface_group", "secondary_virtual_ip"]], + ], + ) + + tenant = module.params.get("tenant") + l3out = module.params.get("l3out") + node_profile = module.params.get("node_profile") + interface_profile = module.params.get("interface_profile") + hsrp_interface_group = module.params.get("hsrp_interface_group") + secondary_virtual_ip = module.params.get("secondary_virtual_ip") + 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="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(node_profile), + module_object=node_profile, + target_filter={"name": node_profile}, + ), + subclass_3=dict( + aci_class="l3extLIfP", + aci_rn="lifp-[{0}]".format(interface_profile), + module_object=interface_profile, + target_filter={"name": interface_profile}, + ), + subclass_4=dict( + aci_class="hsrpIfP", + aci_rn="hsrpIfP", + module_object=interface_profile, + target_filter={"name": interface_profile}, + ), + subclass_5=dict( + aci_class="hsrpGroupP", + aci_rn="hsrpGroupP-{0}".format(hsrp_interface_group), + module_object=hsrp_interface_group, + target_filter={"name": hsrp_interface_group}, + ), + subclass_6=dict( + aci_class="hsrpSecVip", + aci_rn="hsrpSecVip-[{0}]".format(secondary_virtual_ip), + module_object=secondary_virtual_ip, + target_filter={"ip": secondary_virtual_ip}, + ), + ) + + aci.get_existing() + + if state == "present": + aci.payload(aci_class="hsrpSecVip", class_config=dict(ip=secondary_virtual_ip)) + + aci.get_diff(aci_class="hsrpSecVip") + + aci.post_config() + + elif state == "absent": + aci.delete_config() + + aci.exit_json() + + +if __name__ == "__main__": + main() diff --git a/ansible_collections/cisco/aci/plugins/modules/aci_l3out_interface.py b/ansible_collections/cisco/aci/plugins/modules/aci_l3out_interface.py index f9a43b012..1f8b86070 100644 --- a/ansible_collections/cisco/aci/plugins/modules/aci_l3out_interface.py +++ b/ansible_collections/cisco/aci/plugins/modules/aci_l3out_interface.py @@ -1,6 +1,8 @@ #!/usr/bin/python # -*- coding: utf-8 -*- +# Copyright: (c) 2021, Tim Cragg (@timcragg) +# Copyright: (c) 2023, Akini Ross (@akinross) # GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) from __future__ import absolute_import, division, print_function @@ -51,14 +53,19 @@ options: type: str path_ep: description: - - Path to interface - - Interface Policy Group name for Port-channels and vPCs - - Port number for single ports (e.g. "eth1/12") + - Path to interface. + - Interface Policy Group name for Port-channels and vPCs. + - Port number for single ports (e.g. "eth1/12"). type: str encap: description: - - encapsulation on the interface (e.g. "vlan-500") + - The encapsulation on the interface (e.g. "vlan-500"). type: str + encap_scope: + description: + - The scope of the encapsulation on the interface. + type: str + choices: [ vrf, local ] address: description: - IP address. @@ -80,7 +87,7 @@ options: choices: [ l3-port, sub-interface, ext-svi ] mode: description: - - Interface mode, only used if instance_type is ext-svi + - Interface mode, only used if instance_type is ext-svi. type: str choices: [ regular, native, untagged ] state: @@ -95,19 +102,51 @@ options: - SVI auto state. type: str choices: [ enabled, disabled ] + description: + description: + - The description of the interface. + type: str + aliases: [ descr] + mac: + description: + - The MAC address of the interface. + type: str + aliases: [ mac_address ] + micro_bfd: + description: + - Enable micro BFD on the interface. + - Micro BFD should only be configured on Infra SR-MPLS L3Outs Direct Port Channel Interfaces. + type: bool + micro_bfd_destination: + description: + - The micro BFD destination address of the interface. + type: str + aliases: [ micro_bfd_address, micro_bfd_destination_address ] + micro_bfd_timer: + description: + - The micro BFD start timer in seconds. + - The APIC defaults to C(0) when unset during creation. + type: int + aliases: [ micro_bfd_start_timer, micro_bfd_start ] extends_documentation_fragment: - cisco.aci.aci - cisco.aci.annotation +notes: +- The C(tenant), C(l3out), C(node_profile) and the C(interface_profile) must exist before using this module in your playbook. + The M(cisco.aci.aci_tenant), M(cisco.aci.aci_l3out), M(cisco.aci.aci_l3out_logical_node_profile) and + M(cisco.aci.aci_l3out_logical_interface_profile) can be used for this. seealso: +- module: aci_tenant - module: aci_l3out - module: aci_l3out_logical_node_profile +- module: aci_l3out_logical_interface_profile - name: APIC Management Information Model reference description: More information about the internal APIC class B(l3ext:RsPathL3OutAtt) link: https://developer.cisco.com/docs/apic-mim-ref/ author: - Tim Cragg (@timcragg) -- Marcel Zehnder (@maercu) +- Akini Ross (@akinross) """ EXAMPLES = r""" @@ -146,6 +185,25 @@ EXAMPLES = r""" state: present delegate_to: localhost +- name: Add direct port channel interface in the infra SR-MPLS l3out interface profile with micro BFD enabled + aci_l3out_interface: + host: apic + username: admin + password: SomeSecretPassword + tenant: infra + l3out: ansible_infra_sr_mpls_l3out + interface_profile: ansible_infra_sr_mpls_l3out_interface_profile + pod_id: 1 + node_id: 101 + path_ep: pc_ansible_test + interface_type: l3-port + addr: 192.168.90.1/24 + micro_bfd: true + micro_bfd_destination: 192.168.90.2 + micro_bfd_timer: 75 + state: present + delegate_to: localhost + - name: Delete an interface cisco.aci.aci_l3out_interface: host: apic @@ -307,15 +365,28 @@ def main(): interface_type=dict(type="str", choices=["l3-port", "sub-interface", "ext-svi"]), mode=dict(type="str", choices=["regular", "native", "untagged"]), encap=dict(type="str"), + encap_scope=dict(type="str", choices=["vrf", "local"]), auto_state=dict(type="str", choices=["enabled", "disabled"]), + description=dict(type="str", aliases=["descr"]), + mac=dict(type="str", aliases=["mac_address"]), + micro_bfd=dict(type="bool"), + micro_bfd_destination=dict(type="str", aliases=["micro_bfd_address", "micro_bfd_destination_address"]), + micro_bfd_timer=dict(type="int", aliases=["micro_bfd_start_timer", "micro_bfd_start"]), ) module = AnsibleModule( argument_spec=argument_spec, supports_check_mode=True, - required_if=[["state", "present", ["interface_type", "pod_id", "node_id", "path_ep"]], ["state", "absent", ["pod_id", "node_id", "path_ep"]]], + required_if=[ + ["state", "present", ["interface_type", "pod_id", "node_id", "path_ep"]], + ["state", "absent", ["pod_id", "node_id", "path_ep"]], + ["micro_bfd", True, ["micro_bfd_destination"]], + ], + required_by={"micro_bfd_timer": "micro_bfd", "micro_bfd_destination": "micro_bfd"}, ) + aci = ACIModule(module) + tenant = module.params.get("tenant") l3out = module.params.get("l3out") node_profile = module.params.get("node_profile") @@ -330,9 +401,14 @@ def main(): interface_type = module.params.get("interface_type") mode = module.params.get("mode") encap = module.params.get("encap") + encap_scope = module.params.get("encap_scope") auto_state = module.params.get("auto_state") + description = module.params.get("description") + mac = module.params.get("mac") + micro_bfd = aci.boolean(module.params.get("micro_bfd")) + micro_bfd_destination = module.params.get("micro_bfd_destination") + micro_bfd_timer = module.params.get("micro_bfd_timer") - aci = ACIModule(module) if node_id and "-" in node_id: path_type = "protpaths" else: @@ -342,6 +418,12 @@ def main(): if pod_id and node_id and path_ep: path_dn = "topology/pod-{0}/{1}-{2}/pathep-[{3}]".format(pod_id, path_type, node_id, path_ep) + child_classes = [] + child_configs = [] + if micro_bfd is not None: + child_classes.append("bfdMicroBfdP") + child_configs.append(dict(bfdMicroBfdP=dict(attributes=dict(adminState=micro_bfd, dst=micro_bfd_destination, stTm=micro_bfd_timer)))) + aci.construct_url( root_class=dict( aci_class="fvTenant", @@ -367,7 +449,13 @@ def main(): module_object=interface_profile, target_filter={"name": interface_profile}, ), - subclass_4=dict(aci_class="l3extRsPathL3OutAtt", aci_rn="rspathL3OutAtt-[{0}]".format(path_dn), module_object=path_dn, target_filter={"tDn": path_dn}), + subclass_4=dict( + aci_class="l3extRsPathL3OutAtt", + aci_rn="rspathL3OutAtt-[{0}]".format(path_dn), + module_object=path_dn, + target_filter={"tDn": path_dn}, + ), + child_classes=child_classes, ) aci.get_existing() @@ -375,7 +463,20 @@ def main(): if state == "present": aci.payload( aci_class="l3extRsPathL3OutAtt", - class_config=dict(tDn=path_dn, addr=address, ipv6Dad=ipv6_dad, mtu=mtu, ifInstT=interface_type, mode=mode, encap=encap, autostate=auto_state), + class_config=dict( + tDn=path_dn, + addr=address, + ipv6Dad=ipv6_dad, + mtu=mtu, + ifInstT=interface_type, + mode=mode, + encap=encap, + encapScope="ctx" if encap_scope == "vrf" else encap_scope, + autostate=auto_state, + descr=description, + mac=mac, + ), + child_configs=child_configs, ) aci.get_diff(aci_class="l3extRsPathL3OutAtt") diff --git a/ansible_collections/cisco/aci/plugins/modules/aci_l3out_interface_secondary_ip.py b/ansible_collections/cisco/aci/plugins/modules/aci_l3out_interface_secondary_ip.py index d8311dad5..e127e1ff6 100644 --- a/ansible_collections/cisco/aci/plugins/modules/aci_l3out_interface_secondary_ip.py +++ b/ansible_collections/cisco/aci/plugins/modules/aci_l3out_interface_secondary_ip.py @@ -16,9 +16,9 @@ ANSIBLE_METADATA = { DOCUMENTATION = r""" --- module: aci_l3out_interface_secondary_ip -short_description: Manage Layer 3 Outside (L3Out) interface secondary IP addresses (l3ext:Ip). +short_description: Manage Layer 3 Outside (L3Out) interface secondary IP addresses (l3ext:Ip) description: -- Manage Layer 3 Outside (L3Out) interface secondary IP addresses (l3ext:Ip). +- Manage Layer 3 Outside (L3Out) interface secondary IP addresses. options: tenant: description: @@ -89,7 +89,7 @@ seealso: - module: aci_l3out_logical_interface_profile - module: aci_l3out_logical_interface - name: APIC Management Information Model reference - description: More information about the internal APIC class B(l3ext:RsPathL3OutAtt) + description: More information about the internal APIC class B(l3ext:Ip) link: https://developer.cisco.com/docs/apic-mim-ref/ author: - Marcel Zehnder (@maercu) diff --git a/ansible_collections/cisco/aci/plugins/modules/aci_l3out_logical_interface_profile.py b/ansible_collections/cisco/aci/plugins/modules/aci_l3out_logical_interface_profile.py index db5890205..cd32ccb5a 100644 --- a/ansible_collections/cisco/aci/plugins/modules/aci_l3out_logical_interface_profile.py +++ b/ansible_collections/cisco/aci/plugins/modules/aci_l3out_logical_interface_profile.py @@ -1,6 +1,7 @@ #!/usr/bin/python # -*- coding: utf-8 -*- +# Copyright: (c) 2024, Gaspard Micol (@gmicol) # 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 @@ -18,39 +19,96 @@ description: options: tenant: description: - - Name of an existing tenant. + - The name of an existing tenant. type: str aliases: [ tenant_name ] l3out: description: - - Name of an existing L3Out. + - The name of an existing L3Out. type: str aliases: [ l3out_name ] node_profile: description: - - Name of the node profile. + - The name of the node profile. type: str aliases: [ node_profile_name, logical_node ] interface_profile: description: - - Name of the interface profile. + - The name of the logical interface profile. type: str aliases: [ name, interface_profile_name, logical_interface ] nd_policy: description: - - Name of the neighbor discovery interface policy. + - The name of the neighbor discovery interface policy. type: str - default: "" egress_dpp_policy: description: - - Name of the egress data plane policing policy. + - The name of the egress data plane policing policy. type: str - default: "" ingress_dpp_policy: description: - - Name of the ingress data plane policing policy. + - The name of the ingress data plane policing policy. type: str - default: "" + qos_priority: + description: + - The QoS priority class ID. + - The APIC defaults to C(unspecified) when unset during creation. + type: str + choices: [ level1, level2, level3, level4, level5, level6, unspecified ] + aliases: [ priority, prio ] + qos_custom_policy: + description: + - The name of the QoS custom policy. + type: str + aliases: [ qos_custom_policy_name ] + pim_v4_interface_profile: + description: + - The PIM IPv4 interface profile. + type: dict + suboptions: + tenant: + description: + - The name of the tenant to which the PIM IPv4 interface policy belongs. + type: str + aliases: [ tenant_name ] + pim: + description: + - The name of the PIM IPv4 interface policy. + type: str + aliases: [ pim_interface_policy, name ] + aliases: [ pim_v4 ] + pim_v6_interface_profile: + description: + - The PIM IPv6 interface profile. + type: dict + suboptions: + tenant: + description: + - The name of the tenant to which the PIM IPv6 interface policy belongs. + type: str + aliases: [ tenant_name ] + pim: + description: + - The name of the PIM IPv6 interface policy. + type: str + aliases: [ pim_interface_policy, name ] + aliases: [ pim_v6 ] + igmp_interface_profile: + description: + - The IGMP interface profile. + type: dict + suboptions: + tenant: + description: + - The name of the tenant to which the IGMP interface policy belongs. + type: str + aliases: [ tenant_name ] + igmp: + description: + - The name of the IGMP interface policy. + type: str + aliases: [ igmp_interface_policy, name ] + aliases: [ igmp ] description: description: - The description for the logical interface profile. @@ -68,14 +126,19 @@ extends_documentation_fragment: - cisco.aci.annotation - cisco.aci.owner +notes: +- The I(tenant), I(l3out) and I(node_profile) 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_logical_node_profile) can be used for this. seealso: -- module: aci_l3out -- module: aci_l3out_logical_node_profile +- module: cisco.aci.aci_tenant +- module: cisco.aci.aci_l3out +- module: cisco.aci.aci_l3out_logical_node_profile - name: APIC Management Information Model reference - description: More information about the internal APIC classes + description: More information about the internal APIC class B(l3ext:LIfP). link: https://developer.cisco.com/docs/apic-mim-ref/ author: - Marcel Zehnder (@maercu) +- Gaspard Micol (@gmicol) """ EXAMPLES = r""" @@ -91,7 +154,7 @@ EXAMPLES = r""" state: present delegate_to: localhost -- name: Delete an interface profile +- name: Query an interface profile cisco.aci.aci_l3out_logical_interface_profile: host: apic username: admin @@ -100,30 +163,30 @@ EXAMPLES = r""" l3out: my_l3out node_profile: my_node_profile interface_profile: my_interface_profile - state: absent + state: query delegate_to: localhost + register: query_result -- name: Query an interface profile +- name: Query all interface profiles cisco.aci.aci_l3out_logical_interface_profile: host: apic username: admin password: SomeSecretPassword - tenant: my_tenant - l3out: my_l3out - node_profile: my_node_profile - interface_profile: my_interface_profile state: query delegate_to: localhost register: query_result -- name: Query all interface profiles +- name: Delete an interface profile cisco.aci.aci_l3out_logical_interface_profile: host: apic username: admin password: SomeSecretPassword - state: query + tenant: my_tenant + l3out: my_l3out + node_profile: my_node_profile + interface_profile: my_interface_profile + state: absent delegate_to: localhost - register: query_result """ RETURN = r""" @@ -233,7 +296,14 @@ url: from ansible.module_utils.basic import AnsibleModule -from ansible_collections.cisco.aci.plugins.module_utils.aci import ACIModule, aci_argument_spec, aci_annotation_spec, aci_owner_spec +from ansible_collections.cisco.aci.plugins.module_utils.aci import ( + ACIModule, + aci_argument_spec, + aci_annotation_spec, + aci_owner_spec, + pim_interface_profile_spec, + igmp_interface_profile_spec, +) def main(): @@ -245,9 +315,14 @@ def main(): l3out=dict(type="str", aliases=["l3out_name"]), node_profile=dict(type="str", aliases=["node_profile_name", "logical_node"]), interface_profile=dict(type="str", aliases=["name", "interface_profile_name", "logical_interface"]), - nd_policy=dict(type="str", default=""), - egress_dpp_policy=dict(type="str", default=""), - ingress_dpp_policy=dict(type="str", default=""), + nd_policy=dict(type="str"), + egress_dpp_policy=dict(type="str"), + ingress_dpp_policy=dict(type="str"), + qos_priority=dict(type="str", choices=["level1", "level2", "level3", "level4", "level5", "level6", "unspecified"], aliases=["priority", "prio"]), + qos_custom_policy=dict(type="str", aliases=["qos_custom_policy_name"]), + pim_v4_interface_profile=dict(type="dict", options=pim_interface_profile_spec(), aliases=["pim_v4"]), + pim_v6_interface_profile=dict(type="dict", options=pim_interface_profile_spec(), aliases=["pim_v6"]), + igmp_interface_profile=dict(type="dict", options=igmp_interface_profile_spec(), aliases=["igmp"]), state=dict(type="str", default="present", choices=["absent", "present", "query"]), description=dict(type="str", aliases=["descr"]), ) @@ -268,11 +343,19 @@ def main(): nd_policy = module.params.get("nd_policy") egress_dpp_policy = module.params.get("egress_dpp_policy") ingress_dpp_policy = module.params.get("ingress_dpp_policy") + qos_priority = module.params.get("qos_priority") + qos_custom_policy = module.params.get("qos_custom_policy") description = module.params.get("description") state = module.params.get("state") aci = ACIModule(module) + extra_child_classes = dict( + pimIPV6IfP=dict(rs_class="pimRsV6IfPol", attribute_input=module.params.get("pim_v6_interface_profile")), + pimIfP=dict(rs_class="pimRsIfPol", attribute_input=module.params.get("pim_v4_interface_profile")), + igmpIfP=dict(rs_class="igmpRsIfPol", attribute_input=module.params.get("igmp_interface_profile")), + ) + aci.construct_url( root_class=dict( aci_class="fvTenant", @@ -294,11 +377,11 @@ def main(): ), subclass_3=dict( aci_class="l3extLIfP", - aci_rn="lifp-[{0}]".format(interface_profile), + aci_rn="lifp-{0}".format(interface_profile), module_object=interface_profile, target_filter={"name": interface_profile}, ), - child_classes=["l3extRsNdIfPol", "l3extRsIngressQosDppPol", "l3extRsEgressQosDppPol"], + child_classes=list(extra_child_classes.keys()) + ["l3extRsEgressQosDppPol", "l3extRsIngressQosDppPol", "l3extRsLIfPCustQosPol", "l3extRsNdIfPol"], ) aci.get_existing() @@ -308,8 +391,67 @@ def main(): dict(l3extRsNdIfPol=dict(attributes=dict(tnNdIfPolName=nd_policy))), dict(l3extRsIngressQosDppPol=dict(attributes=dict(tnQosDppPolName=ingress_dpp_policy))), dict(l3extRsEgressQosDppPol=dict(attributes=dict(tnQosDppPolName=egress_dpp_policy))), + dict(l3extRsLIfPCustQosPol=dict(attributes=dict(tnQosCustomPolName=qos_custom_policy))), ] - aci.payload(aci_class="l3extLIfP", class_config=dict(name=interface_profile, descr=description), child_configs=child_configs) + for class_name, attribute in extra_child_classes.items(): + attribute_input = attribute.get("attribute_input") + if attribute_input is not None: + rs_class = attribute.get("rs_class") + if all(value is None for value in attribute_input.values()) and isinstance(aci.existing, list) and len(aci.existing) > 0: + for child in aci.existing[0].get("l3extLIfP", {}).get("children", {}): + if child.get(class_name): + child_configs.append( + { + class_name: dict( + attributes=dict(status="deleted"), + ), + } + ) + elif all(value is not None for value in attribute_input.values()): + if rs_class in ["pimRsV6IfPol", "pimRsIfPol"]: + child_configs.append( + { + class_name: dict( + attributes={}, + children=[ + { + rs_class: dict( + attributes=dict( + tDn="uni/tn-{0}/pimifpol-{1}".format(attribute_input.get("tenant"), attribute_input.get("pim")) + ) + ) + }, + ], + ) + } + ) + elif rs_class == "igmpRsIfPol": + child_configs.append( + { + class_name: dict( + attributes={}, + children=[ + { + rs_class: dict( + attributes=dict( + tDn="uni/tn-{0}/igmpIfPol-{1}".format(attribute_input.get("tenant"), attribute_input.get("igmp")) + ) + ) + }, + ], + ) + } + ) + + aci.payload( + aci_class="l3extLIfP", + class_config=dict( + name=interface_profile, + prio=qos_priority, + descr=description, + ), + child_configs=child_configs, + ) aci.get_diff(aci_class="l3extLIfP") diff --git a/ansible_collections/cisco/aci/plugins/modules/aci_l3out_logical_interface_profile_ospf_policy.py b/ansible_collections/cisco/aci/plugins/modules/aci_l3out_logical_interface_profile_ospf_policy.py index 798a82111..2d1a407ae 100644 --- a/ansible_collections/cisco/aci/plugins/modules/aci_l3out_logical_interface_profile_ospf_policy.py +++ b/ansible_collections/cisco/aci/plugins/modules/aci_l3out_logical_interface_profile_ospf_policy.py @@ -2,6 +2,7 @@ # -*- coding: utf-8 -*- # Copyright: (c) 2022, Jason Juenger (@jasonjuenger) +# Copyright: (c) 2023, Gaspard Micol (@gmicol) # 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 @@ -13,9 +14,9 @@ ANSIBLE_METADATA = {"metadata_version": "1.1", "status": ["preview"], "supported DOCUMENTATION = r""" --- module: aci_l3out_logical_interface_profile_ospf_policy -short_description: Manage Layer 3 Outside (L3Out) logical interface profile (l3ext:LIfP) OSPF policy (ospfIfP) +short_description: Manage Layer 3 Outside (L3Out) OSPF interface profile (ospf:IfP) description: -- Manage L3Out interface profile OSPF policies on Cisco ACI fabrics. +- Manage L3Out logical interface profile OSPF policies on Cisco ACI fabrics. options: tenant: description: @@ -64,14 +65,22 @@ extends_documentation_fragment: - cisco.aci.annotation - cisco.aci.owner +notes: +- The C(tenant), C(l3out), C(node_profile), C(interface_profile) and C(ospf_policy) must exist before using this module in your playbook. + The M(cisco.aci.aci_tenant), M(cisco.aci.aci_l3out), M(cisco.aci.aci_l3out_logical_node_profile), M(cisco.aci.aci_l3out_logical_interface_profile) + and (cisco.aci.aci_interface_policy_ospf) can be used for this. seealso: -- module: aci_l3out -- module: aci_l3out_logical_node_profile +- module: cisco.aci.aci_tenant +- module: cisco.aci.aci_l3out +- module: cisco.aci.aci_l3out_logical_node_profile +- module: cisco.aci.aci_l3out_logical_interface_profile +- module: cisco.aci.aci_interface_policy_ospf - name: APIC Management Information Model reference - description: More information about the internal APIC classes + description: More information about the internal APIC class B(ospf:IfP). link: https://developer.cisco.com/docs/apic-mim-ref/ author: - Jason Juenger (@jasonjuenger) +- Gaspard Micol (@gmicol) """ EXAMPLES = r""" diff --git a/ansible_collections/cisco/aci/plugins/modules/aci_l3out_logical_interface_vpc_member.py b/ansible_collections/cisco/aci/plugins/modules/aci_l3out_logical_interface_vpc_member.py index 4ddd32161..822c53af7 100644 --- a/ansible_collections/cisco/aci/plugins/modules/aci_l3out_logical_interface_vpc_member.py +++ b/ansible_collections/cisco/aci/plugins/modules/aci_l3out_logical_interface_vpc_member.py @@ -94,7 +94,7 @@ notes: seealso: - module: cisco.aci.aci_l3out_logical_interface_profile - name: APIC Management Information Model reference - description: More information about the internal APIC class B(l3ext:Out). + description: More information about the internal APIC class B(l3ext:Member). link: https://developer.cisco.com/docs/apic-mim-ref/ author: - Anvitha Jain (@anvitha-jain) diff --git a/ansible_collections/cisco/aci/plugins/modules/aci_l3out_logical_node.py b/ansible_collections/cisco/aci/plugins/modules/aci_l3out_logical_node.py index 33c8a22a5..7ab756566 100644 --- a/ansible_collections/cisco/aci/plugins/modules/aci_l3out_logical_node.py +++ b/ansible_collections/cisco/aci/plugins/modules/aci_l3out_logical_node.py @@ -1,6 +1,8 @@ #!/usr/bin/python # -*- coding: utf-8 -*- +# Copyright: (c) 2021, Marcel Zehnder (@maercu) +# Copyright: (c) 2023, Akini Ross (@akinross) # 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 @@ -52,9 +54,20 @@ options: loopback_address: description: - The loopback IP address. + - The BGP-EVPN loopback IP address for Infra SR-MPLS L3Outs. - A configured loopback address can be removed by passing an empty string (see Examples). type: str aliases: [ loopback ] + mpls_transport_loopback_address: + description: + - The MPLS transport loopback IP address for Infra SR-MPLS L3Outs. + type: str + aliases: [ mpls_transport_loopback ] + sid: + description: + - The Segment ID (SID) Index for Infra SR-MPLS L3Outs. + type: str + aliases: [ segment_id ] state: description: - Use C(present) or C(absent) for adding or removing. @@ -70,10 +83,11 @@ seealso: - module: aci_l3out - module: aci_l3out_logical_node_profile - name: APIC Management Information Model reference - description: More information about the internal APIC classes B(vmm:DomP) + description: More information about the internal APIC classes B(l3ext:RsNodeL3OutAtt) link: https://developer.cisco.com/docs/apic-mim-ref/ author: - Marcel Zehnder (@maercu) +- Akini Ross (@akinross) """ EXAMPLES = r""" @@ -92,6 +106,22 @@ EXAMPLES = r""" state: present delegate_to: localhost +- name: Add a node to a infra SR-MPLS l3out node profile + cisco.aci.aci_l3out_logical_node: &aci_infra_node_profile_node + host: apic + username: admin + password: SomeSecretPassword + tenant: infra + l3out: ansible_infra_sr_mpls_l3out + node_profile: ansible_infra_sr_mpls_l3out_node_profile + pod_id: 1 + node_id: 113 + router_id_as_loopback: no + loopback_address: 50.0.0.1 + mpls_transport_loopback_address: 51.0.0.1 + sid: 500 + delegate_to: localhost + - name: Remove a loopback address from a node in node profile cisco.aci.aci_l3out_logical_node: host: apic @@ -264,6 +294,8 @@ def main(): router_id=dict(type="str"), router_id_as_loopback=dict(type="str", default="yes", choices=["yes", "no"]), loopback_address=dict(type="str", aliases=["loopback"]), + mpls_transport_loopback_address=dict(type="str", aliases=["mpls_transport_loopback"]), + sid=dict(type="str", aliases=["segment_id"]), state=dict(type="str", default="present", choices=["absent", "present", "query"]), ) @@ -274,6 +306,8 @@ def main(): ["state", "absent", ["tenant", "l3out", "node_profile", "pod_id", "node_id"]], ["state", "present", ["tenant", "l3out", "node_profile", "pod_id", "node_id"]], ], + required_by={"mpls_transport_loopback_address": "loopback_address"}, + required_together=[("mpls_transport_loopback_address", "sid")], ) tenant = module.params.get("tenant") @@ -284,6 +318,8 @@ def main(): router_id = module.params.get("router_id") router_id_as_loopback = module.params.get("router_id_as_loopback") loopback_address = module.params.get("loopback_address") + mpls_transport_loopback_address = module.params.get("mpls_transport_loopback_address") + sid = module.params.get("sid") state = module.params.get("state") tdn = None @@ -294,6 +330,9 @@ def main(): child_classes = ["l3extLoopBackIfP"] + if mpls_transport_loopback_address is not None: + child_classes.append("mplsNodeSidP") + child_configs = [] aci.construct_url( @@ -333,7 +372,12 @@ def main(): previous_loopback_address = child.get("l3extLoopBackIfP", {}).get("attributes", {}).get("addr") child_configs.append(dict(l3extLoopBackIfP=dict(attributes=dict(addr=previous_loopback_address, status="deleted")))) elif loopback_address: - child_configs.append(dict(l3extLoopBackIfP=dict(attributes=dict(addr=loopback_address)))) + loopback_address_config = dict(l3extLoopBackIfP=dict(attributes=dict(addr=loopback_address), children=[])) + if mpls_transport_loopback_address: + loopback_address_config["l3extLoopBackIfP"]["children"].append( + dict(mplsNodeSidP=dict(attributes=dict(loopbackAddr=mpls_transport_loopback_address, sidoffset=sid))) + ) + child_configs.append(loopback_address_config) aci.payload( aci_class="l3extRsNodeL3OutAtt", diff --git a/ansible_collections/cisco/aci/plugins/modules/aci_l3out_logical_node_profile.py b/ansible_collections/cisco/aci/plugins/modules/aci_l3out_logical_node_profile.py index 10eefd018..ac6b87ebe 100644 --- a/ansible_collections/cisco/aci/plugins/modules/aci_l3out_logical_node_profile.py +++ b/ansible_collections/cisco/aci/plugins/modules/aci_l3out_logical_node_profile.py @@ -1,6 +1,7 @@ #!/usr/bin/python # -*- coding: utf-8 -*- +# Copyright: (c) 2023, Akini Ross (@akinross) # 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 @@ -43,6 +44,12 @@ options: 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_dscp ] + mpls_custom_qos_policy: + description: + - The MPLS custom QoS policy name for the node profile. + - This argument should only be used for Infra SR-MPLS L3Outs. + aliases: [ mpls_custom_qos_policy_name ] + type: str state: description: - Use C(present) or C(absent) for adding or removing. @@ -62,10 +69,11 @@ extends_documentation_fragment: seealso: - module: aci_l3out - name: APIC Management Information Model reference - description: More information about the internal APIC classes B(vmm:DomP) + description: More information about the internal APIC classes B(l3ext:LNodeP). link: https://developer.cisco.com/docs/apic-mim-ref/ author: - Jason Juenger (@jasonjuenger) +- Akini Ross (@akinross) """ EXAMPLES = r""" @@ -82,6 +90,18 @@ EXAMPLES = r""" state: present delegate_to: localhost +- name: Add a new node profile with MPLS custom QOS policy to SR-MPLS infra l3out + cisco.aci.aci_l3out_logical_node_profile: + host: apic + username: admin + password: SomeSecretPassword + tenant: infra + l3out: infra_sr_mpls_l3out + node_profile: infra_sr_mpls_l3out_node_profile + mpls_custom_qos_policy: infra_mpls_custom_qos_policy + state: present + delegate_to: localhost + - name: Delete a node profile cisco.aci.aci_l3out_logical_node_profile: host: apic @@ -264,6 +284,8 @@ def main(): ], aliases=["target_dscp"], ), + # alias=dict(type="str"), not implemented because of different (api/alias/mo/uni/) api endpoint + mpls_custom_qos_policy=dict(type="str", aliases=["mpls_custom_qos_policy_name"]), state=dict(type="str", default="present", choices=["absent", "present", "query"]), name_alias=dict(type="str"), ) @@ -282,11 +304,16 @@ def main(): l3out = module.params.get("l3out") description = module.params.get("description") dscp = module.params.get("dscp") + mpls_custom_qos_policy = module.params.get("mpls_custom_qos_policy") state = module.params.get("state") name_alias = module.params.get("name_alias") aci = ACIModule(module) + child_classes = [] + if mpls_custom_qos_policy is not None: + child_classes.append("l3extRsLNodePMplsCustQosPol") + aci.construct_url( root_class=dict( aci_class="fvTenant", @@ -306,11 +333,21 @@ def main(): module_object=node_profile, target_filter={"name": node_profile}, ), + child_classes=child_classes, ) aci.get_existing() if state == "present": + child_configs = [] + if mpls_custom_qos_policy is not None: + if mpls_custom_qos_policy == "": + child_configs.append(dict(l3extRsLNodePMplsCustQosPol=dict(attributes=dict(status="deleted")))) + else: + child_configs.append( + dict(l3extRsLNodePMplsCustQosPol=dict(attributes=dict(tDn="uni/tn-infra/qosmplscustom-{0}".format(mpls_custom_qos_policy)))) + ) + aci.payload( aci_class="l3extLNodeP", class_config=dict( @@ -319,6 +356,7 @@ def main(): targetDscp=dscp, nameAlias=name_alias, ), + child_configs=child_configs, ) aci.get_diff(aci_class="l3extLNodeP") diff --git a/ansible_collections/cisco/aci/plugins/modules/aci_l3out_static_routes.py b/ansible_collections/cisco/aci/plugins/modules/aci_l3out_static_routes.py index 039593366..a8c410bb5 100644 --- a/ansible_collections/cisco/aci/plugins/modules/aci_l3out_static_routes.py +++ b/ansible_collections/cisco/aci/plugins/modules/aci_l3out_static_routes.py @@ -15,7 +15,7 @@ DOCUMENTATION = r""" module: aci_l3out_static_routes short_description: Manage Static routes object (l3ext:ipRouteP) description: -- Manage External Subnet objects (l3ext:ipRouteP) +- Manage External Subnet objects. options: description: description: @@ -86,7 +86,7 @@ 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). + description: More information about the internal APIC class B(l3ext:ipRouteP). link: https://developer.cisco.com/docs/apic-mim-ref/ author: - Anvitha Jain(@anvitha-jain) diff --git a/ansible_collections/cisco/aci/plugins/modules/aci_l3out_static_routes_nexthop.py b/ansible_collections/cisco/aci/plugins/modules/aci_l3out_static_routes_nexthop.py index 36c3afa36..b475bba5c 100644 --- a/ansible_collections/cisco/aci/plugins/modules/aci_l3out_static_routes_nexthop.py +++ b/ansible_collections/cisco/aci/plugins/modules/aci_l3out_static_routes_nexthop.py @@ -65,7 +65,7 @@ seealso: - module: aci_l3out_logical_node_profile_to_node - module: aci_l3out_static_routes - name: APIC Management Information Model reference - description: More information about the internal APIC classes B(vmm:DomP) + description: More information about the internal APIC classes B(ip:NexthopP) link: https://developer.cisco.com/docs/apic-mim-ref/ author: - Marcel Zehnder (@maercu) diff --git a/ansible_collections/cisco/aci/plugins/modules/aci_l3out_to_sr_mpls_infra_l3out.py b/ansible_collections/cisco/aci/plugins/modules/aci_l3out_to_sr_mpls_infra_l3out.py new file mode 100644 index 000000000..db621d5c8 --- /dev/null +++ b/ansible_collections/cisco/aci/plugins/modules/aci_l3out_to_sr_mpls_infra_l3out.py @@ -0,0 +1,355 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- + +# Copyright: (c) 2023, Akini Ross (@akinross) +# 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_to_sr_mpls_infra_l3out +short_description: Manage Layer 3 Outside (L3Out) to SR-MPLS Infra L3Outs objects (l3ext:ConsLbl) +description: +- Manage Layer 3 Outside (L3Out) to SR-MPLS Infra L3Outs objects on Cisco ACI fabrics. +options: + tenant: + description: + - The name of an existing tenant. + type: str + aliases: [ tenant_name ] + l3out: + description: + - The name of an existing SR MPLS VRF L3Out. + type: str + aliases: [ l3out_name, name ] + infra_l3out: + description: + - The name of an existing SR-MPLS Infra L3Out. + type: str + aliases: [ infra_l3out_name ] + external_epg: + description: + - The distinguished name (DN) of the external EPG. + type: str + aliases: [ external_epg_dn ] + outbound_route_map: + description: + - The distinguished name (DN) of the outbound route map. + type: str + aliases: [ outbound_route_map_dn, outbound ] + inbound_route_map: + description: + - The distinguished name (DN) of the inbound route map. + - Use an empty string to remove the inbound route map. + type: str + aliases: [ inbound_route_map_dn, inbound ] + 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 +- cisco.aci.annotation +- cisco.aci.owner + +notes: +- The C(tenant) and C(l3out) 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:ConsLbl). + link: https://developer.cisco.com/docs/apic-mim-ref/ +author: +- Akini Ross (@akinross) +""" + +EXAMPLES = r""" +- name: Add a new l3out to sr-mpls infra l3out + cisco.aci.aci_l3out_to_sr_mpls_infra_l3out: + host: apic + username: admin + password: SomeSecretPassword + tenant: production + l3out: prod_l3out + description: L3Out for Production tenant + infra_l3out: infra_l3out_name + external_epg: uni/tn-production/out-l3out_name/instP-external_epg_name + outbound_route_map: uni/tn-production/prof-outbound_route_map_name + inbound_route_map: uni/tn-production/prof-inbound_route_map_name + state: present + delegate_to: localhost + +- name: Delete a l3out to sr-mpls infra l3out + cisco.aci.aci_l3out_to_sr_mpls_infra_l3out: + host: apic + username: admin + password: SomeSecretPassword + tenant: production + l3out: prod_l3out + infra_l3out: infra_l3out_name + state: absent + delegate_to: localhost + +- name: Query a l3out to sr-mpls infra l3out + cisco.aci.aci_l3out_to_sr_mpls_infra_l3out: + host: apic + username: admin + password: SomeSecretPassword + tenant: production + l3out: prod_l3out + state: query + delegate_to: localhost + register: query_result + +- name: Query all l3out to sr-mpls infra l3outs + cisco.aci.aci_l3out_to_sr_mpls_infra_l3out: + host: apic + username: admin + password: SomeSecretPassword + state: query + delegate_to: localhost + register: query_all_result +""" + +RETURN = r""" +current: + description: The existing configuration from the APIC after the module has finished + returned: success + type: list + sample: + [ + { + "fvTenant": { + "attributes": { + "descr": "Production environment", + "dn": "uni/tn-production", + "name": "production", + "nameAlias": "", + "ownerKey": "", + "ownerTag": "" + } + } + } + ] +error: + description: The error information as returned from the APIC + returned: failure + type: dict + sample: + { + "code": "122", + "text": "unknown managed object class foo" + } +raw: + description: The raw output returned by the APIC REST API (xml or json) + returned: parse error + type: str + sample: '' +sent: + description: The actual/minimal configuration pushed to the APIC + returned: info + type: list + sample: + { + "fvTenant": { + "attributes": { + "descr": "Production environment" + } + } + } +previous: + description: The original configuration from the APIC before the module has started + returned: info + type: list + sample: + [ + { + "fvTenant": { + "attributes": { + "descr": "Production", + "dn": "uni/tn-production", + "name": "production", + "nameAlias": "", + "ownerKey": "", + "ownerTag": "" + } + } + } + ] +proposed: + description: The assembled configuration from the user-provided parameters + returned: info + type: dict + sample: + { + "fvTenant": { + "attributes": { + "descr": "Production environment", + "name": "production" + } + } + } +filter_string: + description: The filter string used for the request + returned: failure or debug + type: str + sample: ?rsp-prop-include=config-only +method: + description: The HTTP method used for the request to the APIC + returned: failure or debug + type: str + sample: POST +response: + description: The HTTP response from the APIC + returned: failure or debug + type: str + sample: OK (30 bytes) +status: + description: The HTTP status from the APIC + returned: failure or debug + type: int + sample: 200 +url: + description: The HTTP url used for the request to the APIC + returned: failure or debug + type: str + sample: https://10.11.12.13/api/mo/uni/tn-production.json +""" + +from ansible.module_utils.basic import AnsibleModule +from ansible_collections.cisco.aci.plugins.module_utils.aci import ACIModule, aci_argument_spec, aci_annotation_spec, aci_owner_spec + + +def main(): + argument_spec = aci_argument_spec() + argument_spec.update(aci_annotation_spec()) + argument_spec.update(aci_owner_spec()) + argument_spec.update( + tenant=dict(type="str", aliases=["tenant_name"]), # Not required for querying all objects + l3out=dict(type="str", aliases=["l3out_name", "name"]), # Not required for querying all objects + description=dict(type="str", aliases=["descr"]), + infra_l3out=dict(type="str", aliases=["infra_l3out_name"]), + external_epg=dict(type="str", aliases=["external_epg_dn"]), + outbound_route_map=dict(type="str", aliases=["outbound_route_map_dn", "outbound"]), + inbound_route_map=dict(type="str", aliases=["inbound_route_map_dn", "inbound"]), + 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", "infra_l3out"]], + ["state", "present", ["l3out", "tenant", "infra_l3out", "external_epg", "outbound_route_map"]], + ], + ) + + aci = ACIModule(module) + + tenant = module.params.get("tenant") + l3out = module.params.get("l3out") + description = module.params.get("description") + infra_l3out = module.params.get("infra_l3out") + external_epg = module.params.get("external_epg") + outbound_route_map = module.params.get("outbound_route_map") + inbound_route_map = module.params.get("inbound_route_map") + state = module.params.get("state") + name_alias = module.params.get("name_alias") + + # l3extRsProvLblDef, bgpDomainIdAllocator are auto-generated classes, added for query output + child_classes = ["l3extRsLblToInstP", "l3extRsLblToProfile", "l3extRsProvLblDef", "bgpDomainIdAllocator"] + + 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="l3extConsLbl", + aci_rn="conslbl-{0}".format(infra_l3out), + module_object=infra_l3out, + target_filter={"name": infra_l3out}, + ), + child_classes=child_classes, + ) + + aci.get_existing() + + if state == "present": + child_configs = [] + + if aci.existing: + children = aci.existing[0].get("l3extConsLbl", {}).get("children", []) + for child in children: + if child.get("l3extRsLblToProfile"): + tdn = child.get("l3extRsLblToProfile").get("attributes").get("tDn") + direction = child.get("l3extRsLblToProfile").get("attributes").get("direction") + route_map = outbound_route_map if direction == "export" else inbound_route_map + # Inbound route-map is removed when input is different or an empty string, otherwise ignored. + if route_map is not None and tdn != route_map: + child_configs.append(dict(l3extRsLblToProfile=dict(attributes=dict(tDn=tdn, direction=direction, status="deleted")))) + elif child.get("l3extRsLblToInstP"): + tdn = child.get("l3extRsLblToInstP").get("attributes").get("tDn") + if tdn != external_epg: + child_configs.append(dict(l3extRsLblToInstP=dict(attributes=dict(tDn=tdn, status="deleted")))) + + child_configs.append(dict(l3extRsLblToProfile=dict(attributes=dict(tDn=outbound_route_map, direction="export")))) + child_configs.append(dict(l3extRsLblToInstP=dict(attributes=dict(tDn=external_epg)))) + + if inbound_route_map: + child_configs.append(dict(l3extRsLblToProfile=dict(attributes=dict(tDn=inbound_route_map, direction="import")))) + + aci.payload( + aci_class="l3extConsLbl", + class_config=dict( + name=infra_l3out, + descr=description, + nameAlias=name_alias, + ), + child_configs=child_configs, + ) + + aci.get_diff(aci_class="l3extConsLbl") + + aci.post_config() + + elif state == "absent": + aci.delete_config() + + aci.exit_json() + + +if __name__ == "__main__": + main() diff --git a/ansible_collections/cisco/aci/plugins/modules/aci_maintenance_group_node.py b/ansible_collections/cisco/aci/plugins/modules/aci_maintenance_group_node.py index be97ede40..30fb14403 100644 --- a/ansible_collections/cisco/aci/plugins/modules/aci_maintenance_group_node.py +++ b/ansible_collections/cisco/aci/plugins/modules/aci_maintenance_group_node.py @@ -15,7 +15,7 @@ DOCUMENTATION = r""" module: aci_maintenance_group_node short_description: Manage maintenance group nodes (fabric:NodeBlk) description: -- Manage maintenance group nodes +- Manage maintenance group nodes. options: group: description: diff --git a/ansible_collections/cisco/aci/plugins/modules/aci_match_route_destination.py b/ansible_collections/cisco/aci/plugins/modules/aci_match_route_destination.py index 973d70561..1ba471c9d 100644 --- a/ansible_collections/cisco/aci/plugins/modules/aci_match_route_destination.py +++ b/ansible_collections/cisco/aci/plugins/modules/aci_match_route_destination.py @@ -14,7 +14,7 @@ ANSIBLE_METADATA = {"metadata_version": "1.1", "status": ["preview"], "supported DOCUMENTATION = r""" --- module: aci_match_route_destination -short_description: Manage Match action rule term based on the Route Destination. (rtctrl:MatchRtDest) +short_description: Manage Match action rule term based on the Route Destination (rtctrl:MatchRtDest) description: - Match action rule terms based on the Route Destination for Subject Profiles on Cisco ACI fabrics. options: diff --git a/ansible_collections/cisco/aci/plugins/modules/aci_netflow_exporter_policy.py b/ansible_collections/cisco/aci/plugins/modules/aci_netflow_exporter_policy.py new file mode 100644 index 000000000..e45eb6217 --- /dev/null +++ b/ansible_collections/cisco/aci/plugins/modules/aci_netflow_exporter_policy.py @@ -0,0 +1,490 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- + +# Copyright: (c) 2023, Gaspard Micol (@gmicol) +# 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_netflow_exporter_policy +short_description: Manage Netflow Exporter Policy (netflow:ExporterPol) +description: +- Manage Netflow Exporter Policies for tenants on Cisco ACI fabrics. +- Exporter information for bootstrapping the netflow Collection agent. +options: + tenant: + description: + - The name of an existing tenant. + type: str + aliases: [ tenant_name ] + netflow_exporter_policy: + description: + - The name of the Netflow Exporter Policy. + type: str + aliases: [ netflow_exporter, netflow_exporter_name, name ] + dscp: + description: + - The IP DSCP value. + - The APIC defaults to C(CS2) when unset during creation. + It defaults to C(VA) for APIC versions 4.2 or prior. + 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 ] + destination_address: + description: + - The remote node destination IP address. + type: str + destination_port: + description: + - The remote node destination port. + - Accepted values are any valid TCP/UDP port range. + - The APIC defaults to C(unspecified) when unset during creation. + type: str + source_ip_type: + description: + - The type of Exporter source IP Address. + - It can be one of the available management IP Address for a given leaf or a custom IP Address. + type: str + choices: [ custom_source_ip, inband_management_ip, out_of_band_management_ip, ptep ] + custom_source_address: + description: + - The custom source IP address. + - It can only be used if O(source_ip_type=custom_source_ip). + type: str + associated_epg: + description: + - The associated EPG. + - To remove the current associated EPG, pass an empty dictionary. + type: dict + aliases: [ epg ] + suboptions: + tenant: + description: + - The name of the tenant to which the associated AP/EPG belong. + type: str + ap: + description: + - The name of the associated Application Profile to which the associated EPG belongs. + type: str + epg: + description: + - The name of the associated EPG. + type: str + associated_extepg: + description: + - The associated external EPG. + - To remove the current associated external EPG, pass an empty dictionary. + type: dict + aliases: [ external_epg, associated_external_epg ] + suboptions: + tenant: + description: + - The name of the tenant to which the associated L3Out/external EPG belong. + type: str + l3out: + description: + - The name of the L3Out to which the associated external EPG belongs. + type: str + extepg: + description: + - The name of the associated EPG. + type: str + associated_vrf: + description: + - The associated VRF. + - To remove the current associated VRF, pass an empty dictionary. + type: dict + aliases: [ vrf, context, associated_context ] + suboptions: + tenant: + description: + - The name of the tenant to which the associated VRF belongs. + type: str + vrf: + description: + - The name of the associated VRF. + type: str + description: + description: + - The description for the Netflow Exporter 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 +extends_documentation_fragment: +- cisco.aci.aci +- cisco.aci.annotation +- cisco.aci.owner + +notes: +- The I(tenant) must exist before using this module in your playbook. + The M(cisco.aci.aci_tenant) can be used for this. +- The I(associated_epg) and I(associated_extepg) are mutually exclusive. +- If the I(associated_epg) is used, the I(epg), the(tenant) and + the I(ap) must exist before using this module in your play book. + The M(cisco.aci.aci_epg) and the M(cisco.aci.aci_ap) can be used for this. +- If the I(associated_extepg) is used, the I(extepg), the(tenant) and + the I(l3out) must exist before using this module in your play book. + The M(cisco.aci.aci_l3out_extepg) and the M(cisco.aci.aci_l3out) can be used for this. +- If the I(associated_vrf) is used, the I(vrf) and the I(tenant) must exist + before using this module in your play book. + The M(cisco.aci.aci_vrf) can be used for this. +seealso: +- module: cisco.aci.aci_tenant +- module: cisco.aci.aci_vrf +- module: cisco.aci.aci_ap +- module: cisco.aci.aci_epg +- module: cisco.aci.aci_l3out +- module: cisco.aci.aci_l3out_extepg +- name: APIC Management Information Model reference + description: More information about the internal APIC class B(netflow:ExporterPol). + link: https://developer.cisco.com/docs/apic-mim-ref/ +author: +- Gaspard Micol (@gmicol) +""" + +EXAMPLES = r""" +- name: Add a new Netflow Exporter Policy + cisco.aci.aci_netflow_exporter_policy: + host: apic + username: admin + password: SomeSecretPassword + tenant: my_tenant + netflow_exporter_policy: my_netflow_exporter_policy + dscp: CS2 + destination_address: 11.11.11.1 + destination_port: 25 + source_ip_type: custom_source_ip + custom_source_address: 11.11.11.2 + associated_epg: + tenant: my_tenant + ap: my_ap + epg: my_epg + associated_vrf: + tenant: my_tenant + vrf: my_vrf + state: present + delegate_to: localhost + +- name: Remove associated EPG and VRF from the new Netflow Exporter Policy + cisco.aci.aci_netflow_exporter_policy: + host: apic + username: admin + password: SomeSecretPassword + tenant: my_tenant + netflow_exporter_policy: my_netflow_exporter_policy + associated_epg: {} + associated_vrf: {} + delegate_to: localhost + +- name: Query a Netflow Exporter Policy + cisco.aci.aci_netflow_exporter_policy: + host: apic + username: admin + password: SomeSecretPassword + tenant: my_tenant + netflow_exporter_policy: my_netflow_exporter_policy + state: query + delegate_to: localhost + +- name: Query all Netflow Exporter Policies in my_tenant + cisco.aci.aci_netflow_exporter_policy: + host: apic + username: admin + password: SomeSecretPassword + tenant: my_tenant + state: query + delegate_to: localhost + +- name: Query all Netflow Exporter Policies + cisco.aci.aci_netflow_exporter_policy: + host: apic + username: admin + password: SomeSecretPassword + state: query + delegate_to: localhost + +- name: Delete a Netflow Exporter Policy + cisco.aci.aci_netflow_exporter_policy: + host: apic + username: admin + password: SomeSecretPassword + tenant: my_tenant + netflow_exporter_policy: my_netflow_exporter_policy + 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: '' +sent: + description: The actual/minimal configuration pushed to the APIC + returned: info + type: list + sample: + { + "fvTenant": { + "attributes": { + "descr": "Production environment" + } + } + } +previous: + description: The original configuration from the APIC before the module has started + returned: info + type: list + sample: + [ + { + "fvTenant": { + "attributes": { + "descr": "Production", + "dn": "uni/tn-production", + "name": "production", + "nameAlias": "", + "ownerKey": "", + "ownerTag": "" + } + } + } + ] +proposed: + description: The assembled configuration from the user-provided parameters + returned: info + type: dict + sample: + { + "fvTenant": { + "attributes": { + "descr": "Production environment", + "name": "production" + } + } + } +filter_string: + description: The filter string used for the request + returned: failure or debug + type: str + sample: ?rsp-prop-include=config-only +method: + description: The HTTP method used for the request to the APIC + returned: failure or debug + type: str + sample: POST +response: + description: The HTTP response from the APIC + returned: failure or debug + type: str + sample: OK (30 bytes) +status: + description: The HTTP status from the APIC + returned: failure or debug + type: int + sample: 200 +url: + description: The HTTP url used for the request to the APIC + returned: failure or debug + type: str + sample: https://10.11.12.13/api/mo/uni/tn-production.json +""" + + +from ansible.module_utils.basic import AnsibleModule +from ansible_collections.cisco.aci.plugins.module_utils.aci import ( + ACIModule, + aci_argument_spec, + aci_annotation_spec, + aci_owner_spec, + aci_contract_dscp_spec, + associated_netflow_exporter_epg_spec, + associated_netflow_exporter_extepg_spec, + associated_netflow_exporter_vrf_spec, +) +from ansible_collections.cisco.aci.plugins.module_utils.constants import MATCH_SOURCE_IP_TYPE_NETFLOW_EXPORTER_MAPPING + + +def main(): + argument_spec = aci_argument_spec() + argument_spec.update(aci_annotation_spec()) + argument_spec.update(aci_owner_spec()) + argument_spec.update( + tenant=dict(type="str", aliases=["tenant_name"]), + netflow_exporter_policy=dict(type="str", aliases=["netflow_exporter", "netflow_exporter_name", "name"]), + dscp=dict((k, aci_contract_dscp_spec()[k]) for k in aci_contract_dscp_spec() if k != "aliases"), + destination_address=dict(type="str"), + destination_port=dict(type="str"), + source_ip_type=dict(type="str", choices=list(MATCH_SOURCE_IP_TYPE_NETFLOW_EXPORTER_MAPPING.keys())), + custom_source_address=dict(type="str"), + associated_epg=dict(type="dict", aliases=["epg"], options=associated_netflow_exporter_epg_spec()), + associated_extepg=dict(type="dict", aliases=["external_epg", "associated_external_epg"], options=associated_netflow_exporter_extepg_spec()), + associated_vrf=dict(type="dict", aliases=["vrf", "associated_context", "context"], options=associated_netflow_exporter_vrf_spec()), + description=dict(type="str", aliases=["descr"]), + state=dict(type="str", default="present", choices=["absent", "present", "query"]), + ) + + module = AnsibleModule( + argument_spec=argument_spec, + supports_check_mode=True, + required_if=[ + ["state", "absent", ["tenant", "netflow_exporter_policy"]], + ["state", "present", ["tenant", "netflow_exporter_policy", "destination_address", "destination_port"]], + ], + mutually_exclusive=[["associated_epg", "associated_extepg"]], + ) + + tenant = module.params.get("tenant") + description = module.params.get("description") + netflow_exporter_policy = module.params.get("netflow_exporter_policy") + dscp = module.params.get("dscp") + destination_address = module.params.get("destination_address") + destination_port = module.params.get("destination_port") + source_ip_type = MATCH_SOURCE_IP_TYPE_NETFLOW_EXPORTER_MAPPING.get(module.params.get("source_ip_type")) + custom_source_address = module.params.get("custom_source_address") + associated_epg = module.params.get("associated_epg") + associated_extepg = module.params.get("associated_extepg") + associated_vrf = module.params.get("associated_vrf") + state = module.params.get("state") + + aci = ACIModule(module) + + child_classes = ["netflowRsExporterToCtx", "netflowRsExporterToEPg"] + + 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="netflowExporterPol", + aci_rn="exporterpol-{0}".format(netflow_exporter_policy), + module_object=netflow_exporter_policy, + target_filter={"name": netflow_exporter_policy}, + ), + child_classes=child_classes, + ) + + aci.get_existing() + + if state == "present": + child_configs = [] + if associated_vrf is not None: + if all(value is None for value in associated_vrf.values()) and isinstance(aci.existing, list) and len(aci.existing) > 0: + for child in aci.existing[0].get("netflowExporterPol", {}).get("children", {}): + if child.get("netflowRsExporterToCtx"): + child_configs.extend([dict(netflowRsExporterToCtx=dict(attributes=dict(status="deleted")))]) + elif all(value is not None for value in associated_vrf.values()): + child_configs.extend( + [ + dict( + netflowRsExporterToCtx=dict( + attributes=dict(tDn="uni/tn-{0}/ctx-{1}".format(associated_vrf.get("tenant"), associated_vrf.get("vrf"))) + ) + ), + ] + ) + if associated_epg is not None: + if all(value is None for value in associated_epg.values()) and isinstance(aci.existing, list) and len(aci.existing) > 0: + for child in aci.existing[0].get("netflowExporterPol", {}).get("children", {}): + if child.get("netflowRsExporterToEPg"): + child_configs.extend([dict(netflowRsExporterToEPg=dict(attributes=dict(status="deleted")))]) + elif all(value is not None for value in associated_epg.values()): + child_configs.extend( + [ + dict( + netflowRsExporterToEPg=dict( + attributes=dict( + tDn="uni/tn-{0}/ap-{1}/epg-{2}".format(associated_epg.get("tenant"), associated_epg.get("ap"), associated_epg.get("epg")) + ) + ) + ), + ] + ) + elif associated_extepg is not None: + if all(value is None for value in associated_extepg.values()) and isinstance(aci.existing, list) and len(aci.existing) > 0: + for child in aci.existing[0].get("netflowExporterPol", {}).get("children", {}): + if child.get("netflowRsExporterToEPg"): + child_configs.extend([dict(netflowRsExporterToEPg=dict(attributes=dict(status="deleted")))]) + elif all(value is not None for value in associated_extepg.values()): + child_configs.extend( + [ + dict( + netflowRsExporterToEPg=dict( + attributes=dict( + tDn="uni/tn-{0}/out-{1}/instP-{2}".format( + associated_extepg.get("tenant"), associated_extepg.get("l3out"), associated_extepg.get("extepg") + ) + ) + ) + ), + ] + ) + aci.payload( + aci_class="netflowExporterPol", + class_config=dict( + name=netflow_exporter_policy, + descr=description, + dscp=dscp, + dstAddr=destination_address, + dstPort=destination_port, + sourceIpType=source_ip_type, + srcAddr=custom_source_address, + ), + child_configs=child_configs, + ) + + aci.get_diff(aci_class="netflowExporterPol") + + aci.post_config() + + elif state == "absent": + aci.delete_config() + + aci.exit_json() + + +if __name__ == "__main__": + main() diff --git a/ansible_collections/cisco/aci/plugins/modules/aci_netflow_monitor_policy.py b/ansible_collections/cisco/aci/plugins/modules/aci_netflow_monitor_policy.py new file mode 100644 index 000000000..462187609 --- /dev/null +++ b/ansible_collections/cisco/aci/plugins/modules/aci_netflow_monitor_policy.py @@ -0,0 +1,300 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- + +# Copyright: (c) 2023, Gaspard Micol (@gmicol) +# 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_netflow_monitor_policy +short_description: Manage Netflow Monitor Policy (netflow:MonitorPol) +description: +- Manage Netflow Monitor Policies for tenants on Cisco ACI fabrics. +options: + tenant: + description: + - The name of an existing tenant. + type: str + aliases: [ tenant_name ] + netflow_monitor_policy: + description: + - The name of the Netflow Monitor Policy. + type: str + aliases: [ netflow_monitor, netflow_monitor_name, name ] + netflow_record_policy: + description: + - The name of the Netflow Record Policy. + - To remove the current Netflow Record Policy, pass an empty string. + type: str + aliases: [ netflow_record, netflow_record_name ] + description: + description: + - The description for the Netflow Monitor 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 +extends_documentation_fragment: +- cisco.aci.aci +- cisco.aci.annotation +- cisco.aci.owner + +notes: +- The I(tenant) must exist before using this module in your playbook. + The M(cisco.aci.aci_tenant) can be used for this. +- If the I(netflow_record_policy) is used, it must exist before using this module in your playbook. + The M(cisco.aci.aci_netflow_record_policy) can be used for this. +seealso: +- module: cisco.aci.aci_tenant +- module: cisco.aci.aci_netflow_record_policy +- name: APIC Management Information Model reference + description: More information about the internal APIC class B(netflow:MonitorPol). + link: https://developer.cisco.com/docs/apic-mim-ref/ +author: +- Gaspard Micol (@gmicol) +""" + +EXAMPLES = r""" +- name: Add a new Netflow Monitor Policy + cisco.aci.aci_netflow_monitor_policy: + host: apic + username: admin + password: SomeSecretPassword + tenant: my_tenant + netflow_monitor_policy: my_netflow_monitor_policy + netflow_record_policy: my_netflow_record_policy + state: present + delegate_to: localhost + +- name: Query a Netflow Monitor Policy + cisco.aci.aci_netflow_monitor_policy: + host: apic + username: admin + password: SomeSecretPassword + tenant: my_tenant + netflow_monitor_policy: my_netflow_monitor_policy + state: query + delegate_to: localhost + +- name: Query all Netflow Monitor Policies in my_tenant + cisco.aci.aci_netflow_monitor_policy: + host: apic + username: admin + password: SomeSecretPassword + tenant: my_tenant + state: query + delegate_to: localhost + +- name: Query all Netflow Monitor Policies + cisco.aci.aci_netflow_monitor_policy: + host: apic + username: admin + password: SomeSecretPassword + state: query + delegate_to: localhost + +- name: Delete a Netflow Monitor Policy + cisco.aci.aci_netflow_monitor_policy: + host: apic + username: admin + password: SomeSecretPassword + tenant: my_tenant + netflow_monitor_policy: my_netflow_monitor_policy + 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: '' +sent: + description: The actual/minimal configuration pushed to the APIC + returned: info + type: list + sample: + { + "fvTenant": { + "attributes": { + "descr": "Production environment" + } + } + } +previous: + description: The original configuration from the APIC before the module has started + returned: info + type: list + sample: + [ + { + "fvTenant": { + "attributes": { + "descr": "Production", + "dn": "uni/tn-production", + "name": "production", + "nameAlias": "", + "ownerKey": "", + "ownerTag": "" + } + } + } + ] +proposed: + description: The assembled configuration from the user-provided parameters + returned: info + type: dict + sample: + { + "fvTenant": { + "attributes": { + "descr": "Production environment", + "name": "production" + } + } + } +filter_string: + description: The filter string used for the request + returned: failure or debug + type: str + sample: ?rsp-prop-include=config-only +method: + description: The HTTP method used for the request to the APIC + returned: failure or debug + type: str + sample: POST +response: + description: The HTTP response from the APIC + returned: failure or debug + type: str + sample: OK (30 bytes) +status: + description: The HTTP status from the APIC + returned: failure or debug + type: int + sample: 200 +url: + description: The HTTP url used for the request to the APIC + returned: failure or debug + type: str + sample: https://10.11.12.13/api/mo/uni/tn-production.json +""" + + +from ansible.module_utils.basic import AnsibleModule +from ansible_collections.cisco.aci.plugins.module_utils.aci import ACIModule, aci_argument_spec, aci_annotation_spec, aci_owner_spec + + +def main(): + argument_spec = aci_argument_spec() + argument_spec.update(aci_annotation_spec()) + argument_spec.update(aci_owner_spec()) + argument_spec.update( + tenant=dict(type="str", aliases=["tenant_name"]), + netflow_monitor_policy=dict(type="str", aliases=["netflow_monitor", "netflow_monitor_name", "name"]), + netflow_record_policy=dict(type="str", aliases=["netflow_record", "netflow_record_name"]), + description=dict(type="str", aliases=["descr"]), + state=dict(type="str", default="present", choices=["absent", "present", "query"]), + ) + + module = AnsibleModule( + argument_spec=argument_spec, + supports_check_mode=True, + required_if=[ + ["state", "absent", ["tenant", "netflow_monitor_policy"]], + ["state", "present", ["tenant", "netflow_monitor_policy"]], + ], + ) + + tenant = module.params.get("tenant") + description = module.params.get("description") + netflow_monitor_policy = module.params.get("netflow_monitor_policy") + netflow_record_policy = module.params.get("netflow_record_policy") + state = module.params.get("state") + + aci = ACIModule(module) + + child_classes = ["netflowRsMonitorToRecord"] + + 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="netflowMonitorPol", + aci_rn="monitorpol-{0}".format(netflow_monitor_policy), + module_object=netflow_monitor_policy, + target_filter={"name": netflow_monitor_policy}, + ), + child_classes=child_classes, + ) + + aci.get_existing() + + if state == "present": + child_configs = [] + child_configs.append(dict(netflowRsMonitorToRecord=dict(attributes=dict(tnNetflowRecordPolName=netflow_record_policy)))) + aci.payload( + aci_class="netflowMonitorPol", + class_config=dict( + name=netflow_monitor_policy, + descr=description, + ), + child_configs=child_configs, + ) + + aci.get_diff(aci_class="netflowMonitorPol") + + aci.post_config() + + elif state == "absent": + aci.delete_config() + + aci.exit_json() + + +if __name__ == "__main__": + main() diff --git a/ansible_collections/cisco/aci/plugins/modules/aci_netflow_monitor_to_exporter.py b/ansible_collections/cisco/aci/plugins/modules/aci_netflow_monitor_to_exporter.py new file mode 100644 index 000000000..50e2f2524 --- /dev/null +++ b/ansible_collections/cisco/aci/plugins/modules/aci_netflow_monitor_to_exporter.py @@ -0,0 +1,290 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- + +# Copyright: (c) 2023, Gaspard Micol (@gmicol) +# 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_netflow_monitor_to_exporter +short_description: Manage Netflow Monitor to Exporter (netflow:RsMonitorToExporter) +description: +- Link Netflow Exporter policies to Netflow Monitor policies for tenants on Cisco ACI fabrics. +options: + tenant: + description: + - The name of an existing tenant. + type: str + aliases: [ tenant_name ] + netflow_monitor_policy: + description: + - The name of the Netflow Monitor Policy. + type: str + aliases: [ netflow_monitor, netflow_monitor_name, name ] + netflow_exporter_policy: + description: + - The name of the Netflow Exporter Policy. + type: str + aliases: [ netflow_exporter, netflow_exporter_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 +- cisco.aci.annotation +- cisco.aci.owner + +notes: +- The I(tenant), I(netflow_monitor_policy) and I(netflow_exporter_policy) must exist before using this module in your playbook. + The M(cisco.aci.aci_tenant), M(cisco.aci.aci_netflow_monitor_policy), M(cisco.aci.aci_netflow_exporter_policy) can be used for this. +seealso: +- module: cisco.aci.aci_tenant +- module: cisco.aci.aci_netflow_monitor_policy +- module: cisco.aci.aci_netflow_exporter_policy +- name: APIC Management Information Model reference + description: More information about the internal APIC class B(netflow:RsMonitorToExporter). + link: https://developer.cisco.com/docs/apic-mim-ref/ +author: +- Gaspard Micol (@gmicol) +""" + +EXAMPLES = r""" +- name: Add a new Netflow Monitor Policy + cisco.aci.aci_netflow_monitor_to_exporter: + host: apic + username: admin + password: SomeSecretPassword + tenant: my_tenant + netflow_monitor_policy: my_netflow_monitor_policy + netflow_exporter_policy: my_netflow_exporter_policy + state: present + delegate_to: localhost + +- name: Query a Netflow Monitor Policy + cisco.aci.aci_netflow_monitor_to_exporter: + host: apic + username: admin + password: SomeSecretPassword + tenant: my_tenant + netflow_monitor_policy: my_netflow_monitor_policy + netflow_exporter_policy: my_netflow_exporter_policy + state: query + delegate_to: localhost + +- name: Query all Netflow Monitor Policies in my_tenant + cisco.aci.aci_netflow_monitor_to_exporter: + host: apic + username: admin + password: SomeSecretPassword + tenant: my_tenant + state: query + delegate_to: localhost + +- name: Query all Netflow Monitor Policies + cisco.aci.aci_netflow_monitor_to_exporter: + host: apic + username: admin + password: SomeSecretPassword + state: query + delegate_to: localhost + +- name: Delete a Netflow Monitor Policy + cisco.aci.aci_netflow_monitor_to_exporter: + host: apic + username: admin + password: SomeSecretPassword + tenant: my_tenant + netflow_monitor_policy: my_netflow_monitor_policy + netflow_exporter_policy: my_netflow_exporter_policy + 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: '' +sent: + description: The actual/minimal configuration pushed to the APIC + returned: info + type: list + sample: + { + "fvTenant": { + "attributes": { + "descr": "Production environment" + } + } + } +previous: + description: The original configuration from the APIC before the module has started + returned: info + type: list + sample: + [ + { + "fvTenant": { + "attributes": { + "descr": "Production", + "dn": "uni/tn-production", + "name": "production", + "nameAlias": "", + "ownerKey": "", + "ownerTag": "" + } + } + } + ] +proposed: + description: The assembled configuration from the user-provided parameters + returned: info + type: dict + sample: + { + "fvTenant": { + "attributes": { + "descr": "Production environment", + "name": "production" + } + } + } +filter_string: + description: The filter string used for the request + returned: failure or debug + type: str + sample: ?rsp-prop-include=config-only +method: + description: The HTTP method used for the request to the APIC + returned: failure or debug + type: str + sample: POST +response: + description: The HTTP response from the APIC + returned: failure or debug + type: str + sample: OK (30 bytes) +status: + description: The HTTP status from the APIC + returned: failure or debug + type: int + sample: 200 +url: + description: The HTTP url used for the request to the APIC + returned: failure or debug + type: str + sample: https://10.11.12.13/api/mo/uni/tn-production.json +""" + + +from ansible.module_utils.basic import AnsibleModule +from ansible_collections.cisco.aci.plugins.module_utils.aci import ACIModule, aci_argument_spec, aci_annotation_spec, aci_owner_spec + + +def main(): + argument_spec = aci_argument_spec() + argument_spec.update(aci_annotation_spec()) + argument_spec.update(aci_owner_spec()) + argument_spec.update( + tenant=dict(type="str", aliases=["tenant_name"]), + netflow_monitor_policy=dict(type="str", aliases=["netflow_monitor", "netflow_monitor_name", "name"]), + netflow_exporter_policy=dict(type="str", aliases=["netflow_exporter", "netflow_exporter_name"]), + state=dict(type="str", default="present", choices=["absent", "present", "query"]), + ) + + module = AnsibleModule( + argument_spec=argument_spec, + supports_check_mode=True, + required_if=[ + ["state", "absent", ["tenant", "netflow_monitor_policy", "netflow_exporter_policy"]], + ["state", "present", ["tenant", "netflow_monitor_policy", "netflow_exporter_policy"]], + ], + ) + + tenant = module.params.get("tenant") + netflow_monitor_policy = module.params.get("netflow_monitor_policy") + netflow_exporter_policy = module.params.get("netflow_exporter_policy") + 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="netflowMonitorPol", + aci_rn="monitorpol-{0}".format(netflow_monitor_policy), + module_object=netflow_monitor_policy, + target_filter={"name": netflow_monitor_policy}, + ), + subclass_2=dict( + aci_class="netflowRsMonitorToExporter", + aci_rn="rsmonitorToExporter-{0}".format(netflow_exporter_policy), + module_object=netflow_exporter_policy, + target_filter={"tnNetflowExporterPolName": netflow_exporter_policy}, + ), + ) + + aci.get_existing() + + if state == "present": + aci.payload( + aci_class="netflowRsMonitorToExporter", + class_config=dict(tnNetflowExporterPolName=netflow_exporter_policy), + ) + + aci.get_diff(aci_class="netflowRsMonitorToExporter") + + aci.post_config() + + elif state == "absent": + aci.delete_config() + + aci.exit_json() + + +if __name__ == "__main__": + main() diff --git a/ansible_collections/cisco/aci/plugins/modules/aci_netflow_record_policy.py b/ansible_collections/cisco/aci/plugins/modules/aci_netflow_record_policy.py new file mode 100644 index 000000000..e2f04af0c --- /dev/null +++ b/ansible_collections/cisco/aci/plugins/modules/aci_netflow_record_policy.py @@ -0,0 +1,313 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- + +# Copyright: (c) 2023, Gaspard Micol (@gmicol) +# 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_netflow_record_policy +short_description: Manage Netflow Record Policy (netflow:RecordPol) +description: +- Manage Netflow Record Policies for tenants on Cisco ACI fabrics. +options: + tenant: + description: + - The name of an existing tenant. + type: str + aliases: [ tenant_name ] + netflow_record_policy: + description: + - The name of the Netflow Record Policy. + type: str + aliases: [ netflow_record, netflow_record_name, name ] + collect: + description: + - The collect parameters for the flow record. + - The APIC defaults to C(source_interface) when unset during creation. + type: list + elements: str + choices: [ bytes_counter, pkts_counter, pkt_disposition, sampler_id, source_interface, tcp_flags, first_pkt_timestamp, recent_pkt_timestamp ] + match: + description: + - The match parameters for the flow record. + type: list + elements: str + choices: [ destination_ipv4_v6, destination_ipv4, destination_ipv6, destination_mac, destination_port, ethertype, ip_protocol, source_ipv4_v6, + source_ipv4, source_ipv6, source_mac, source_port, ip_tos, unspecified, vlan ] + description: + description: + - The description for the Netflow Record 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 +extends_documentation_fragment: +- cisco.aci.aci +- cisco.aci.annotation +- cisco.aci.owner + +notes: +- The I(tenant) must exist before using this module in your playbook. + The M(cisco.aci.aci_tenant) 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(netflow:RecordPol). + link: https://developer.cisco.com/docs/apic-mim-ref/ +author: +- Gaspard Micol (@gmicol) +""" + +EXAMPLES = r""" +- name: Add a new Netflow Record Policy + cisco.aci.aci_netflow_record_policy: + host: apic + username: admin + password: SomeSecretPassword + tenant: my_tenant + netflow_record_policy: my_netflow_record_policy + collect: [pkts_counter, pkt_disposition] + match: [destination_ipv4, source_ipv4] + state: present + delegate_to: localhost + +- name: Query a Netflow Record Policy + cisco.aci.aci_netflow_record_policy: + host: apic + username: admin + password: SomeSecretPassword + tenant: my_tenant + netflow_record_policy: my_netflow_record_policy + state: query + delegate_to: localhost + +- name: Query all Netflow Record Policies in my_tenant + cisco.aci.aci_netflow_record_policy: + host: apic + username: admin + password: SomeSecretPassword + tenant: my_tenant + state: query + delegate_to: localhost + +- name: Query all Netflow Record Policies + cisco.aci.aci_netflow_record_policy: + host: apic + username: admin + password: SomeSecretPassword + state: query + delegate_to: localhost + +- name: Delete a Netflow Record Policy + cisco.aci.aci_netflow_record_policy: + host: apic + username: admin + password: SomeSecretPassword + tenant: my_tenant + netflow_record_policy: my_netflow_record_policy + 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: '' +sent: + description: The actual/minimal configuration pushed to the APIC + returned: info + type: list + sample: + { + "fvTenant": { + "attributes": { + "descr": "Production environment" + } + } + } +previous: + description: The original configuration from the APIC before the module has started + returned: info + type: list + sample: + [ + { + "fvTenant": { + "attributes": { + "descr": "Production", + "dn": "uni/tn-production", + "name": "production", + "nameAlias": "", + "ownerKey": "", + "ownerTag": "" + } + } + } + ] +proposed: + description: The assembled configuration from the user-provided parameters + returned: info + type: dict + sample: + { + "fvTenant": { + "attributes": { + "descr": "Production environment", + "name": "production" + } + } + } +filter_string: + description: The filter string used for the request + returned: failure or debug + type: str + sample: ?rsp-prop-include=config-only +method: + description: The HTTP method used for the request to the APIC + returned: failure or debug + type: str + sample: POST +response: + description: The HTTP response from the APIC + returned: failure or debug + type: str + sample: OK (30 bytes) +status: + description: The HTTP status from the APIC + returned: failure or debug + type: int + sample: 200 +url: + description: The HTTP url used for the request to the APIC + returned: failure or debug + type: str + sample: https://10.11.12.13/api/mo/uni/tn-production.json +""" + + +from ansible.module_utils.basic import AnsibleModule +from ansible_collections.cisco.aci.plugins.module_utils.aci import ACIModule, aci_argument_spec, aci_annotation_spec, aci_owner_spec +from ansible_collections.cisco.aci.plugins.module_utils.constants import MATCH_COLLECT_NETFLOW_RECORD_MAPPING, MATCH_MATCH_NETFLOW_RECORD_MAPPING + + +def main(): + argument_spec = aci_argument_spec() + argument_spec.update(aci_annotation_spec()) + argument_spec.update(aci_owner_spec()) + argument_spec.update( + tenant=dict(type="str", aliases=["tenant_name"]), + netflow_record_policy=dict(type="str", aliases=["netflow_record", "netflow_record_name", "name"]), + collect=dict(type="list", elements="str", choices=list(MATCH_COLLECT_NETFLOW_RECORD_MAPPING.keys())), + match=dict(type="list", elements="str", choices=list(MATCH_MATCH_NETFLOW_RECORD_MAPPING.keys())), + description=dict(type="str", aliases=["descr"]), + state=dict(type="str", default="present", choices=["absent", "present", "query"]), + ) + + module = AnsibleModule( + argument_spec=argument_spec, + supports_check_mode=True, + required_if=[ + ["state", "absent", ["tenant", "netflow_record_policy"]], + ["state", "present", ["tenant", "netflow_record_policy"]], + ], + ) + + tenant = module.params.get("tenant") + description = module.params.get("description") + netflow_record_policy = module.params.get("netflow_record_policy") + state = module.params.get("state") + + if module.params.get("collect") is not None: + collect = ",".join(sorted(MATCH_COLLECT_NETFLOW_RECORD_MAPPING.get(v) for v in module.params.get("collect"))) + else: + collect = None + + if module.params.get("match") is not None: + match = ",".join(sorted(MATCH_MATCH_NETFLOW_RECORD_MAPPING.get(v) for v in module.params.get("match"))) + else: + match = None + + 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="netflowRecordPol", + aci_rn="recordpol-{0}".format(netflow_record_policy), + module_object=netflow_record_policy, + target_filter={"name": netflow_record_policy}, + ), + ) + + aci.get_existing() + + if state == "present": + aci.payload( + aci_class="netflowRecordPol", + class_config=dict( + name=netflow_record_policy, + collect=collect, + match=match, + descr=description, + ), + ) + + aci.get_diff(aci_class="netflowRecordPol") + + aci.post_config() + + elif state == "absent": + aci.delete_config() + + aci.exit_json() + + +if __name__ == "__main__": + main() diff --git a/ansible_collections/cisco/aci/plugins/modules/aci_node_block.py b/ansible_collections/cisco/aci/plugins/modules/aci_node_block.py new file mode 100644 index 000000000..d2f86a275 --- /dev/null +++ b/ansible_collections/cisco/aci/plugins/modules/aci_node_block.py @@ -0,0 +1,390 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- + +# Copyright: (c) 2024, Gaspard Micol (@gmicol) +# 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_node_block +short_description: Manage Node Block (infra:NodeBlk) +description: +- Manage Node Blocks on Cisco ACI fabrics. +- A node block is a range of nodes. Each node block begins with the first port and ends with the last port. +options: + switch_profile: + description: + - The name of the Fabric access policy leaf/spine switch profile. + type: str + aliases: + - leaf_profile_name + - leaf_profile + - switch_profile_name + - spine_switch_profile + - spine_switch_profile_name + access_port_selector: + description: + - The name of the Fabric access policy leaf/spine switch port selector. + type: str + aliases: [ access_port_selector_name, port_selector, port_selector_name ] + node_block: + description: + - The name of the Node Block. + type: str + aliases: [ node_block_name, name ] + description: + description: + - The description for the Node Block. + type: str + aliases: [ node_block_description ] + from_port: + description: + - The beginning of the port range block for the Node Block. + type: str + aliases: [ from, from_port_range ] + to_port: + description: + - The end of the port range block for the Node Block. + type: str + aliases: [ to, to_port_range ] + type_node: + description: + - The type of Node Block to be created under respective access port. + type: str + choices: [ leaf, spine ] + 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 +extends_documentation_fragment: +- cisco.aci.aci +- cisco.aci.annotation + +notes: +- If Adding a port block on an access leaf switch port selector of I(type) C(leaf), + The I(switch_profile) and I(access_port_selector) must exist before using this module in your playbook. + The M(cisco.aci.aci_switch_policy_leaf_profile) and M(cisco.aci.aci_switch_leaf_selector) modules can be used for this. +- If Adding a port block on an access switch port selector of C(type) C(spine), + The I(switch_profile) and I(access_port_selector) must exist before using this module in your playbook. + The M(cisco.aci.aci_access_spine_switch_profile) and M(cisco.aci.aci_access_spine_switch_selector) modules can be used for this. +seealso: +- module: cisco.aci.aci_switch_policy_leaf_profile +- module: cisco.aci.aci_switch_leaf_selector +- module: cisco.aci.aci_access_spine_switch_profile +- module: cisco.aci.aci_access_spine_switch_selector +- name: APIC Management Information Model reference + description: More information about the internal APIC classes B(infra:NodeBlk). + link: https://developer.cisco.com/docs/apic-mim-ref/ +author: +- Gaspard Micol (@gmicol) +""" + +EXAMPLES = r""" +- name: Add a new Node Block associated to a switch policy leaf profile selector + cisco.aci.aci_node_block: + host: apic + username: admin + password: SomeSecretPassword + switch_profile: my_leaf_switch_profile + access_port_selector: my_leaf_switch_selector + node_block: my_node_block + from_port: 1011 + to_port: 1011 + type_node: leaf + state: present + delegate_to: localhost + +- name: Add a new Node Block associated to a switch policy spine profile selector + cisco.aci.aci_node_block: + host: apic + username: admin + password: SomeSecretPassword + switch_profile: my_spine_switch_profile + access_port_selector: my_spine_switch_selector + node_block: my_node_block + from_port: 1012 + to_port: 1012 + type_node: spine + state: present + delegate_to: localhost + +- name: Query a Node Block associated to a switch policy leaf profile selector + cisco.aci.aci_node_block: + host: apic + username: admin + password: SomeSecretPassword + switch_profile: my_leaf_switch_profile + access_port_selector: my_leaf_switch_selector + node_block: my_node_block + state: query + delegate_to: localhost + register: query_result + +- name: Query all Node Blocks under the switch policy leaf profile selector + cisco.aci.aci_node_block: + host: apic + username: admin + password: SomeSecretPassword + switch_profile: my_leaf_switch_profile + access_port_selector: my_leaf_switch_selector + state: query + delegate_to: localhost + register: query_result + +- name: Query all Node Blocks + cisco.aci.aci_node_block: + host: apic + username: admin + password: SomeSecretPassword + state: query + delegate_to: localhost + register: query_result + +- name: Remove a Node Block associated to a switch policy leaf profile selector + cisco.aci.aci_node_block: + host: apic + username: admin + password: SomeSecretPassword + switch_profile: my_leaf_switch_profile + access_port_selector: my_leaf_switch_selector + node_block: my_node_block + type_node: leaf + 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: '' +sent: + description: The actual/minimal configuration pushed to the APIC + returned: info + type: list + sample: + { + "fvTenant": { + "attributes": { + "descr": "Production environment" + } + } + } +previous: + description: The original configuration from the APIC before the module has started + returned: info + type: list + sample: + [ + { + "fvTenant": { + "attributes": { + "descr": "Production", + "dn": "uni/tn-production", + "name": "production", + "nameAlias": "", + "ownerKey": "", + "ownerTag": "" + } + } + } + ] +proposed: + description: The assembled configuration from the user-provided parameters + returned: info + type: dict + sample: + { + "fvTenant": { + "attributes": { + "descr": "Production environment", + "name": "production" + } + } + } +filter_string: + description: The filter string used for the request + returned: failure or debug + type: str + sample: ?rsp-prop-include=config-only +method: + description: The HTTP method used for the request to the APIC + returned: failure or debug + type: str + sample: POST +response: + description: The HTTP response from the APIC + returned: failure or debug + type: str + sample: OK (30 bytes) +status: + description: The HTTP status from the APIC + returned: failure or debug + type: int + sample: 200 +url: + description: The HTTP url used for the request to the APIC + returned: failure or debug + type: str + sample: https://10.11.12.13/api/mo/uni/tn-production.json +""" + +from ansible.module_utils.basic import AnsibleModule +from ansible_collections.cisco.aci.plugins.module_utils.aci import ACIModule, aci_argument_spec, aci_annotation_spec + + +def main(): + argument_spec = aci_argument_spec() + argument_spec.update(aci_annotation_spec()) + argument_spec.update( + switch_profile=dict( + type="str", + aliases=[ + "leaf_profile_name", + "leaf_profile", + "switch_profile_name", + "spine_switch_profile", + "spine_switch_profile_name", + ], + ), # Not required for querying all objects + access_port_selector=dict( + type="str", + aliases=[ + "access_port_selector_name", + "port_selector", + "port_selector_name", + ], + ), # Not required for querying all objects + node_block=dict(type="str", aliases=["node_block_name", "name"]), # Not required for querying all objects + description=dict(type="str", aliases=["node_block_description"]), + from_port=dict(type="str", aliases=["from", "from_port_range"]), + to_port=dict(type="str", aliases=["to", "to_port_range"]), + state=dict(type="str", default="present", choices=["absent", "present", "query"]), + type_node=dict(type="str", choices=["leaf", "spine"], aliases=["type"]), # Not required for querying all objects + ) + + module = AnsibleModule( + argument_spec=argument_spec, + supports_check_mode=True, + required_if=[ + ["state", "absent", ["switch_profile", "access_port_selector", "node_block", "type_node"]], + ["state", "present", ["switch_profile", "access_port_selector", "node_block", "type_node"]], + ], + ) + + switch_profile = module.params.get("switch_profile") + access_port_selector = module.params.get("access_port_selector") + node_block = module.params.get("node_block") + description = module.params.get("description") + from_port = module.params.get("from_port") + to_port = module.params.get("to_port") + state = module.params.get("state") + type_node = module.params.get("type_node") + + aci = ACIModule(module) + + if type_node == "spine": + subclass_1 = dict( + aci_class="infraSpineP", + aci_rn="spprof-{0}".format(switch_profile), + module_object=switch_profile, + target_filter={"name": switch_profile}, + ) + subclass_2 = dict( + aci_class="infraSpineS", + aci_rn="spines-{0}-typ-range".format(access_port_selector), + module_object=access_port_selector, + target_filter={"name": access_port_selector}, + ) + else: + subclass_1 = dict( + aci_class="infraNodeP", + aci_rn="nprof-{0}".format(switch_profile), + module_object=switch_profile, + target_filter={"name": switch_profile}, + ) + subclass_2 = dict( + aci_class="infraLeafS", + aci_rn="leaves-{0}-typ-range".format(access_port_selector), + module_object=access_port_selector, + target_filter={"name": access_port_selector}, + ) + aci.construct_url( + root_class=dict( + aci_class="infraInfra", + aci_rn="infra", + ), + subclass_1=subclass_1, + subclass_2=subclass_2, + subclass_3=dict( + aci_class="infraNodeBlk", + aci_rn="nodeblk-{0}".format(node_block), + module_object=node_block, + target_filter={"name": node_block}, + ), + ) + + aci.get_existing() + + if state == "present": + aci.payload( + aci_class="infraNodeBlk", + class_config=dict( + descr=description, + name=node_block, + from_=from_port, + to_=to_port, + ), + ) + + aci.get_diff(aci_class="infraNodeBlk") + + aci.post_config() + + elif state == "absent": + aci.delete_config() + + aci.exit_json() + + +if __name__ == "__main__": + main() diff --git a/ansible_collections/cisco/aci/plugins/modules/aci_node_mgmt_epg.py b/ansible_collections/cisco/aci/plugins/modules/aci_node_mgmt_epg.py index be8fe1838..161ce36f3 100644 --- a/ansible_collections/cisco/aci/plugins/modules/aci_node_mgmt_epg.py +++ b/ansible_collections/cisco/aci/plugins/modules/aci_node_mgmt_epg.py @@ -11,7 +11,7 @@ __metaclass__ = type DOCUMENTATION = r""" --- module: aci_node_mgmt_epg -short_description: In band or Out of band management EPGs +short_description: In band or Out of band management EPGs (mgmt:OoB and mgmt:InB) description: - Cisco ACI Fabric Node EPGs options: @@ -45,6 +45,10 @@ extends_documentation_fragment: - cisco.aci.aci - cisco.aci.annotation +seealso: +- name: APIC Management Information Model reference + description: More information about the internal APIC classes B(mgmt:OoB) and B(mgmt:InB). + link: https://developer.cisco.com/docs/apic-mim-ref/ author: - Shreyas Srish (@shrsr) """ diff --git a/ansible_collections/cisco/aci/plugins/modules/aci_ntp_policy.py b/ansible_collections/cisco/aci/plugins/modules/aci_ntp_policy.py index 7fc8abde3..1adb35cc3 100644 --- a/ansible_collections/cisco/aci/plugins/modules/aci_ntp_policy.py +++ b/ansible_collections/cisco/aci/plugins/modules/aci_ntp_policy.py @@ -17,9 +17,9 @@ ANSIBLE_METADATA = { DOCUMENTATION = r""" --- module: aci_ntp_policy -short_description: Manage NTP policies. +short_description: Manage NTP policies (datetime:Pol) description: -- Manage NTP policy (datetimePol) configuration on Cisco ACI fabrics. +- Manage NTP policy configuration on Cisco ACI fabrics. options: name: description: @@ -64,7 +64,7 @@ extends_documentation_fragment: seealso: - name: APIC Management Information Model reference - description: More information about the internal APIC class B(datetimePol). + description: More information about the internal APIC class B(datetime:Pol). link: https://developer.cisco.com/docs/apic-mim-ref/ author: - Tim Cragg (@timcragg) diff --git a/ansible_collections/cisco/aci/plugins/modules/aci_ntp_server.py b/ansible_collections/cisco/aci/plugins/modules/aci_ntp_server.py index 3e40b652a..e8a94a03b 100644 --- a/ansible_collections/cisco/aci/plugins/modules/aci_ntp_server.py +++ b/ansible_collections/cisco/aci/plugins/modules/aci_ntp_server.py @@ -17,7 +17,7 @@ ANSIBLE_METADATA = { DOCUMENTATION = r""" --- module: aci_ntp_server -short_description: Manage NTP servers. +short_description: Manage NTP servers (datetime:NtpProv) description: - Manage NTP server (datetimeNtpProv) configuration on Cisco ACI fabrics. options: @@ -74,7 +74,7 @@ notes: The M(cisco.aci.aci_ntp_policy) module can be used for this. seealso: - name: APIC Management Information Model reference - description: More information about the internal APIC class B(datetimeNtpProv). + description: More information about the internal APIC class B(datetime:NtpProv). link: https://developer.cisco.com/docs/apic-mim-ref/ author: - Tim Cragg (@timcragg) diff --git a/ansible_collections/cisco/aci/plugins/modules/aci_pim_route_map_entry.py b/ansible_collections/cisco/aci/plugins/modules/aci_pim_route_map_entry.py new file mode 100644 index 000000000..79ad849a7 --- /dev/null +++ b/ansible_collections/cisco/aci/plugins/modules/aci_pim_route_map_entry.py @@ -0,0 +1,329 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- + +# Copyright: (c) 2023, Gaspard Micol (@gmicol) +# 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_pim_route_map_entry +short_description: Manage Protocol-Independent Multicast (PIM) Route Map Entry (pim:RouteMapEntry) +description: +- Manage PIM Route Map Entries for the PIM route Map Policies on Cisco ACI fabrics. +options: + tenant: + description: + - The name of an existing tenant. + type: str + aliases: [ tenant_name ] + pim_route_map_policy: + description: + - The name of the PIM Route Map policy. + type: str + aliases: [ route_map_policy_name ] + order: + description: + - The PIM Route Map Entry order. + type: int + source_ip: + description: + - The Multicast Source IP. + type: str + group_ip: + description: + - The Multicast Group IP. + type: str + rp_ip: + description: + - The Multicast Rendezvous Point (RP) IP. + type: str + aliases: [ rendezvous_point_ip ] + action: + description: + - The route action. + - The APIC defaults to C(permit) when unset during creation. + type: str + choices: [ permit, deny ] + description: + description: + - The description for the PIM Route Map entry. + 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 +extends_documentation_fragment: +- cisco.aci.aci +- cisco.aci.annotation +- cisco.aci.owner + +notes: +- The C(tenant) and the C(pim_route_map_policy) must exist before using this module in your playbook. + The M(cisco.aci.aci_tenant) and M(cisco.aci.aci_pim_route_map_policy) can be used for this. +seealso: +- module: cisco.aci.aci_tenant +- module: cisco.aci.aci_pim_route_map_policy +- name: APIC Management Information Model reference + description: More information about the internal APIC class B(pim:RouteMapEntry). + link: https://developer.cisco.com/docs/apic-mim-ref/ +author: +- Gaspard Micol (@gmicol) +""" + +EXAMPLES = r""" +- name: Add a new PIM Route Map Entry + cisco.aci.aci_pim_route_map_entry: + host: apic + username: admin + password: SomeSecretPassword + tenant: my_tenant + pim_route_map_policy: my_pim_route_map_policy + order: 1 + source_ip: 1.1.1.1/24 + group_ip: 224.0.0.1/24 + rp_ip: 1.1.1.2 + action: permit + state: present + delegate_to: localhost + +- name: Query a PIM Route Map Entry + cisco.aci.aci_pim_route_map_entry: + host: apic + username: admin + password: SomeSecretPassword + tenant: my_tenant + pim_route_map_policy: my_pim_route_map_policy + order: 1 + state: query + delegate_to: localhost + register: query_result + +- name: Query all PIM Route Map Entries in my_pim_route_map_policy + cisco.aci.aci_pim_route_map_entry: + host: apic + username: admin + password: SomeSecretPassword + tenant: my_tenant + pim_route_map_policy: my_pim_route_map_policy + state: query + delegate_to: localhost + register: query_result + +- name: Delete a PIM Route Map Entry + cisco.aci.aci_pim_route_map_entry: + host: apic + username: admin + password: SomeSecretPassword + tenant: my_tenant + pim_route_map_policy: my_pim_route_map_policy + order: 1 + 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: '' +sent: + description: The actual/minimal configuration pushed to the APIC + returned: info + type: list + sample: + { + "fvTenant": { + "attributes": { + "descr": "Production environment" + } + } + } +previous: + description: The original configuration from the APIC before the module has started + returned: info + type: list + sample: + [ + { + "fvTenant": { + "attributes": { + "descr": "Production", + "dn": "uni/tn-production", + "name": "production", + "nameAlias": "", + "ownerKey": "", + "ownerTag": "" + } + } + } + ] +proposed: + description: The assembled configuration from the user-provided parameters + returned: info + type: dict + sample: + { + "fvTenant": { + "attributes": { + "descr": "Production environment", + "name": "production" + } + } + } +filter_string: + description: The filter string used for the request + returned: failure or debug + type: str + sample: ?rsp-prop-include=config-only +method: + description: The HTTP method used for the request to the APIC + returned: failure or debug + type: str + sample: POST +response: + description: The HTTP response from the APIC + returned: failure or debug + type: str + sample: OK (30 bytes) +status: + description: The HTTP status from the APIC + returned: failure or debug + type: int + sample: 200 +url: + description: The HTTP url used for the request to the APIC + returned: failure or debug + type: str + sample: https://10.11.12.13/api/mo/uni/tn-production.json +""" + + +from ansible.module_utils.basic import AnsibleModule +from ansible_collections.cisco.aci.plugins.module_utils.aci import ACIModule, aci_argument_spec, aci_annotation_spec, aci_owner_spec + + +def main(): + argument_spec = aci_argument_spec() + argument_spec.update(aci_annotation_spec()) + argument_spec.update(aci_owner_spec()) + argument_spec.update( + tenant=dict(type="str", aliases=["tenant_name"]), + pim_route_map_policy=dict(type="str", aliases=["route_map_policy_name"]), + description=dict(type="str", aliases=["descr"]), + order=dict(type="int"), + source_ip=dict(type="str"), + group_ip=dict(type="str"), + rp_ip=dict(type="str", aliases=["rendezvous_point_ip"]), + action=dict(type="str", choices=["permit", "deny"]), + state=dict(type="str", default="present", choices=["absent", "present", "query"]), + ) + + module = AnsibleModule( + argument_spec=argument_spec, + supports_check_mode=True, + required_if=[ + ["state", "absent", ["tenant", "pim_route_map_policy", "order"]], + ["state", "present", ["tenant", "pim_route_map_policy", "order"]], + ], + ) + + tenant = module.params.get("tenant") + description = module.params.get("description") + pim_route_map_policy = module.params.get("pim_route_map_policy") + order = module.params.get("order") + source_ip = module.params.get("source_ip") + group_ip = module.params.get("group_ip") + rp_ip = module.params.get("rp_ip") + action = module.params.get("action") + 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="pimRouteMapPol", + aci_rn="rtmap-{0}".format(pim_route_map_policy), + module_object=pim_route_map_policy, + target_filter={"name": pim_route_map_policy}, + ), + subclass_2=dict( + aci_class="pimRouteMapEntry", + aci_rn="rtmapentry-{0}".format(order), + module_object=order, + target_filter={"order": order}, + ), + ) + + aci.get_existing() + + if state == "present": + aci.payload( + aci_class="pimRouteMapEntry", + class_config=dict( + name=pim_route_map_policy, + descr=description, + action=action, + grp=group_ip, + order=order, + rp=rp_ip, + src=source_ip, + ), + ) + + aci.get_diff(aci_class="pimRouteMapEntry") + + aci.post_config() + + elif state == "absent": + aci.delete_config() + + aci.exit_json() + + +if __name__ == "__main__": + main() diff --git a/ansible_collections/cisco/aci/plugins/modules/aci_pim_route_map_policy.py b/ansible_collections/cisco/aci/plugins/modules/aci_pim_route_map_policy.py new file mode 100644 index 000000000..06c7c7b29 --- /dev/null +++ b/ansible_collections/cisco/aci/plugins/modules/aci_pim_route_map_policy.py @@ -0,0 +1,276 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- + +# Copyright: (c) 2023, Gaspard Micol (@gmicol) +# 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_pim_route_map_policy +short_description: Manage Protocol-Independent Multicast (PIM) Route Map Policy (pim:RouteMapPol) +description: +- Manage PIM Route Map Policies for tenants on Cisco ACI fabrics. +options: + tenant: + description: + - The name of an existing tenant. + type: str + aliases: [ tenant_name ] + pim_route_map_policy: + description: + - The name of the PIM Route Map policy. + type: str + aliases: [ route_map_policy_name, name ] + description: + description: + - The description for the PIM Route Map 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 +extends_documentation_fragment: +- cisco.aci.aci +- cisco.aci.annotation +- cisco.aci.owner + +notes: +- The C(tenant) must exist before using this module in your playbook. + The M(cisco.aci.aci_tenant) 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(pim:RouteMapPol). + link: https://developer.cisco.com/docs/apic-mim-ref/ +author: +- Gaspard Micol (@gmicol) +""" + +EXAMPLES = r""" +- name: Add a new PIM Route Map policy + cisco.aci.aci_pim_route_map_policy: + host: apic + username: admin + password: SomeSecretPassword + tenant: my_tenant + pim_route_map_policy: my_pim_route_map_policy + state: present + delegate_to: localhost + +- name: Query a PIM Route Map policy + cisco.aci.aci_pim_route_map_policy: + host: apic + username: admin + password: SomeSecretPassword + tenant: my_tenant + pim_route_map_policy: my_pim_route_map_policy + state: query + delegate_to: localhost + register: query_result + +- name: Query all PIM Route Map policies in my_tenant + cisco.aci.aci_pim_route_map_policy: + host: apic + username: admin + password: SomeSecretPassword + tenant: my_tenant + state: query + delegate_to: localhost + register: query_result + +- name: Delete a PIM Route Map policy + cisco.aci.aci_pim_route_map_policy: + host: apic + username: admin + password: SomeSecretPassword + tenant: my_tenant + pim_route_map_policy: my_pim_route_map_policy + 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: '' +sent: + description: The actual/minimal configuration pushed to the APIC + returned: info + type: list + sample: + { + "fvTenant": { + "attributes": { + "descr": "Production environment" + } + } + } +previous: + description: The original configuration from the APIC before the module has started + returned: info + type: list + sample: + [ + { + "fvTenant": { + "attributes": { + "descr": "Production", + "dn": "uni/tn-production", + "name": "production", + "nameAlias": "", + "ownerKey": "", + "ownerTag": "" + } + } + } + ] +proposed: + description: The assembled configuration from the user-provided parameters + returned: info + type: dict + sample: + { + "fvTenant": { + "attributes": { + "descr": "Production environment", + "name": "production" + } + } + } +filter_string: + description: The filter string used for the request + returned: failure or debug + type: str + sample: ?rsp-prop-include=config-only +method: + description: The HTTP method used for the request to the APIC + returned: failure or debug + type: str + sample: POST +response: + description: The HTTP response from the APIC + returned: failure or debug + type: str + sample: OK (30 bytes) +status: + description: The HTTP status from the APIC + returned: failure or debug + type: int + sample: 200 +url: + description: The HTTP url used for the request to the APIC + returned: failure or debug + type: str + sample: https://10.11.12.13/api/mo/uni/tn-production.json +""" + + +from ansible.module_utils.basic import AnsibleModule +from ansible_collections.cisco.aci.plugins.module_utils.aci import ACIModule, aci_argument_spec, aci_annotation_spec, aci_owner_spec + + +def main(): + argument_spec = aci_argument_spec() + argument_spec.update(aci_annotation_spec()) + argument_spec.update(aci_owner_spec()) + argument_spec.update( + tenant=dict(type="str", aliases=["tenant_name"]), + pim_route_map_policy=dict(type="str", aliases=["route_map_policy_name", "name"]), + description=dict(type="str", aliases=["descr"]), + state=dict(type="str", default="present", choices=["absent", "present", "query"]), + ) + + module = AnsibleModule( + argument_spec=argument_spec, + supports_check_mode=True, + required_if=[ + ["state", "absent", ["tenant", "pim_route_map_policy"]], + ["state", "present", ["tenant", "pim_route_map_policy"]], + ], + ) + + tenant = module.params.get("tenant") + description = module.params.get("description") + pim_route_map_policy = module.params.get("pim_route_map_policy") + 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="pimRouteMapPol", + aci_rn="rtmap-{0}".format(pim_route_map_policy), + module_object=pim_route_map_policy, + target_filter={"name": pim_route_map_policy}, + ), + ) + + aci.get_existing() + + if state == "present": + aci.payload( + aci_class="pimRouteMapPol", + class_config=dict( + name=pim_route_map_policy, + descr=description, + ), + ) + + aci.get_diff(aci_class="pimRouteMapPol") + + aci.post_config() + + elif state == "absent": + aci.delete_config() + + aci.exit_json() + + +if __name__ == "__main__": + main() diff --git a/ansible_collections/cisco/aci/plugins/modules/aci_qos_custom_policy.py b/ansible_collections/cisco/aci/plugins/modules/aci_qos_custom_policy.py new file mode 100644 index 000000000..c5200b0f7 --- /dev/null +++ b/ansible_collections/cisco/aci/plugins/modules/aci_qos_custom_policy.py @@ -0,0 +1,284 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- + +# Copyright: (c) 2023, Gaspard Micol (@gmicol) +# 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_qos_custom_policy +short_description: Manage QoS Custom Policy (qos:CustomPol) +description: +- Manage QoS Custom Policies for tenants on Cisco ACI fabrics. +- The custom QoS policy enables different levels of service to be assigned to network traffic, + including specifications for the Differentiated Services Code Point (DSCP) value(s), and the 802.1p Dot1p priority. +options: + tenant: + description: + - The name of an existing tenant. + type: str + aliases: [ tenant_name ] + qos_custom_policy: + description: + - The name of the QoS Custom Policy. + type: str + aliases: [ qos_custom_policy_name, name ] + description: + description: + - The description for the QoS Custom 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 +extends_documentation_fragment: +- cisco.aci.aci +- cisco.aci.annotation +- cisco.aci.owner + +notes: +- The I(tenant) must exist before using this module in your playbook. + The M(cisco.aci.aci_tenant) 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(qos:CustomPol). + link: https://developer.cisco.com/docs/apic-mim-ref/ +author: +- Gaspard Micol (@gmicol) +""" + +EXAMPLES = r""" +- name: Add a new QoS Custom Policy + cisco.aci.aci_qos_custom_policy: + host: apic + username: admin + password: SomeSecretPassword + tenant: my_tenant + qos_custom_policy: my_qos_custom_policy + state: present + delegate_to: localhost + +- name: Query a QoS Custom Policy + cisco.aci.aci_qos_custom_policy: + host: apic + username: admin + password: SomeSecretPassword + tenant: my_tenant + qos_custom_policy: my_qos_custom_policy + state: query + delegate_to: localhost + +- name: Query all QoS Custom Policies in my_tenant + cisco.aci.aci_qos_custom_policy: + host: apic + username: admin + password: SomeSecretPassword + tenant: my_tenant + state: query + delegate_to: localhost + +- name: Query all QoS Custom Policies + cisco.aci.aci_qos_custom_policy: + host: apic + username: admin + password: SomeSecretPassword + state: query + delegate_to: localhost + +- name: Delete a QoS Custom Policy + cisco.aci.aci_qos_custom_policy: + host: apic + username: admin + password: SomeSecretPassword + tenant: my_tenant + qos_custom_policy: my_qos_custom_policy + 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: '' +sent: + description: The actual/minimal configuration pushed to the APIC + returned: info + type: list + sample: + { + "fvTenant": { + "attributes": { + "descr": "Production environment" + } + } + } +previous: + description: The original configuration from the APIC before the module has started + returned: info + type: list + sample: + [ + { + "fvTenant": { + "attributes": { + "descr": "Production", + "dn": "uni/tn-production", + "name": "production", + "nameAlias": "", + "ownerKey": "", + "ownerTag": "" + } + } + } + ] +proposed: + description: The assembled configuration from the user-provided parameters + returned: info + type: dict + sample: + { + "fvTenant": { + "attributes": { + "descr": "Production environment", + "name": "production" + } + } + } +filter_string: + description: The filter string used for the request + returned: failure or debug + type: str + sample: ?rsp-prop-include=config-only +method: + description: The HTTP method used for the request to the APIC + returned: failure or debug + type: str + sample: POST +response: + description: The HTTP response from the APIC + returned: failure or debug + type: str + sample: OK (30 bytes) +status: + description: The HTTP status from the APIC + returned: failure or debug + type: int + sample: 200 +url: + description: The HTTP url used for the request to the APIC + returned: failure or debug + type: str + sample: https://10.11.12.13/api/mo/uni/tn-production.json +""" + + +from ansible.module_utils.basic import AnsibleModule +from ansible_collections.cisco.aci.plugins.module_utils.aci import ACIModule, aci_argument_spec, aci_annotation_spec, aci_owner_spec + + +def main(): + argument_spec = aci_argument_spec() + argument_spec.update(aci_annotation_spec()) + argument_spec.update(aci_owner_spec()) + argument_spec.update( + tenant=dict(type="str", aliases=["tenant_name"]), + qos_custom_policy=dict(type="str", aliases=["qos_custom_policy_name", "name"]), + description=dict(type="str", aliases=["descr"]), + state=dict(type="str", default="present", choices=["absent", "present", "query"]), + ) + + module = AnsibleModule( + argument_spec=argument_spec, + supports_check_mode=True, + required_if=[ + ["state", "absent", ["tenant", "qos_custom_policy"]], + ["state", "present", ["tenant", "qos_custom_policy"]], + ], + ) + + tenant = module.params.get("tenant") + description = module.params.get("description") + qos_custom_policy = module.params.get("qos_custom_policy") + 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="qosCustomPol", + aci_rn="qoscustom-{0}".format(qos_custom_policy), + module_object=qos_custom_policy, + target_filter={"name": qos_custom_policy}, + ), + ) + + aci.get_existing() + + if state == "present": + aci.payload( + aci_class="qosCustomPol", + class_config=dict( + name=qos_custom_policy, + descr=description, + ), + ) + + aci.get_diff(aci_class="qosCustomPol") + + aci.post_config() + + elif state == "absent": + aci.delete_config() + + aci.exit_json() + + +if __name__ == "__main__": + main() diff --git a/ansible_collections/cisco/aci/plugins/modules/aci_qos_dot1p_class.py b/ansible_collections/cisco/aci/plugins/modules/aci_qos_dot1p_class.py new file mode 100644 index 000000000..f6939af20 --- /dev/null +++ b/ansible_collections/cisco/aci/plugins/modules/aci_qos_dot1p_class.py @@ -0,0 +1,355 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- + +# Copyright: (c) 2023, Gaspard Micol (@gmicol) +# 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_qos_dot1p_class +short_description: Manage QoS Dot1P Class (qos:Dot1PClass) +description: +- Manage Dot1P Class levels for QoS Custom Policies on Cisco ACI fabrics. +- The class level for Dot1P to prioritize the map. +options: + tenant: + description: + - The name of an existing tenant. + type: str + aliases: [ tenant_name ] + qos_custom_policy: + description: + - The name of the QoS Custom Policy. + type: str + aliases: [ qos_custom_policy_name ] + priority: + description: + - The desired QoS class level to be used. + - The APIC defaults to C(unspecified) when unset during creation. + type: str + choices: [ level1, level2, level3, level4, level5, level6, unspecified ] + aliases: [ prio ] + dot1p_from: + description: + - The Dot1P range starting value. + type: str + choices: [ background, best_effort, excellent_effort, critical_applications, video, voice, internetwork_control, network_control, unspecified ] + dot1p_to: + description: + - The Dot1P range ending value. + type: str + choices: [ background, best_effort, excellent_effort, critical_applications, video, voice, internetwork_control, network_control, unspecified ] + dot1p_target: + description: + - The Dot1P target 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 ] + target_cos: + description: + - The target COS to be driven based on the range of input values of Dot1P coming into the fabric. + - The APIC defaults to C(unspecified) when unset during creation. + type: str + choices: [ background, best_effort, excellent_effort, critical_applications, video, voice, internetwork_control, network_control, 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 +- cisco.aci.annotation +- cisco.aci.owner + +notes: +- The I(tenant) and I(qos_custom_policy) must exist before using this module in your playbook. + The M(cisco.aci.aci_tenant) and the M(cisco.aci.aci_qos_custom_policy) can be used for this. +seealso: +- module: cisco.aci.aci_tenant +- module: cisco.aci.aci_qos_custom_policy +- name: APIC Management Information Model reference + description: More information about the internal APIC class B(qos:Dot1PClass). + link: https://developer.cisco.com/docs/apic-mim-ref/ +author: +- Gaspard Micol (@gmicol) +""" + +EXAMPLES = r""" +- name: Add a new QoS dot1P Class + cisco.aci.aci_qos_dot1p_class: + host: apic + username: admin + password: SomeSecretPassword + tenant: my_tenant + qos_custom_policy: my_qos_custom_policy + priority: level3 + dot1p_from: best_effort + dot1p_to: excellent_effort + dot1p_target: unspecified + target_cos: unspecified + state: present + delegate_to: localhost + +- name: Query a QoS dot1P Class + cisco.aci.aci_qos_dot1p_class: + host: apic + username: admin + password: SomeSecretPassword + tenant: my_tenant + qos_custom_policy: my_qos_custom_policy + dot1p_from: best_effort + dot1p_to: excellent_effort + state: query + delegate_to: localhost + +- name: Query all QoS dot1P Classes in my_qos_custom_policy + cisco.aci.aci_qos_dot1p_class: + host: apic + username: admin + password: SomeSecretPassword + tenant: my_tenant + qos_custom_policy: my_qos_custom_policy + state: query + delegate_to: localhost + +- name: Query all QoS dot1P Classes + cisco.aci.aci_qos_dot1p_class: + host: apic + username: admin + password: SomeSecretPassword + state: query + delegate_to: localhost + +- name: Delete a QoS dot1P Class + cisco.aci.aci_qos_dot1p_class: + host: apic + username: admin + password: SomeSecretPassword + tenant: my_tenant + qos_custom_policy: my_qos_custom_policy + dot1p_from: best_effort + dot1p_to: excellent_effort + 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: '' +sent: + description: The actual/minimal configuration pushed to the APIC + returned: info + type: list + sample: + { + "fvTenant": { + "attributes": { + "descr": "Production environment" + } + } + } +previous: + description: The original configuration from the APIC before the module has started + returned: info + type: list + sample: + [ + { + "fvTenant": { + "attributes": { + "descr": "Production", + "dn": "uni/tn-production", + "name": "production", + "nameAlias": "", + "ownerKey": "", + "ownerTag": "" + } + } + } + ] +proposed: + description: The assembled configuration from the user-provided parameters + returned: info + type: dict + sample: + { + "fvTenant": { + "attributes": { + "descr": "Production environment", + "name": "production" + } + } + } +filter_string: + description: The filter string used for the request + returned: failure or debug + type: str + sample: ?rsp-prop-include=config-only +method: + description: The HTTP method used for the request to the APIC + returned: failure or debug + type: str + sample: POST +response: + description: The HTTP response from the APIC + returned: failure or debug + type: str + sample: OK (30 bytes) +status: + description: The HTTP status from the APIC + returned: failure or debug + type: int + sample: 200 +url: + description: The HTTP url used for the request to the APIC + returned: failure or debug + type: str + sample: https://10.11.12.13/api/mo/uni/tn-production.json +""" + + +from ansible.module_utils.basic import AnsibleModule +from ansible_collections.cisco.aci.plugins.module_utils.aci import ( + ACIModule, + aci_argument_spec, + aci_annotation_spec, + aci_owner_spec, + aci_contract_dscp_spec, +) +from ansible_collections.cisco.aci.plugins.module_utils.constants import MATCH_TARGET_COS_MAPPING + + +def main(): + argument_spec = aci_argument_spec() + argument_spec.update(aci_annotation_spec()) + argument_spec.update(aci_owner_spec()) + argument_spec.update( + tenant=dict(type="str", aliases=["tenant_name"]), + qos_custom_policy=dict(type="str", aliases=["qos_custom_policy_name"]), + priority=dict( + type="str", + choices=[ + "level1", + "level2", + "level3", + "level4", + "level5", + "level6", + "unspecified", + ], + aliases=["prio"], + ), + dot1p_from=dict(type="str", choices=list(MATCH_TARGET_COS_MAPPING.keys())), + dot1p_to=dict(type="str", choices=list(MATCH_TARGET_COS_MAPPING.keys())), + dot1p_target=aci_contract_dscp_spec(), + target_cos=dict(type="str", choices=list(MATCH_TARGET_COS_MAPPING.keys())), + state=dict(type="str", default="present", choices=["absent", "present", "query"]), + ) + + module = AnsibleModule( + argument_spec=argument_spec, + supports_check_mode=True, + required_if=[ + ["state", "absent", ["tenant", "qos_custom_policy", "dot1p_from", "dot1p_to"]], + ["state", "present", ["tenant", "qos_custom_policy", "dot1p_from", "dot1p_to"]], + ], + ) + + tenant = module.params.get("tenant") + qos_custom_policy = module.params.get("qos_custom_policy") + priority = module.params.get("priority") + dot1p_from = MATCH_TARGET_COS_MAPPING.get(module.params.get("dot1p_from")) + dot1p_to = MATCH_TARGET_COS_MAPPING.get(module.params.get("dot1p_to")) + dot1p_target = module.params.get("dot1p_target") + target_cos = MATCH_TARGET_COS_MAPPING.get(module.params.get("target_cos")) + 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="qosCustomPol", + aci_rn="qoscustom-{0}".format(qos_custom_policy), + module_object=qos_custom_policy, + target_filter={"name": qos_custom_policy}, + ), + subclass_2=dict( + aci_class="qosDot1PClass", + aci_rn="dot1P-{0}-{1}".format(dot1p_from, dot1p_to), + module_object=qos_custom_policy, + target_filter={"from": dot1p_from, "to": dot1p_to}, + ), + ) + + aci.get_existing() + + if state == "present": + aci.payload( + aci_class="qosDot1PClass", + class_config={ + "prio": priority, + "from": dot1p_from, + "to": dot1p_to, + "target": dot1p_target, + "targetCos": target_cos, + }, + ) + + aci.get_diff(aci_class="qosDot1PClass") + + aci.post_config() + + elif state == "absent": + aci.delete_config() + + aci.exit_json() + + +if __name__ == "__main__": + main() diff --git a/ansible_collections/cisco/aci/plugins/modules/aci_qos_dscp_class.py b/ansible_collections/cisco/aci/plugins/modules/aci_qos_dscp_class.py new file mode 100644 index 000000000..18219d0c0 --- /dev/null +++ b/ansible_collections/cisco/aci/plugins/modules/aci_qos_dscp_class.py @@ -0,0 +1,356 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- + +# Copyright: (c) 2023, Gaspard Micol (@gmicol) +# 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_qos_dscp_class +short_description: Manage QoS DSCP Class (qos:DscpClass) +description: +- Manage QoS Custom Differentiated Services Code Point (DSCP) Class levels for QoS Custom Policies on Cisco ACI fabrics. +- The class level for DSCP to prioritize the map. +options: + tenant: + description: + - The name of an existing tenant. + type: str + aliases: [ tenant_name ] + qos_custom_policy: + description: + - The name of the QoS Custom Policy. + type: str + aliases: [ qos_custom_policy_name ] + priority: + description: + - The desired QoS class level to be used. + - The APIC defaults to C(level3) when unset during creation. + type: str + choices: [ level1, level2, level3, level4, level5, level6, unspecified ] + aliases: [ prio ] + dscp_from: + description: + - The DSCP range starting value. + 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 ] + dscp_to: + description: + - The DSCP range ending value. + 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 ] + dscp_target: + description: + - The DSCP target 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 ] + target_cos: + description: + - The target COS to be driven based on the range of input values of DSCP coming into the fabric. + - The APIC defaults to C(unspecified) when unset during creation. + type: str + choices: [ background, best_effort, excellent_effort, critical_applications, video, voice, internetwork_control, network_control, 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 +- cisco.aci.annotation +- cisco.aci.owner + +notes: +- The I(tenant) and I(qos_custom_policy) must exist before using this module in your playbook. + The M(cisco.aci.aci_tenant) and the M(cisco.aci.aci_qos_custom_policy) can be used for this. +seealso: +- module: cisco.aci.aci_tenant +- module: cisco.aci.aci_qos_custom_policy +- name: APIC Management Information Model reference + description: More information about the internal APIC class B(qos:DscpClass). + link: https://developer.cisco.com/docs/apic-mim-ref/ +author: +- Gaspard Micol (@gmicol) +""" + +EXAMPLES = r""" +- name: Add a new QoS DSCP Class + cisco.aci.aci_qos_dscp_class: + host: apic + username: admin + password: SomeSecretPassword + tenant: my_tenant + qos_custom_policy: my_qos_custom_policy + priority: level3 + dscp_from: AF11 + dscp_to: AF21 + dscp_target: unspecified + target_cos: best_effort + state: present + delegate_to: localhost + +- name: Query a QoS DSCP Class + cisco.aci.aci_qos_dscp_class: + host: apic + username: admin + password: SomeSecretPassword + tenant: my_tenant + qos_custom_policy: my_qos_custom_policy + dscp_from: AF11 + dscp_to: AF21 + state: query + delegate_to: localhost + +- name: Query all QoS DSCP Classes in my_qos_custom_policy + cisco.aci.aci_qos_dscp_class: + host: apic + username: admin + password: SomeSecretPassword + tenant: my_tenant + qos_custom_policy: my_qos_custom_policy + state: query + delegate_to: localhost + +- name: Query all QoS DSCP Classes + cisco.aci.aci_qos_dscp_class: + host: apic + username: admin + password: SomeSecretPassword + state: query + delegate_to: localhost + +- name: Delete a QoS DSCP Class + cisco.aci.aci_qos_dscp_class: + host: apic + username: admin + password: SomeSecretPassword + tenant: my_tenant + qos_custom_policy: my_qos_custom_policy + dscp_from: AF11 + dscp_to: AF21 + 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: '' +sent: + description: The actual/minimal configuration pushed to the APIC + returned: info + type: list + sample: + { + "fvTenant": { + "attributes": { + "descr": "Production environment" + } + } + } +previous: + description: The original configuration from the APIC before the module has started + returned: info + type: list + sample: + [ + { + "fvTenant": { + "attributes": { + "descr": "Production", + "dn": "uni/tn-production", + "name": "production", + "nameAlias": "", + "ownerKey": "", + "ownerTag": "" + } + } + } + ] +proposed: + description: The assembled configuration from the user-provided parameters + returned: info + type: dict + sample: + { + "fvTenant": { + "attributes": { + "descr": "Production environment", + "name": "production" + } + } + } +filter_string: + description: The filter string used for the request + returned: failure or debug + type: str + sample: ?rsp-prop-include=config-only +method: + description: The HTTP method used for the request to the APIC + returned: failure or debug + type: str + sample: POST +response: + description: The HTTP response from the APIC + returned: failure or debug + type: str + sample: OK (30 bytes) +status: + description: The HTTP status from the APIC + returned: failure or debug + type: int + sample: 200 +url: + description: The HTTP url used for the request to the APIC + returned: failure or debug + type: str + sample: https://10.11.12.13/api/mo/uni/tn-production.json +""" + + +from ansible.module_utils.basic import AnsibleModule +from ansible_collections.cisco.aci.plugins.module_utils.aci import ( + ACIModule, + aci_argument_spec, + aci_annotation_spec, + aci_owner_spec, + aci_contract_dscp_spec, +) +from ansible_collections.cisco.aci.plugins.module_utils.constants import MATCH_TARGET_COS_MAPPING + + +def main(): + new_dscp_spec = dict((k, aci_contract_dscp_spec()[k]) for k in aci_contract_dscp_spec() if k != "aliases") + argument_spec = aci_argument_spec() + argument_spec.update(aci_annotation_spec()) + argument_spec.update(aci_owner_spec()) + argument_spec.update( + tenant=dict(type="str", aliases=["tenant_name"]), + qos_custom_policy=dict(type="str", aliases=["qos_custom_policy_name"]), + priority=dict( + type="str", + choices=[ + "level1", + "level2", + "level3", + "level4", + "level5", + "level6", + "unspecified", + ], + aliases=["prio"], + ), + dscp_from=new_dscp_spec, + dscp_to=new_dscp_spec, + dscp_target=aci_contract_dscp_spec(), + target_cos=dict(type="str", choices=list(MATCH_TARGET_COS_MAPPING.keys())), + state=dict(type="str", default="present", choices=["absent", "present", "query"]), + ) + + module = AnsibleModule( + argument_spec=argument_spec, + supports_check_mode=True, + required_if=[ + ["state", "absent", ["tenant", "qos_custom_policy", "dscp_from", "dscp_to"]], + ["state", "present", ["tenant", "qos_custom_policy", "dscp_from", "dscp_to"]], + ], + ) + + tenant = module.params.get("tenant") + qos_custom_policy = module.params.get("qos_custom_policy") + priority = module.params.get("priority") + dscp_from = module.params.get("dscp_from") + dscp_to = module.params.get("dscp_to") + dscp_target = module.params.get("dscp_target") + target_cos = MATCH_TARGET_COS_MAPPING.get(module.params.get("target_cos")) + 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="qosCustomPol", + aci_rn="qoscustom-{0}".format(qos_custom_policy), + module_object=qos_custom_policy, + target_filter={"name": qos_custom_policy}, + ), + subclass_2=dict( + aci_class="qosDscpClass", + aci_rn="dcsp-{0}-{1}".format(dscp_from, dscp_to), + module_object=qos_custom_policy, + target_filter={"from": dscp_from, "to": dscp_to}, + ), + ) + + aci.get_existing() + + if state == "present": + aci.payload( + aci_class="qosDscpClass", + class_config={ + "prio": priority, + "from": dscp_from, + "to": dscp_to, + "target": dscp_target, + "targetCos": target_cos, + }, + ) + + aci.get_diff(aci_class="qosDscpClass") + + aci.post_config() + + elif state == "absent": + aci.delete_config() + + aci.exit_json() + + +if __name__ == "__main__": + main() diff --git a/ansible_collections/cisco/aci/plugins/modules/aci_rest.py b/ansible_collections/cisco/aci/plugins/modules/aci_rest.py index ad73cb5bd..43986592a 100644 --- a/ansible_collections/cisco/aci/plugins/modules/aci_rest.py +++ b/ansible_collections/cisco/aci/plugins/modules/aci_rest.py @@ -3,6 +3,7 @@ # Copyright: (c) 2017, Dag Wieers (@dagwieers) # Copyright: (c) 2020, Cindy Zhao (@cizhao) +# Copyright: (c) 2023, Samita Bhattacharjee (@samitab) # 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 @@ -62,6 +63,7 @@ options: default: false extends_documentation_fragment: - cisco.aci.aci +- cisco.aci.annotation notes: - Certain payloads are known not to be idempotent, so be careful when constructing payloads, @@ -73,6 +75,7 @@ notes: - 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. +- Annotation set directly in c(src) or C(content) will take precedent over the C(annotation) parameter. seealso: - module: cisco.aci.aci_tenant - name: Cisco APIC REST API Configuration Guide @@ -81,6 +84,7 @@ seealso: author: - Dag Wieers (@dagwieers) - Cindy Zhao (@cizhao) +- Samita Bhattacharjee (@samitab) """ EXAMPLES = r""" @@ -284,8 +288,11 @@ 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_collections.cisco.aci.plugins.module_utils.aci import ACIModule, aci_argument_spec, aci_annotation_spec from ansible.module_utils._text import to_text +from ansible_collections.cisco.aci.plugins.module_utils.annotation_unsupported import ( + ANNOTATION_UNSUPPORTED, +) def update_qsl(url, params): @@ -303,6 +310,33 @@ def update_qsl(url, params): return url + "?" + "&".join(["%s=%s" % (k, v) for k, v in params.items()]) +def add_annotation(annotation, payload): + """Add annotation to payload only if it has not already been added""" + if annotation and isinstance(payload, dict): + for key, val in payload.items(): + if key in ANNOTATION_UNSUPPORTED: + continue + att = val.get("attributes", {}) + if "annotation" not in att.keys(): + att["annotation"] = annotation + # Recursively add annotation to children + children = val.get("children", None) + if children: + for child in children: + add_annotation(annotation, child) + + +def add_annotation_xml(annotation, tree): + """Add annotation to payload xml only if it has not already been added""" + if annotation: + for element in tree.iter(): + if element.tag in ANNOTATION_UNSUPPORTED: + continue + ann = element.get("annotation") + if ann is None: + element.set("annotation", annotation) + + class ACIRESTModule(ACIModule): def changed(self, d): """Check ACI response for changes""" @@ -335,6 +369,7 @@ class ACIRESTModule(ACIModule): def main(): argument_spec = aci_argument_spec() + argument_spec.update(aci_annotation_spec()) argument_spec.update( path=dict(type="str", required=True, aliases=["uri"]), method=dict(type="str", default="get", choices=["delete", "get", "post"], aliases=["action"]), @@ -353,6 +388,7 @@ def main(): path = module.params.get("path") src = module.params.get("src") rsp_subtree_preserve = module.params.get("rsp_subtree_preserve") + annotation = module.params.get("annotation") # Report missing file file_exists = False @@ -388,21 +424,27 @@ def main(): if rest_type == "json": if content and isinstance(content, dict): # Validate inline YAML/JSON + add_annotation(annotation, payload) 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)) + payload = yaml.safe_load(payload) + add_annotation(annotation, payload) + payload = json.dumps(payload) except Exception as e: module.fail_json(msg="Failed to parse provided JSON/YAML payload: {0}".format(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 + add_annotation(annotation, payload) payload = etree.tostring(cobra.etree(payload)[0], encoding="unicode") elif payload and isinstance(payload, str): try: # Validate XML string - payload = etree.tostring(etree.fromstring(payload), encoding="unicode") + payload = etree.fromstring(payload) + add_annotation_xml(annotation, payload) + payload = etree.tostring(payload, encoding="unicode") except Exception as e: module.fail_json(msg="Failed to parse provided XML payload: {0}".format(to_text(e)), payload=payload) diff --git a/ansible_collections/cisco/aci/plugins/modules/aci_snmp_client.py b/ansible_collections/cisco/aci/plugins/modules/aci_snmp_client.py index a7c01dc8e..545167377 100644 --- a/ansible_collections/cisco/aci/plugins/modules/aci_snmp_client.py +++ b/ansible_collections/cisco/aci/plugins/modules/aci_snmp_client.py @@ -12,7 +12,7 @@ ANSIBLE_METADATA = {"metadata_version": "1.1", "status": ["preview"], "supported DOCUMENTATION = r""" --- module: aci_snmp_client -short_description: Manage SNMP clients (snmp:ClientP). +short_description: Manage SNMP clients (snmp:ClientP) description: - Manage SNMP clients options: diff --git a/ansible_collections/cisco/aci/plugins/modules/aci_snmp_client_group.py b/ansible_collections/cisco/aci/plugins/modules/aci_snmp_client_group.py index 7f7b12504..b18d4aecc 100644 --- a/ansible_collections/cisco/aci/plugins/modules/aci_snmp_client_group.py +++ b/ansible_collections/cisco/aci/plugins/modules/aci_snmp_client_group.py @@ -12,7 +12,7 @@ ANSIBLE_METADATA = {"metadata_version": "1.1", "status": ["preview"], "supported DOCUMENTATION = r""" --- module: aci_snmp_client_group -short_description: Manage SNMP client groups (snmp:ClientGrpP). +short_description: Manage SNMP client groups (snmp:ClientGrpP) description: - Manage SNMP client groups options: diff --git a/ansible_collections/cisco/aci/plugins/modules/aci_snmp_community_policy.py b/ansible_collections/cisco/aci/plugins/modules/aci_snmp_community_policy.py index 446962165..1494a6bbe 100644 --- a/ansible_collections/cisco/aci/plugins/modules/aci_snmp_community_policy.py +++ b/ansible_collections/cisco/aci/plugins/modules/aci_snmp_community_policy.py @@ -12,7 +12,7 @@ ANSIBLE_METADATA = {"metadata_version": "1.1", "status": ["preview"], "supported DOCUMENTATION = r""" --- module: aci_snmp_community_policy -short_description: Manage SNMP community policies (snmp:CommunityP). +short_description: Manage SNMP community policies (snmp:CommunityP) description: - Manage SNMP community policies options: diff --git a/ansible_collections/cisco/aci/plugins/modules/aci_snmp_policy.py b/ansible_collections/cisco/aci/plugins/modules/aci_snmp_policy.py index c3956db2f..3295453a7 100644 --- a/ansible_collections/cisco/aci/plugins/modules/aci_snmp_policy.py +++ b/ansible_collections/cisco/aci/plugins/modules/aci_snmp_policy.py @@ -12,9 +12,9 @@ ANSIBLE_METADATA = {"metadata_version": "1.1", "status": ["preview"], "supported DOCUMENTATION = r""" --- module: aci_snmp_policy -short_description: Manage Syslog groups (snmp:Pol). +short_description: Manage Syslog groups (snmp:Pol) description: -- Manage syslog policies +- Manage syslog policies. options: admin_state: description: diff --git a/ansible_collections/cisco/aci/plugins/modules/aci_snmp_user.py b/ansible_collections/cisco/aci/plugins/modules/aci_snmp_user.py index 9e9b6d852..23e7c6f3e 100644 --- a/ansible_collections/cisco/aci/plugins/modules/aci_snmp_user.py +++ b/ansible_collections/cisco/aci/plugins/modules/aci_snmp_user.py @@ -14,9 +14,9 @@ ANSIBLE_METADATA = {"metadata_version": "1.1", "status": ["preview"], "supported DOCUMENTATION = r""" --- module: aci_snmp_user -short_description: Manage SNMP v3 Users (snmp:UserP). +short_description: Manage SNMP v3 Users (snmp:UserP) description: -- Manage SNMP v3 Users +- Manage SNMP v3 Users. - Note that all properties within the snmpUserP class are Create-only. To modify any property of an existing user, you must delete and re-create it. options: auth_type: diff --git a/ansible_collections/cisco/aci/plugins/modules/aci_static_node_mgmt_address.py b/ansible_collections/cisco/aci/plugins/modules/aci_static_node_mgmt_address.py index 62602487e..bc99969be 100644 --- a/ansible_collections/cisco/aci/plugins/modules/aci_static_node_mgmt_address.py +++ b/ansible_collections/cisco/aci/plugins/modules/aci_static_node_mgmt_address.py @@ -13,7 +13,7 @@ __metaclass__ = type DOCUMENTATION = r""" --- module: aci_static_node_mgmt_address -short_description: In band or Out of band management IP address +short_description: In band or Out of band management IP address (mgmt:RsOoBStNode and mgmt:RsInBStNode) description: - Cisco ACI Fabric Node IP address options: @@ -65,6 +65,10 @@ extends_documentation_fragment: - cisco.aci.aci - cisco.aci.annotation +seealso: +- name: APIC Management Information Model reference + description: More information about the internal APIC classes B(mgmt:RsOoBStNode) and B(mgmt:RsInBStNode). + link: https://developer.cisco.com/docs/apic-mim-ref/ author: - Sudhakar Shet Kudtarkar (@kudtarkar1) - Lionel Hercot (@lhercot) diff --git a/ansible_collections/cisco/aci/plugins/modules/aci_subject_label.py b/ansible_collections/cisco/aci/plugins/modules/aci_subject_label.py new file mode 100644 index 000000000..a68c39d8f --- /dev/null +++ b/ansible_collections/cisco/aci/plugins/modules/aci_subject_label.py @@ -0,0 +1,746 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- + +# Copyright: (c) 2022, Mark Ciecior (@markciecior) +# Copyright: (c) 2024, Akini Ross +# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) + +from __future__ import absolute_import, division, print_function + +__metaclass__ = type + +ANSIBLE_METADATA = {"metadata_version": "1.1", "status": ["preview"], "supported_by": "certified"} + +DOCUMENTATION = r""" +--- +module: aci_subject_label +short_description: Manage Subject Labels (vz:ConsSubjLbl and vz:ProvSubjLbl) +description: +- Manage Subject Labels on Cisco ACI fabrics. +options: + tenant: + description: + - The name of the Tenant. + type: str + aliases: [ tenant_name ] + l2out: + description: + - The name of the L2Out. + type: str + aliases: [ l2out_name ] + l3out: + description: + - The name of the L3Out. + type: str + aliases: [ l3out_name ] + external_epg: + description: + - The name of the External End Point Group. + type: str + aliases: [ extepg, extepg_name, external_epg_name ] + contract: + description: + - The name of the Contract. + type: str + aliases: [ contract_name ] + subject: + description: + - The name of the Subject. + type: str + aliases: [ subject_name ] + ap: + description: + - The name of the Application Profile. + type: str + aliases: [ app_profile, app_profile_name, application_profile, application_profile_name] + epg: + description: + - The name of the End Point Group. + type: str + aliases: [ epg_name ] + esg: + description: + - The name of the Endpoint Security Group. + type: str + aliases: [ esg_name ] + subject_label: + description: + - The name of the Subject Label. + type: str + aliases: [ subject_label_name, name, label ] + subject_label_type: + description: + - Determines the type of the Subject Label. + type: str + required: true + choices: [ consumer, provider ] + aliases: [ type ] + complement: + description: + - Whether complement is enabled on the Subject Label. + - The APIC defaults to C(false) when unset during creation. + type: bool + tag: + description: + - The color of a policy label of the Subject Label. + - The APIC defaults to C(yellow-green) when unset during creation. + type: str + choices: + - alice_blue + - antique_white + - aqua + - aquamarine + - azure + - beige + - bisque + - black + - blanched_almond + - blue + - blue_violet + - brown + - burlywood + - cadet_blue + - chartreuse + - chocolate + - coral + - cornflower_blue + - cornsilk + - crimson + - cyan + - dark_blue + - dark_cyan + - dark_goldenrod + - dark_gray + - dark_green + - dark_khaki + - dark_magenta + - dark_olive_green + - dark_orange + - dark_orchid + - dark_red + - dark_salmon + - dark_sea_green + - dark_slate_blue + - dark_slate_gray + - dark_turquoise + - dark_violet + - deep_pink + - deep_sky_blue + - dim_gray + - dodger_blue + - fire_brick + - floral_white + - forest_green + - fuchsia + - gainsboro + - ghost_white + - gold + - goldenrod + - gray + - green + - green_yellow + - honeydew + - hot_pink + - indian_red + - indigo + - ivory + - khaki + - lavender + - lavender_blush + - lawn_green + - lemon_chiffon + - light_blue + - light_coral + - light_cyan + - light_goldenrod_yellow + - light_gray + - light_green + - light_pink + - light_salmon + - light_sea_green + - light_sky_blue + - light_slate_gray + - light_steel_blue + - light_yellow + - lime + - lime_green + - linen + - magenta + - maroon + - medium_aquamarine + - medium_blue + - medium_orchid + - medium_purple + - medium_sea_green + - medium_slate_blue + - medium_spring_green + - medium_turquoise + - medium_violet_red + - midnight_blue + - mint_cream + - misty_rose + - moccasin + - navajo_white + - navy + - old_lace + - olive + - olive_drab + - orange + - orange_red + - orchid + - pale_goldenrod + - pale_green + - pale_turquoise + - pale_violet_red + - papaya_whip + - peachpuff + - peru + - pink + - plum + - powder_blue + - purple + - red + - rosy_brown + - royal_blue + - saddle_brown + - salmon + - sandy_brown + - sea_green + - seashell + - sienna + - silver + - sky_blue + - slate_blue + - slate_gray + - snow + - spring_green + - steel_blue + - tan + - teal + - thistle + - tomato + - turquoise + - violet + - wheat + - white + - white_smoke + - yellow + - yellow_green + description: + description: + - The description for the Subject Label. + 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 +- cisco.aci.annotation +- cisco.aci.owner + +seealso: +- name: APIC Management Information Model reference + description: More information about the internal APIC class B(vz:ConsSubjLbl) and (vz:ProvSubjLbl). + link: https://developer.cisco.com/docs/apic-mim-ref/ +author: +- Mark Ciecior (@markciecior) +- Akini Ross (@akinross) +""" + +EXAMPLES = r""" +- name: Add a Subject Label on a Contract Subject + cisco.aci.aci_subject_label: + host: apic + username: admin + password: SomeSecretPassword + tenant: production + contract: web + subject: web_subject + subject_label: web_subject_label + subject_type: consumer + state: present + delegate_to: localhost + +- name: Add a Subject Label on a L2Out External EPG + cisco.aci.aci_subject_label: + host: apic + username: admin + password: SomeSecretPassword + tenant: production + l2out: l2out_name + external_epg: external_epg_name + subject_label: l2out_subject_label + subject_type: consumer + state: present + delegate_to: localhost + +- name: Add a Subject Label on a L3Out External EPG + cisco.aci.aci_subject_label: + host: apic + username: admin + password: SomeSecretPassword + tenant: production + l3out: l3out_name + external_epg: external_epg_name + subject_label: l3out_subject_label + subject_type: consumer + state: present + delegate_to: localhost + +- name: Add a Subject Label on a L3Out External EPG Contract + cisco.aci.aci_subject_label: + host: apic + username: admin + password: SomeSecretPassword + tenant: production + l3out: l3out_name + external_epg: external_epg_name + contract: web + subject_label: l3out_subject_label + subject_type: consumer + state: present + delegate_to: localhost + +- name: Add a Subject Label on a ESG + cisco.aci.aci_subject_label: + host: apic + username: admin + password: SomeSecretPassword + tenant: production + ap: app_profile_name + esg: esg_name + subject_label: esg_subject_label + subject_type: consumer + state: present + delegate_to: localhost + +- name: Add a Subject Label on a EPG + cisco.aci.aci_subject_label: + host: apic + username: admin + password: SomeSecretPassword + tenant: production + ap: app_profile_name + epg: epg_name + subject_label: epg_subject_label + subject_type: consumer + state: present + delegate_to: localhost + +- name: Add a Subject Label on a EPG Contract + cisco.aci.aci_subject_label: + host: apic + username: admin + password: SomeSecretPassword + tenant: production + ap: app_profile_name + epg: epg_name + contract: web + subject_label: epg_subject_label + subject_type: consumer + state: present + delegate_to: localhost + +- name: Query a Subject Label on a Contract Subject + cisco.aci.aci_subject_label: + host: apic + username: admin + password: SomeSecretPassword + tenant: production + contract: web + subject: web_subject + subject_label: web_subject_label + subject_type: consumer + state: query + delegate_to: localhost + register: query_result + +- name: Query all Subject Labels + cisco.aci.aci_subject_label: + host: apic + username: admin + password: SomeSecretPassword + state: query + delegate_to: localhost + register: query_result + +- name: Remove a Subject Label on a Contract Subject + cisco.aci.aci_subject_label: + host: apic + username: admin + password: SomeSecretPassword + tenant: production + contract: web + subject: web_subject + subject_label: web_subject_label + subject_type: consumer + 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: '' +sent: + description: The actual/minimal configuration pushed to the APIC + returned: info + type: list + sample: + { + "fvTenant": { + "attributes": { + "descr": "Production environment" + } + } + } +previous: + description: The original configuration from the APIC before the module has started + returned: info + type: list + sample: + [ + { + "fvTenant": { + "attributes": { + "descr": "Production", + "dn": "uni/tn-production", + "name": "production", + "nameAlias": "", + "ownerKey": "", + "ownerTag": "" + } + } + } + ] +proposed: + description: The assembled configuration from the user-provided parameters + returned: info + type: dict + sample: + { + "fvTenant": { + "attributes": { + "descr": "Production environment", + "name": "production" + } + } + } +filter_string: + description: The filter string used for the request + returned: failure or debug + type: str + sample: ?rsp-prop-include=config-only +method: + description: The HTTP method used for the request to the APIC + returned: failure or debug + type: str + sample: POST +response: + description: The HTTP response from the APIC + returned: failure or debug + type: str + sample: OK (30 bytes) +status: + description: The HTTP status from the APIC + returned: failure or debug + type: int + sample: 200 +url: + description: The HTTP url used for the request to the APIC + returned: failure or debug + type: str + sample: https://10.11.12.13/api/mo/uni/tn-production.json +""" + +from ansible.module_utils.basic import AnsibleModule +from ansible_collections.cisco.aci.plugins.module_utils.aci import ACIModule, aci_argument_spec, aci_annotation_spec, aci_owner_spec +from ansible_collections.cisco.aci.plugins.module_utils.constants import ACI_CLASS_MAPPING, SUBJ_LABEL_MAPPING, SUBJ_LABEL_RN, POLICY_LABEL_COLORS + + +def main(): + argument_spec = aci_argument_spec() + argument_spec.update(aci_annotation_spec()) + argument_spec.update(aci_owner_spec()) + argument_spec.update( + tenant=dict(type="str", aliases=["tenant_name"]), + l2out=dict(type="str", aliases=["l2out_name"]), + l3out=dict(type="str", aliases=["l3out_name"]), + external_epg=dict(type="str", aliases=["extepg", "extepg_name", "external_epg_name"]), + contract=dict(type="str", aliases=["contract_name"]), + subject=dict(type="str", aliases=["subject_name"]), + ap=dict(type="str", aliases=["app_profile", "app_profile_name", "application_profile", "application_profile_name"]), + epg=dict(type="str", aliases=["epg_name"]), + esg=dict(type="str", aliases=["esg_name"]), + complement=dict(type="bool"), + description=dict(type="str", aliases=["descr"]), + subject_label=dict(type="str", aliases=["subject_label_name", "name", "label"]), + subject_label_type=dict(type="str", choices=["consumer", "provider"], aliases=["type"], required=True), + tag=dict(type="str", choices=POLICY_LABEL_COLORS), + 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", ["tenant", "subject_label"]], + ["state", "present", ["l2out", "l3out", "epg", "esg", "subject"], True], + ["state", "absent", ["tenant", "subject_label"]], + ["state", "absent", ["l2out", "l3out", "epg", "esg", "subject"], True], + ], + mutually_exclusive=[ + ["l2out", "l3out", "epg", "esg", "subject"], + ["esg", "contract"], + ["l2out", "contract"], + ], + required_by={ + "subject": ["contract"], + "l2out": ["external_epg"], + "l3out": ["external_epg"], + "epg": ["ap"], + "esg": ["ap"], + }, + ) + + aci = ACIModule(module) + + tenant = module.params.get("tenant") + l2out = module.params.get("l2out") + l3out = module.params.get("l3out") + external_epg = module.params.get("external_epg") + contract = module.params.get("contract") + subject_label_type = module.params.get("subject_label_type") + subject = module.params.get("subject") + ap = module.params.get("ap") + epg = module.params.get("epg") + esg = module.params.get("esg") + complement = aci.boolean(module.params.get("complement")) + description = module.params.get("description") + subject_label = module.params.get("subject_label") + tag = module.params.get("tag") + state = module.params.get("state") + name_alias = module.params.get("name_alias") + + aci_class = SUBJ_LABEL_MAPPING.get(subject_label_type) + aci_rn = SUBJ_LABEL_RN.get(subject_label_type) + subject_label if subject_label else None + + if contract: + contract_rn = ACI_CLASS_MAPPING.get(subject_label_type).get("rn") + contract + contract_class = ACI_CLASS_MAPPING.get(subject_label_type).get("class") + + root_class = dict( + aci_class="fvTenant", + aci_rn="tn-{0}".format(tenant), + module_object=tenant, + target_filter={"name": tenant}, + ) + subclass_1 = None + subclass_2 = None + subclass_3 = None + subclass_4 = None + if esg: + subclass_1 = dict( + aci_class="fvAp", + aci_rn="ap-{0}".format(ap), + module_object=ap, + target_filter={"name": ap}, + ) + subclass_2 = dict( + aci_class="fvESg", + aci_rn="esg-{0}".format(esg), + module_object=esg, + target_filter={"name": esg}, + ) + subclass_3 = dict( + aci_class=aci_class, + aci_rn=aci_rn, + module_object=subject_label, + target_filter={"name": subject_label}, + ) + elif l2out: + 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(external_epg), + module_object=external_epg, + target_filter={"name": external_epg}, + ) + subclass_3 = dict( + aci_class=aci_class, + aci_rn=aci_rn, + module_object=subject_label, + target_filter={"name": subject_label}, + ) + elif epg: + 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}, + ) + if contract: + subclass_3 = dict( + aci_class=contract_class, + aci_rn=contract_rn, + module_object=contract, + target_filter={"name": contract}, + ) + subclass_4 = dict( + aci_class=aci_class, + aci_rn=aci_rn, + module_object=subject_label, + target_filter={"name": subject_label}, + ) + else: + subclass_3 = dict( + aci_class=aci_class, + aci_rn=aci_rn, + module_object=subject_label, + target_filter={"name": subject_label}, + ) + elif l3out: + subclass_1 = 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(external_epg), + module_object=external_epg, + target_filter={"name": external_epg}, + ) + if contract: + subclass_3 = dict( + aci_class=contract_class, + aci_rn=contract_rn, + module_object=contract, + target_filter={"name": contract}, + ) + subclass_4 = dict( + aci_class=aci_class, + aci_rn=aci_rn, + module_object=subject_label, + target_filter={"name": subject_label}, + ) + else: + subclass_3 = dict( + aci_class=aci_class, + aci_rn=aci_rn, + module_object=subject_label, + target_filter={"name": subject_label}, + ) + elif subject: + 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=aci_class, + aci_rn=aci_rn, + module_object=subject_label, + target_filter={"name": subject_label}, + ) + else: # Query scenario without any filters forcing class query on the subject_label_class + root_class = dict( + aci_class=aci_class, + aci_rn=aci_rn, + module_object=subject_label, + target_filter={"name": subject_label}, + ) + + aci.construct_url( + root_class=root_class, + subclass_1=subclass_1, + subclass_2=subclass_2, + subclass_3=subclass_3, + subclass_4=subclass_4, + ) + + aci.get_existing() + + if state == "present": + aci.payload( + aci_class=aci_class, + class_config=dict( + name=subject_label, + descr=description, + nameAlias=name_alias, + isComplement=complement, + tag=tag.replace("_", "-") if tag else None, + ), + ) + + 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/ansible_collections/cisco/aci/plugins/modules/aci_switch_leaf_selector.py b/ansible_collections/cisco/aci/plugins/modules/aci_switch_leaf_selector.py index 2b850f1cd..bf081bd57 100644 --- a/ansible_collections/cisco/aci/plugins/modules/aci_switch_leaf_selector.py +++ b/ansible_collections/cisco/aci/plugins/modules/aci_switch_leaf_selector.py @@ -2,6 +2,7 @@ # -*- coding: utf-8 -*- # Copyright: (c) 2017, Bruno Calogero +# Copyright: (c) 2024, Gaspard Micol (@gmicol) # 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 @@ -13,7 +14,7 @@ ANSIBLE_METADATA = {"metadata_version": "1.1", "status": ["preview"], "supported DOCUMENTATION = r""" --- module: aci_switch_leaf_selector -short_description: Bind leaf selectors to switch policy leaf profiles (infra:LeafS, infra:NodeBlk, infra:RsAccNodePGrep) +short_description: Bind leaf selectors to switch policy leaf profiles (infra:LeafS, infra:NodeBlk, and infra:RsAccNodePGrep) description: - Bind leaf selectors (with node block range and policy group) to switch policy leaf profiles on Cisco ACI fabrics. options: @@ -82,6 +83,7 @@ seealso: link: https://developer.cisco.com/docs/apic-mim-ref/ author: - Bruno Calogero (@brunocalogero) +- Gaspard Micol (@gmicol) """ EXAMPLES = r""" @@ -266,7 +268,7 @@ def main(): 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"]]], + required_if=[["state", "absent", ["leaf_profile", "leaf"]], ["state", "present", ["leaf_profile", "leaf"]]], ) description = module.params.get("description") @@ -280,19 +282,21 @@ def main(): 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_, + child_configs = [] + # Add infraNodeBlk only when leaf_node_blk was defined + if leaf_node_blk is not None: + child_configs.append( + 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: diff --git a/ansible_collections/cisco/aci/plugins/modules/aci_switch_policy_vpc_protection_group.py b/ansible_collections/cisco/aci/plugins/modules/aci_switch_policy_vpc_protection_group.py index a7994db73..507c84a17 100644 --- a/ansible_collections/cisco/aci/plugins/modules/aci_switch_policy_vpc_protection_group.py +++ b/ansible_collections/cisco/aci/plugins/modules/aci_switch_policy_vpc_protection_group.py @@ -13,7 +13,7 @@ ANSIBLE_METADATA = {"metadata_version": "1.1", "status": ["preview"], "supported DOCUMENTATION = r""" --- module: aci_switch_policy_vpc_protection_group -short_description: Manage switch policy explicit vPC protection groups (fabric:ExplicitGEp, fabric:NodePEp). +short_description: Manage switch policy explicit vPC protection groups (fabric:ExplicitGEp and fabric:NodePEp). description: - Manage switch policy explicit vPC protection groups on Cisco ACI fabrics. options: diff --git a/ansible_collections/cisco/aci/plugins/modules/aci_syslog_group.py b/ansible_collections/cisco/aci/plugins/modules/aci_syslog_group.py index bab3379a1..205c3593b 100644 --- a/ansible_collections/cisco/aci/plugins/modules/aci_syslog_group.py +++ b/ansible_collections/cisco/aci/plugins/modules/aci_syslog_group.py @@ -12,9 +12,9 @@ ANSIBLE_METADATA = {"metadata_version": "1.1", "status": ["preview"], "supported DOCUMENTATION = r""" --- module: aci_syslog_group -short_description: Manage Syslog groups (syslog:Group, syslog:Console, syslog:File and syslog:Prof). +short_description: Manage Syslog groups (syslog:Group, syslog:Console, syslog:File and syslog:Prof) description: -- Manage syslog groups +- Manage syslog groups. options: admin_state: description: @@ -72,7 +72,7 @@ extends_documentation_fragment: seealso: - name: APIC Management Information Model reference - description: More information about the internal APIC classes B(syslog:Group). + description: More information about the internal APIC classes B(syslog:Group), B(syslog:Console), B(syslog:File) and B(syslog:Prof). link: https://developer.cisco.com/docs/apic-mim-ref/ author: - Tim Cragg (@timcragg) diff --git a/ansible_collections/cisco/aci/plugins/modules/aci_syslog_remote_dest.py b/ansible_collections/cisco/aci/plugins/modules/aci_syslog_remote_dest.py index b3c1a02b4..43d2e85eb 100644 --- a/ansible_collections/cisco/aci/plugins/modules/aci_syslog_remote_dest.py +++ b/ansible_collections/cisco/aci/plugins/modules/aci_syslog_remote_dest.py @@ -12,10 +12,9 @@ ANSIBLE_METADATA = {"metadata_version": "1.1", "status": ["preview"], "supported DOCUMENTATION = r""" --- module: aci_syslog_remote_dest -short_description: Manage Syslog Remote Destinations (syslog:RemoteDest). +short_description: Manage Syslog Remote Destinations (syslog:RemoteDest) description: -- Manage remote destinations for syslog messages within - an existing syslog group object +- Manage remote destinations for syslog messages within an existing syslog group object. options: admin_state: description: diff --git a/ansible_collections/cisco/aci/plugins/modules/aci_syslog_source.py b/ansible_collections/cisco/aci/plugins/modules/aci_syslog_source.py index b0bb61bb5..0e3bc6b78 100644 --- a/ansible_collections/cisco/aci/plugins/modules/aci_syslog_source.py +++ b/ansible_collections/cisco/aci/plugins/modules/aci_syslog_source.py @@ -15,7 +15,7 @@ DOCUMENTATION = r""" module: aci_syslog_source short_description: Manage Syslog Source objects (syslog:Src) description: -- Manage Syslog Source objects +- Manage Syslog Source objects. options: name: description: diff --git a/ansible_collections/cisco/aci/plugins/modules/aci_system.py b/ansible_collections/cisco/aci/plugins/modules/aci_system.py index 6a3349ec0..53e2b90e8 100644 --- a/ansible_collections/cisco/aci/plugins/modules/aci_system.py +++ b/ansible_collections/cisco/aci/plugins/modules/aci_system.py @@ -13,7 +13,7 @@ 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. +- Query the ACI system information on Cisco ACI. author: - Lionel Hercot (@lhercot) options: @@ -30,10 +30,11 @@ options: 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. - +seealso: +- name: APIC Management Information Model reference + description: More information about the internal APIC class B(top:System). + link: https://developer.cisco.com/docs/apic-mim-ref/ extends_documentation_fragment: - cisco.aci.aci """ diff --git a/ansible_collections/cisco/aci/plugins/modules/aci_tag.py b/ansible_collections/cisco/aci/plugins/modules/aci_tag.py index 9e56ae068..d005b462b 100644 --- a/ansible_collections/cisco/aci/plugins/modules/aci_tag.py +++ b/ansible_collections/cisco/aci/plugins/modules/aci_tag.py @@ -12,7 +12,7 @@ ANSIBLE_METADATA = {"metadata_version": "1.1", "status": ["preview"], "supported DOCUMENTATION = r""" --- module: aci_tag -short_description: Tagging of ACI objects +short_description: Tagging of ACI objects (tag:Annotation, tag:Inst, and tag:Tag) description: - Tagging a object on Cisco ACI fabric. options: @@ -50,7 +50,11 @@ notes: - CAVEAT - Due to deprecation of the 'tagInst' object, creating a tag with tag_type 'instance' automatically generates a 'annotation' tag_type tag with an empty value. When deleting a tag_type 'instance', the 'tagAnnotation' object will remain present and needs to be deleted separately. + seealso: +- name: APIC Management Information Model reference + description: More information about the internal APIC classes B(tag:Annotation), B(tag:Inst), and B(tag:Tag). + link: https://developer.cisco.com/docs/apic-mim-ref/ - name: Cisco APIC System Management Configuration Guide description: More information about the tagging can be found in the Cisco APIC System Management Configuration Guide. link: https://www.cisco.com/c/en/us/support/cloud-systems-management/application-policy-infrastructure-controller-apic/tsd-products-support-series-home.html diff --git a/ansible_collections/cisco/aci/plugins/modules/aci_tenant_action_rule_profile.py b/ansible_collections/cisco/aci/plugins/modules/aci_tenant_action_rule_profile.py index 55b76f3d6..f51d28fcd 100644 --- a/ansible_collections/cisco/aci/plugins/modules/aci_tenant_action_rule_profile.py +++ b/ansible_collections/cisco/aci/plugins/modules/aci_tenant_action_rule_profile.py @@ -1,6 +1,9 @@ #!/usr/bin/python # -*- coding: utf-8 -*- +# Copyright: (c) 2023, Dag Wieers (@dagwieers) +# Copyright: (c) 2023, Tim Cragg (@timcragg) +# Copyright: (c) 2023, Gaspard Micol (@gmicol) # 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 @@ -16,21 +19,105 @@ short_description: Manage action rule profiles (rtctrl:AttrP) description: - Manage action rule profiles on Cisco ACI fabrics. options: + tenant: + description: + - The name of the tenant. + type: str + aliases: [ tenant_name ] action_rule: description: - The name of the action rule profile. type: str - aliases: [ action_rule_name, name ] + aliases: [action_rule_name, name ] + set_community: + description: + - The set action rule based on communities. + - To delete this attribute, pass an empty dictionary. + type: dict + suboptions: + community: + description: + - The community value. + type: str + criteria: + description: + - The community criteria. + - The option to append or replace the community value. + type: str + choices: [ append, replace, none ] + set_dampening: + description: + - The set action rule based on dampening. + - To delete this attribute, pass an empty dictionary. + type: dict + suboptions: + half_life: + description: + - The half life value (minutes). + type: int + max_suppress_time: + description: + - The maximum suppress time value (minutes). + type: int + reuse: + description: + - The reuse limit value. + type: int + suppress: + description: + - The suppress limit value. + type: int + set_next_hop: + description: + - The set action rule based on the next hop address. + - To delete this attribute, pass an empty string. + type: str + next_hop_propagation: + description: + - The set action rule based on nexthop unchanged configuration. + - Can not be configured along with C(set_route_tag). + - Can not be configured for APIC version 4.2 and prior. + - The APIC defaults to C(false) when unset. + type: bool + multipath: + description: + - Set action rule based on set redistribute multipath configuration. + - Can not be configured along with C(set_route_tag). + - Can not be configured for APIC version 4.2 and prior. + - The APIC defaults to C(false) when unset. + type: bool + set_preference: + description: + - The set action rule based on preference. + - To delete this attribute, pass an empty string. + type: str + set_metric: + description: + - The set action rule based on metric. + - To delete this attribute, pass an empty string. + type: str + set_metric_type: + description: + - The set action rule based on a metric type. + - To delete this attribute, pass an empty string. + type: str + choices: [ ospf_type_1, ospf_type_2, "" ] + set_route_tag: + description: + - The set action rule based on route tag. + - Can not be configured along with C(next_hop_propagation) and C(multipath). + - To delete this attribute, pass an empty string. + type: str + set_weight: + description: + - The set action rule based on weight. + - To delete this attribute, pass an empty string. + type: str 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. @@ -56,6 +143,8 @@ seealso: link: https://developer.cisco.com/docs/apic-mim-ref/ author: - Dag Wieers (@dagwieers) +- Tim Cragg (@timcragg) +- Gaspard Micol (@gmicol) """ EXAMPLES = r""" @@ -66,6 +155,40 @@ EXAMPLES = r""" password: SomeSecretPassword action_rule: my_action_rule tenant: prod + set_preference: 100 + set_weight: 100 + set_metric: 100 + set_metric_type: ospf_type_1 + set_next_hop: 1.1.1.1 + next_hop_propagation: true + multipath: true + set_community: + community: no-advertise + criteria: replace + set_dampening: + half_life: 10 + reuse: 1 + suppress: 10 + max_suppress_time: 100 + state: present + delegate_to: localhost + +- name: Delete action rule profile's children + cisco.aci.aci_tenant_action_rule_profile: + host: apic + username: admin + password: SomeSecretPassword + action_rule: my_action_rule + tenant: prod + set_preference: "" + set_weight: "" + set_metric: "" + set_metric_type: "" + set_next_hop: "" + next_hop_propagation: false + multipath: false + set_community: {} + set_dampening: {} state: present delegate_to: localhost @@ -206,7 +329,14 @@ url: """ from ansible.module_utils.basic import AnsibleModule -from ansible_collections.cisco.aci.plugins.module_utils.aci import ACIModule, aci_argument_spec, aci_annotation_spec +from ansible_collections.cisco.aci.plugins.module_utils.aci import ( + ACIModule, + aci_argument_spec, + aci_annotation_spec, + action_rule_set_comm_spec, + action_rule_set_dampening_spec, +) +from ansible_collections.cisco.aci.plugins.module_utils.constants import MATCH_ACTION_RULE_SET_METRIC_TYPE_MAPPING def main(): @@ -215,6 +345,16 @@ def main(): 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 + set_community=dict(type="dict", options=action_rule_set_comm_spec()), + set_dampening=dict(type="dict", options=action_rule_set_dampening_spec()), + set_next_hop=dict(type="str"), + next_hop_propagation=dict(type="bool"), + multipath=dict(type="bool"), + set_preference=dict(type="str"), + set_metric=dict(type="str"), + set_metric_type=dict(type="str", choices=["ospf_type_1", "ospf_type_2", ""]), + set_route_tag=dict(type="str"), + set_weight=dict(type="str"), description=dict(type="str", aliases=["descr"]), state=dict(type="str", default="present", choices=["absent", "present", "query"]), name_alias=dict(type="str"), @@ -236,6 +376,31 @@ def main(): name_alias = module.params.get("name_alias") aci = ACIModule(module) + + # This dict contains the name of the child classes as well as the corresping attribute input (and attribute name if the input is a string) + # this dict is deviating from normal child classes list structure in order to determine which child classes should be created, modified, deleted or ignored. + child_classes = dict( + rtctrlSetComm=dict(attribute_input=module.params.get("set_community")), + rtctrlSetDamp=dict(attribute_input=module.params.get("set_dampening")), + rtctrlSetNh=dict(attribute_input=module.params.get("set_next_hop"), attribute_name="addr"), + rtctrlSetPref=dict(attribute_input=module.params.get("set_preference"), attribute_name="localPref"), + rtctrlSetRtMetric=dict(attribute_input=module.params.get("set_metric"), attribute_name="metric"), + rtctrlSetRtMetricType=dict( + attribute_input=MATCH_ACTION_RULE_SET_METRIC_TYPE_MAPPING.get(module.params.get("set_metric_type")), attribute_name="metricType" + ), + rtctrlSetTag=dict(attribute_input=module.params.get("set_route_tag"), attribute_name="tag"), + rtctrlSetWeight=dict(attribute_input=module.params.get("set_weight"), attribute_name="weight"), + ) + + # This condition deal with child classes which do not exist in APIC version 4.2 and prior. + additional_child_classes = dict( + rtctrlSetNhUnchanged=dict(attribute_input=module.params.get("next_hop_propagation")), + rtctrlSetRedistMultipath=dict(attribute_input=module.params.get("multipath")), + ) + for class_name, attribute in additional_child_classes.items(): + if attribute.get("attribute_input") is not None: + child_classes[class_name] = attribute + aci.construct_url( root_class=dict( aci_class="fvTenant", @@ -249,11 +414,63 @@ def main(): module_object=action_rule, target_filter={"name": action_rule}, ), + child_classes=list(child_classes.keys()), ) aci.get_existing() if state == "present": + child_configs = [] + for class_name, attribute in child_classes.items(): + attribute_input = attribute.get("attribute_input") + # This condition enables to user to keep its previous configurations if they are not passing anything in the payload. + if attribute_input is not None: + # This condition checks if the attribute input is a dict and checks if all of its values are None (stored as a boolean in only_none). + only_none = False + if isinstance(attribute_input, dict): + only_none = all(value is None for value in attribute_input.values()) + # This condition checks if the child object needs to be deleted depending on the type of the corresponding attribute input (bool, str, dict). + if (attribute_input == "" or attribute_input is False or only_none) and isinstance(aci.existing, list) and len(aci.existing) > 0: + for child in aci.existing[0].get("rtctrlAttrP", {}).get("children", {}): + if child.get(class_name): + child_configs.append( + { + class_name: dict( + attributes=dict(status="deleted"), + ), + } + ) + # This condition checks if the child object needs to be modified or created depending on the type of the corresponding attribute input. + elif attribute_input != "" or attribute_input is True or attribute_input != {}: + if class_name == "rtctrlSetComm" and isinstance(attribute_input, dict): + child_configs.append( + { + class_name: dict( + attributes=dict( + community=attribute_input.get("community"), + setCriteria=attribute_input.get("criteria"), + ), + ) + } + ) + elif class_name == "rtctrlSetDamp" and isinstance(attribute_input, dict): + child_configs.append( + { + class_name: dict( + attributes=dict( + halfLife=attribute_input.get("half_life"), + maxSuppressTime=attribute_input.get("max_suppress_time"), + reuse=attribute_input.get("reuse"), + suppress=attribute_input.get("suppress"), + ), + ) + } + ) + elif class_name in ["rtctrlSetNhUnchanged", "rtctrlSetRedistMultipath"]: + child_configs.append({class_name: dict(attributes=dict(descr=""))}) + else: + child_configs.append({class_name: dict(attributes={attribute.get("attribute_name"): attribute_input})}) + aci.payload( aci_class="rtctrlAttrP", class_config=dict( @@ -261,6 +478,7 @@ def main(): descr=description, nameAlias=name_alias, ), + child_configs=child_configs, ) aci.get_diff(aci_class="rtctrlAttrP") diff --git a/ansible_collections/cisco/aci/plugins/modules/aci_vmm_controller.py b/ansible_collections/cisco/aci/plugins/modules/aci_vmm_controller.py index f8a51529c..eac547dc1 100644 --- a/ansible_collections/cisco/aci/plugins/modules/aci_vmm_controller.py +++ b/ansible_collections/cisco/aci/plugins/modules/aci_vmm_controller.py @@ -3,6 +3,7 @@ # Copyright: (c) 2021, Manuel Widmer # Copyright: (c) 2021, Anvitha Jain (@anvitha-jain) +# Copyright: (c) 2023, Akini Ross (@akinross) # 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 @@ -88,6 +89,8 @@ seealso: link: https://developer.cisco.com/docs/apic-mim-ref/ author: - Manuel Widmer (@lumean) +- Anvitha Jain (@anvitha-jain) +- Akini Ross (@akinross) """ EXAMPLES = r""" @@ -132,7 +135,6 @@ EXAMPLES = r""" host: apic username: admin password: SomeSecretPassword - vm_provider: vmware state: query delegate_to: localhost register: query_result @@ -310,6 +312,8 @@ def main(): aci = ACIModule(module) + child_classes = ["vmmRsMgmtEPg", "vmmRsAcc"] + aci.construct_url( root_class=dict( aci_class="vmmProvP", @@ -327,11 +331,23 @@ def main(): aci_class="vmmCtrlrP", aci_rn="ctrlr-{0}".format(name), module_object=name, - target_filter={"name": "name"}, + target_filter={"name": name}, ), - child_classes=["vmmRsMgmtEPg", "vmmRsAcc"], + child_classes=child_classes, ) + # vmmProvP is not allowed to execute a query with rsp-subtree set in the filter_string + # due to complicated url construction logic which should be refactored creating a temporary fix inside module + # TODO refactor url construction logic if more occurences of rsp-subtree not supported problem appear + # check if the url is pointing towards the vmmProvP class and rsp-subtree is set in the filter_string + if aci.url.split("/")[-1].startswith("vmmp-") and "rsp-subtree" in aci.filter_string: + if name: + aci.url = "{0}/api/class/vmmCtrlrP.json".format(aci.base_url) + aci.filter_string = '?query-target-filter=eq(vmmCtrlrP.name,"{0}")&rsp-subtree=full&rsp-subtree-class={1}'.format(name, ",".join(child_classes)) + else: + aci.url = "{0}/api/mo/uni/vmmp-{1}.json".format(aci.base_url, VM_PROVIDER_MAPPING.get(vm_provider)) + aci.filter_string = "" + aci.get_existing() if state == "present": diff --git a/ansible_collections/cisco/aci/plugins/modules/aci_vmm_vswitch_policy.py b/ansible_collections/cisco/aci/plugins/modules/aci_vmm_vswitch_policy.py index 79d8182ff..90525e11c 100644 --- a/ansible_collections/cisco/aci/plugins/modules/aci_vmm_vswitch_policy.py +++ b/ansible_collections/cisco/aci/plugins/modules/aci_vmm_vswitch_policy.py @@ -14,7 +14,7 @@ ANSIBLE_METADATA = {"metadata_version": "1.1", "status": ["preview"], "supported DOCUMENTATION = r""" --- module: aci_vmm_vswitch_policy -short_description: Manage vSwitch policy for VMware virtual domains profiles (vmm:DomP) +short_description: Manage vSwitch policy for VMware virtual domains profiles (vmm:VSwitchPolicyCont) description: - Manage vSwitch policy for VMware VMM domains on Cisco ACI fabrics. options: @@ -139,7 +139,7 @@ extends_documentation_fragment: seealso: - module: cisco.aci.aci_domain - name: APIC Management Information Model reference - description: More information about the internal APIC classes B(vmm:DomP) + description: More information about the internal APIC classes B(vmm:VSwitchPolicyCont). link: https://developer.cisco.com/docs/apic-mim-ref/ author: - Manuel Widmer (@lumean) diff --git a/ansible_collections/cisco/aci/plugins/modules/aci_vrf_multicast.py b/ansible_collections/cisco/aci/plugins/modules/aci_vrf_multicast.py new file mode 100644 index 000000000..4d3809902 --- /dev/null +++ b/ansible_collections/cisco/aci/plugins/modules/aci_vrf_multicast.py @@ -0,0 +1,702 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- + +# Copyright: (c) 2023, Tim Cragg (@timcragg) +# Copyright: (c) 2023, Akini Ross (@akinross) +# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) + +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_vrf_multicast +short_description: Manage VRF Multicast objects (pim:CtxP) +description: +- Manage VRF Multicast objects on Cisco ACI fabrics. +- Creating I(state=present) enables Protocol Independent Multicast (PIM) on a VRF +- Deleting I(state=absent) disables Protocol Independent Multicast (PIM) on a VRF. +options: + tenant: + description: + - The name of an existing tenant. + type: str + aliases: [ tenant_name ] + vrf: + description: + - The name of an existing VRF. + type: str + aliases: [ vrf_name ] + pim_setting: + description: Configuration container for Protocol Independent Multicast (PIM) settings. + type: dict + suboptions: + mtu: + description: + - The MTU size supported for multicast. + - The APIC defaults to C(1500) when unset during creation. + type: int + control_state: + description: + - The action(s) to take when a loop is detected. + - Specify C([]) to remove the control state configuration. + type: list + elements: str + aliases: [ control, ctrl ] + choices: [ fast, strict ] + resource_policy: + description: Configuration container for Protocol Independent Multicast (PIM) resource policy. + type: dict + suboptions: + maximum_limit: + description: + - The Max Multicast Entries. + - The APIC defaults to C(unlimited) when unset during creation. + - Specify C(0) to reset to C(unlimited). + type: int + aliases: [ max ] + reserved_multicast_entries: + description: + - The Reserved Multicast Entries. + - The APIC defaults to C(undefined) when unset during creation. + - Required when C(reserved_route_map) is provided. + type: int + aliases: [ rsvd ] + reserved_route_map: + description: + - The DN of the Route Map. + - Specify C("") to remove the Route Map configuration. + - Required when C(reserved_multicast_entries) is provided. + type: str + aliases: [ route_map, route_map_dn ] + any_source_multicast: + description: Configuration container for Protocol Independent Multicast (PIM) Any Source Multicast (ASM) settings. + type: dict + aliases: [ asm, any_source ] + suboptions: + shared_range_route_map: + description: + - The DN of the Route Map. + - Specify C("") to remove the Route Map configuration. + type: str + aliases: [ shared_range_policy ] + source_group_expiry_route_map: + description: + - The DN of the Route Map. + - Specify C("") to remove the Route Map configuration. + type: str + aliases: [ sg_expiry_route_map ] + expiry: + description: + - The expiry time in seconds. + - The APIC defaults to C(default-timeout) when unset during creation. + - Specify C(0) to reset to C(default-timeout). + type: int + aliases: [ expiry_seconds ] + max_rate: + description: + - The maximum rate per second. + - The APIC defaults to C(65535) when unset during creation. + type: int + aliases: [ max_rate_per_second ] + source_ip: + description: + - The source IP address. + type: str + aliases: [ source, source_ip_address ] + source_specific_multicast: + description: Configuration container for Protocol Independent Multicast (PIM) Source Specific Multicast (SSM) settings. + type: dict + aliases: [ ssm, specific_source ] + suboptions: + group_range_route_map: + description: + - The DN of the Route Map. + - Specify C("") to remove the Route Map configuration. + type: str + aliases: [ group_range_policy ] + bootstrap_router: + description: Configuration container for Protocol Independent Multicast (PIM) Bootstrap Router (BSR) settings. + type: dict + aliases: [ bsr, bootstrap ] + suboptions: + bsr_filter: + description: + - The DN of the Route Map. + - Specify C("") to remove the Route Map configuration. + type: str + aliases: [ filter, route_map, route_map_dn ] + rp_updates: + description: + - The control state of the Bootstrap Router (BSR) policy. + - Specify C([]) to remove the control state configuration. + type: list + elements: str + aliases: [ control, ctrl ] + choices: [ forward, listen ] + auto_rp: + description: Configuration container for Protocol Independent Multicast (PIM) Auto-Rendezvous Point (Auto-RP) settings. + type: dict + aliases: [ auto ] + suboptions: + ma_filter: + description: + - The DN of the Route Map. + - Specify C("") to remove the Route Map configuration. + type: str + aliases: [ filter, route_map, route_map_dn ] + rp_updates: + description: + - The control state of the Auto-Rendezvous Point (Auto-RP) policy. + - Specify C([]) to remove the control state configuration. + type: list + elements: str + aliases: [ control, ctrl ] + choices: [ forward, listen ] + state: + description: + - Use C(present) or C(absent) for adding or removing. + - Use C(query) for listing an object or multiple objects. + type: str + choices: [ absent, present, query ] + default: present +extends_documentation_fragment: +- cisco.aci.aci +- cisco.aci.annotation +- cisco.aci.owner + +notes: +- The I(tenant) and I(vrf) must exist before using this module in your playbook. + The M(cisco.aci.aci_tenant) and M(cisco.aci.aci_vrf) modules can be used for this. +seealso: +- name: APIC Management Information Model reference + description: More information about the internal APIC class B(pim:CtxP). + link: https://developer.cisco.com/docs/apic-mim-ref/ +author: +- Tim Cragg (@timcragg) +- Akini Ross (@akinross) +""" + +EXAMPLES = r""" +- name: Enable Multicast on a VRF + cisco.aci.aci_vrf_multicast: + host: apic + username: admin + password: SomeSecretePassword + tenant: ansible_tenant + vrf: ansible_vrf + state: present + delegate_to: localhost + +- name: Change Multicast PIM Settings on a VRF + cisco.aci.aci_vrf_multicast: + host: apic + username: admin + password: SomeSecretePassword + tenant: ansible_tenant + vrf: ansible_vrf + pim_setting: + mtu: 2000 + control_state: [ fast, strict ] + state: present + delegate_to: localhost + +- name: Change Multicast Resource Policy on a VRF + cisco.aci.aci_vrf_multicast: + host: apic + username: admin + password: SomeSecretePassword + tenant: ansible_tenant + vrf: ansible_vrf + resource_policy: + maximum_limit: 100 + reserved_multicast_entries: 20 + reserved_route_map: uni/tn-ansible_test/rtmap-ansible_test + state: present + delegate_to: localhost + +- name: Remove Route-Map from Multicast Resource Policy on a VRF + cisco.aci.aci_vrf_multicast: + host: apic + username: admin + password: SomeSecretePassword + tenant: ansible_tenant + vrf: ansible_vrf + resource_policy: + reserved_route_map: "" + state: present + delegate_to: localhost + +- name: Change Multicast Any Source Multicast (ASM) Settings on a VRF + cisco.aci.aci_vrf_multicast: + host: apic + username: admin + password: SomeSecretePassword + tenant: ansible_tenant + vrf: ansible_vrf + any_source_multicast: + shared_range_route_map: uni/tn-ansible_test/rtmap-ansible_test + source_group_expiry_route_map: uni/tn-ansible_test/rtmap-ansible_test + expiry: 500 + max_rate: 64000 + source_ip: 1.1.1.1 + state: present + delegate_to: localhost + +- name: Change Multicast Source Specific Multicast (SSM) Settings on a VRF + cisco.aci.aci_vrf_multicast: + host: apic + username: admin + password: SomeSecretePassword + tenant: ansible_tenant + vrf: ansible_vrf + source_specific_multicast: + group_range_route_map: uni/tn-ansible_test/rtmap-ansible_test + state: present + delegate_to: localhost + +- name: Change Multicast Bootstrap Router (BSR) Settings on a VRF + cisco.aci.aci_vrf_multicast: + host: apic + username: admin + password: SomeSecretePassword + tenant: ansible_tenant + vrf: ansible_vrf + bootstrap_router: + bsr_filter: uni/tn-ansible_test/rtmap-ansible_test + rp_updates: [ forward, listen ] + state: present + delegate_to: localhost + +- name: Change Multicast Auto-Rendezvous Point (Auto-RP) Settings on a VRF + cisco.aci.aci_vrf_multicast: + host: apic + username: admin + password: SomeSecretePassword + tenant: ansible_tenant + vrf: ansible_vrf + auto_rp: + ma_filter: uni/tn-ansible_test/rtmap-ansible_test + rp_updates: [ forward, listen ] + state: present + delegate_to: localhost + +- name: Disable Multicast on a VRF + cisco.aci.aci_vrf_multicast: + host: apic + username: admin + password: SomeSecretePassword + tenant: ansible_tenant + vrf: ansible_vrf + state: absent + delegate_to: localhost + +- name: Query Multicast Settings for a VRF + cisco.aci.aci_vrf_multicast: + host: apic + username: admin + password: SomeSecretePassword + tenant: ansible_tenant + vrf: ansible_vrf + state: query + delegate_to: localhost + register: query_result + +- name: Query Multicast Settings for all VRFs + cisco.aci.aci_vrf_multicast: + host: apic + username: admin + password: SomeSecretePassword + state: query + delegate_to: localhost + register: query_result +""" + +RETURN = r""" + current: + description: The existing configuration from the APIC after the module has finished + returned: success + type: list + sample: + [ + { + "fvTenant": { + "attributes": { + "descr": "Production environment", + "dn": "uni/tn-production", + "name": "production", + "nameAlias": "", + "ownerKey": "", + "ownerTag": "" + } + } + } + ] + error: + description: The error information as returned from the APIC + returned: failure + type: dict + sample: + { + "code": "122", + "text": "unknown managed object class foo" + } + raw: + description: The raw output returned by the APIC REST API (xml or json) + returned: parse error + type: str + sample: '' + sent: + description: The actual/minimal configuration pushed to the APIC + returned: info + type: list + sample: + { + "fvTenant": { + "attributes": { + "descr": "Production environment" + } + } + } + previous: + description: The original configuration from the APIC before the module has started + returned: info + type: list + sample: + [ + { + "fvTenant": { + "attributes": { + "descr": "Production", + "dn": "uni/tn-production", + "name": "production", + "nameAlias": "", + "ownerKey": "", + "ownerTag": "" + } + } + } + ] + proposed: + description: The assembled configuration from the user-provided parameters + returned: info + type: dict + sample: + { + "fvTenant": { + "attributes": { + "descr": "Production environment", + "name": "production" + } + } + } + filter_string: + description: The filter string used for the request + returned: failure or debug + type: str + sample: ?rsp-prop-include=config-only + method: + description: The HTTP method used for the request to the APIC + returned: failure or debug + type: str + sample: POST + response: + description: The HTTP response from the APIC + returned: failure or debug + type: str + sample: OK (30 bytes) + status: + description: The HTTP status from the APIC + returned: failure or debug + type: int + sample: 200 + url: + description: The HTTP url used for the request to the APIC + returned: failure or debug + type: str + sample: https://10.11.12.13/api/mo/uni/tn-production.json + """ + +from ansible.module_utils.basic import AnsibleModule +from ansible_collections.cisco.aci.plugins.module_utils.aci import ACIModule, aci_argument_spec, aci_annotation_spec, aci_owner_spec +from ansible_collections.cisco.aci.plugins.module_utils.constants import PIM_SETTING_CONTROL_STATE_MAPPING + + +def main(): + argument_spec = aci_argument_spec() + argument_spec.update(aci_annotation_spec()) + argument_spec.update(aci_owner_spec()) + argument_spec.update( + tenant=dict(type="str", aliases=["tenant_name"]), + vrf=dict(type="str", aliases=["vrf_name"]), + pim_setting=dict( + type="dict", + options=dict( + mtu=dict(type="int"), + control_state=dict(type="list", elements="str", choices=["fast", "strict"], aliases=["control", "ctrl"]), + ), + ), + resource_policy=dict( + type="dict", + options=dict( + maximum_limit=dict(type="int", aliases=["max"]), + reserved_multicast_entries=dict(type="int", aliases=["rsvd"]), + reserved_route_map=dict(type="str", aliases=["route_map", "route_map_dn"]), + ), + ), + any_source_multicast=dict( + type="dict", + options=dict( + shared_range_route_map=dict(type="str", aliases=["shared_range_policy"]), + source_group_expiry_route_map=dict(type="str", aliases=["sg_expiry_route_map"]), + expiry=(dict(type="int", aliases=["expiry_seconds"])), + max_rate=(dict(type="int", aliases=["max_rate_per_second"])), + source_ip=(dict(type="str", aliases=["source", "source_ip_address"])), + ), + aliases=["asm", "any_source"], + ), + source_specific_multicast=dict( + type="dict", + options=dict( + group_range_route_map=dict(type="str", aliases=["group_range_policy"]), + ), + aliases=["ssm", "specific_source"], + ), + bootstrap_router=dict( + type="dict", + options=dict( + bsr_filter=dict(type="str", aliases=["filter", "route_map", "route_map_dn"]), + rp_updates=dict(type="list", elements="str", choices=["forward", "listen"], aliases=["control", "ctrl"]), + ), + aliases=["bsr", "bootstrap"], + ), + auto_rp=dict( + type="dict", + options=dict( + ma_filter=dict(type="str", aliases=["filter", "route_map", "route_map_dn"]), + rp_updates=dict(type="list", elements="str", choices=["forward", "listen"], aliases=["control", "ctrl"]), + ), + aliases=["auto"], + ), + state=dict(type="str", default="present", choices=["absent", "present", "query"]), + ) + + module = AnsibleModule( + argument_spec=argument_spec, + supports_check_mode=True, + required_if=[ + ["state", "absent", ["tenant", "vrf"]], + ["state", "present", ["tenant", "vrf"]], + ], + ) + + aci = ACIModule(module) + + tenant = module.params.get("tenant") + vrf = module.params.get("vrf") + pim_setting = module.params.get("pim_setting") + resource_policy = module.params.get("resource_policy") + any_source_multicast = module.params.get("any_source_multicast") + source_specific_multicast = module.params.get("source_specific_multicast") + bootstrap_router = module.params.get("bootstrap_router") + auto_rp = module.params.get("auto_rp") + state = module.params.get("state") + + if resource_policy and resource_policy.get("reserved_multicast_entries") and resource_policy.get("reserved_route_map") is None: + aci.fail_json(msg="parameters are mutually exclusive: reserved_route_map|reserved_multicast_entries") + elif resource_policy and resource_policy.get("reserved_route_map") and not resource_policy.get("reserved_multicast_entries"): + aci.fail_json(msg="C(reserved_multicast_entries) must be provided and greater than 0 when C(reserved_route_map) is provided") + + aci.construct_url( + root_class=dict( + aci_class="fvTenant", + aci_rn="tn-{0}".format(tenant), + module_object=tenant, + target_filter={"name": tenant}, + ), + subclass_1=dict( + aci_class="fvCtx", + aci_rn="ctx-{0}".format(vrf), + module_object=vrf, + target_filter={"name": vrf}, + ), + subclass_2=dict( + aci_class="pimCtxP", + aci_rn="pimctxp", + target_filter={"name": ""}, + ), + child_classes=["pimResPol", "pimASMPatPol", "pimSSMPatPol", "pimAutoRPPol", "pimBSRPPol"], + ) + + aci.get_existing() + + if state == "present": + existing_config = aci.existing[0] if aci.existing else {} + child_configs = [] + + resource_policy_config = dict(pimResPol=dict(attributes=dict(name=""), children=[])) + if resource_policy: + max = "unlimited" if resource_policy.get("maximum_limit") == 0 else resource_policy.get("maximum_limit") + if max is not None: + resource_policy_config["pimResPol"]["attributes"]["max"] = str(max) + + reserved_route_map = resource_policy.get("reserved_route_map") + if reserved_route_map is not None: + existing_rrm = get_child_from_existing_config(existing_config, ["pimCtxP", "pimResPol", "rtdmcRsFilterToRtMapPol"]) + rsvd = resource_policy.get("reserved_multicast_entries") + + if (existing_rrm or reserved_route_map != "") and rsvd: + resource_policy_config["pimResPol"]["attributes"]["rsvd"] = str(rsvd) + elif existing_rrm and reserved_route_map == "": + resource_policy_config["pimResPol"]["attributes"]["rsvd"] = "undefined" + + set_route_map_config( + existing_config, + resource_policy_config["pimResPol"]["children"], + ["pimCtxP", "pimResPol", "rtdmcRsFilterToRtMapPol"], + reserved_route_map, + ) + + child_configs.append(resource_policy_config) + + any_source_multicast_config = dict( + pimASMPatPol=dict( + attributes=dict(name=""), + children=[ + dict(pimSharedRangePol=dict(attributes=dict(name=""), children=[])), + dict(pimSGRangeExpPol=dict(attributes=dict(name=""), children=[])), + dict(pimRegTrPol=dict(attributes=dict(name=""), children=[])), + ], + ) + ) + if any_source_multicast: + if any_source_multicast.get("shared_range_route_map") is not None: + set_route_map_config( + existing_config, + any_source_multicast_config["pimASMPatPol"]["children"][0]["pimSharedRangePol"]["children"], + ["pimCtxP", "pimASMPatPol", "pimSharedRangePol", "rtdmcRsFilterToRtMapPol"], + any_source_multicast.get("shared_range_route_map"), + ) + + if any_source_multicast.get("source_group_expiry_route_map") is not None: + set_route_map_config( + existing_config, + any_source_multicast_config["pimASMPatPol"]["children"][1]["pimSGRangeExpPol"]["children"], + ["pimCtxP", "pimASMPatPol", "pimSGRangeExpPol", "rtdmcRsFilterToRtMapPol"], + any_source_multicast.get("source_group_expiry_route_map"), + ) + + expiry = any_source_multicast.get("expiry") + if expiry is not None: + sg_expiry_config = "default-timeout" if any_source_multicast.get("expiry") == 0 else any_source_multicast.get("expiry") + any_source_multicast_config["pimASMPatPol"]["children"][1]["pimSGRangeExpPol"]["attributes"]["sgExpItvl"] = str(sg_expiry_config) + + if any_source_multicast.get("max_rate") is not None: + any_source_multicast_config["pimASMPatPol"]["children"][2]["pimRegTrPol"]["attributes"]["maxRate"] = str(any_source_multicast.get("max_rate")) + + if any_source_multicast.get("source_ip") is not None: + any_source_multicast_config["pimASMPatPol"]["children"][2]["pimRegTrPol"]["attributes"]["srcIp"] = any_source_multicast.get("source_ip") + + child_configs.append(any_source_multicast_config) + + source_specific_multicast_config = dict( + pimSSMPatPol=dict( + attributes=dict(name=""), + children=[ + dict(pimSSMRangePol=dict(attributes=dict(name=""), children=[])), + ], + ) + ) + if source_specific_multicast and source_specific_multicast.get("group_range_route_map") is not None: + set_route_map_config( + existing_config, + source_specific_multicast_config["pimSSMPatPol"]["children"][0]["pimSSMRangePol"]["children"], + ["pimCtxP", "pimSSMPatPol", "pimSSMRangePol", "rtdmcRsFilterToRtMapPol"], + source_specific_multicast.get("group_range_route_map"), + ) + + child_configs.append(source_specific_multicast_config) + + if bootstrap_router: + bsr_config = dict(pimBSRPPol=dict(attributes=dict(name=""), children=[dict(pimBSRFilterPol=dict(attributes=dict(name=""), children=[]))])) + if bootstrap_router.get("bsr_filter") is not None: + set_route_map_config( + existing_config, + bsr_config["pimBSRPPol"]["children"][0]["pimBSRFilterPol"]["children"], + ["pimCtxP", "pimBSRPPol", "pimBSRFilterPol", "rtdmcRsFilterToRtMapPol"], + bootstrap_router.get("bsr_filter"), + ) + + rp_updates = bootstrap_router.get("rp_updates") + if rp_updates is not None: + bsr_config["pimBSRPPol"]["attributes"]["ctrl"] = ",".join(sorted(rp_updates)) + + child_configs.append(bsr_config) + + if auto_rp: + auto_rp_config = dict(pimAutoRPPol=dict(attributes=dict(name=""), children=[dict(pimMAFilterPol=dict(attributes=dict(name=""), children=[]))])) + + if auto_rp.get("ma_filter") is not None: + set_route_map_config( + existing_config, + auto_rp_config["pimAutoRPPol"]["children"][0]["pimMAFilterPol"]["children"], + ["pimCtxP", "pimAutoRPPol", "pimMAFilterPol", "rtdmcRsFilterToRtMapPol"], + auto_rp.get("ma_filter"), + ) + + rp_updates = auto_rp.get("rp_updates") + if rp_updates is not None: + auto_rp_config["pimAutoRPPol"]["attributes"]["ctrl"] = ",".join(sorted(rp_updates)) + + child_configs.append(auto_rp_config) + + mtu = None + control_state = None + if pim_setting: + mtu = pim_setting.get("mtu") + control_state = ( + ",".join(sorted([PIM_SETTING_CONTROL_STATE_MAPPING.get(v) for v in pim_setting.get("control_state")])) + if pim_setting.get("control_state") is not None + else None + ) + + aci.payload( + aci_class="pimCtxP", + class_config=dict(mtu=mtu, ctrl=control_state), + child_configs=child_configs, + ) + + aci.get_diff(aci_class="pimCtxP") + + aci.post_config() + + elif state == "absent": + aci.delete_config() + + aci.exit_json() + + +def get_child_from_existing_config(config, class_names): + parent = class_names[0] + class_names.remove(parent) + + for child in config.get(parent, {}).get("children", []): + if len(class_names) == 1 and class_names[0] in child.keys(): + return child + elif child.get(class_names[0], {}).get("children"): + return get_child_from_existing_config(child, class_names) + + +def set_route_map_config(existing_config, new_config, class_names, route_map): + existing_route_map = get_child_from_existing_config(existing_config, class_names) + if route_map == "" and existing_route_map: + new_config.append(dict(rtdmcRsFilterToRtMapPol=dict(attributes=dict(tDn=route_map, status="deleted")))) + elif route_map: + new_config.append(dict(rtdmcRsFilterToRtMapPol=dict(attributes=dict(tDn=route_map)))) + + +if __name__ == "__main__": + main() diff --git a/ansible_collections/cisco/aci/plugins/modules/aci_vzany_to_contract.py b/ansible_collections/cisco/aci/plugins/modules/aci_vzany_to_contract.py index f2632307c..411f63936 100644 --- a/ansible_collections/cisco/aci/plugins/modules/aci_vzany_to_contract.py +++ b/ansible_collections/cisco/aci/plugins/modules/aci_vzany_to_contract.py @@ -12,7 +12,7 @@ ANSIBLE_METADATA = {"metadata_version": "1.1", "status": ["preview"], "supported DOCUMENTATION = r""" --- module: aci_vzany_to_contract -short_description: Attach contracts to vzAny (vz:RsAnyToProv, vz:RsAnyToCons, vz:RsAnyToConsIf) +short_description: Attach contracts to vzAny (vz:RsAnyToProv, vz:RsAnyToCons, and vz:RsAnyToConsIf) description: - Bind contracts to vzAny on Cisco ACI fabrics. options: @@ -54,7 +54,7 @@ seealso: - module: cisco.aci.aci_vrf - 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). + description: More information about the internal APIC classes B(vz:RsAnyToProv), B(vz:RsAnyToCons), and B(vz:RsAnyToConsIf). link: https://developer.cisco.com/docs/apic-mim-ref/ author: - Marcel Zehnder (@maercu) diff --git a/ansible_collections/cisco/aci/tests/integration/inventory.networking b/ansible_collections/cisco/aci/tests/integration/inventory.networking index 357f58758..9e17071d0 100644 --- a/ansible_collections/cisco/aci/tests/integration/inventory.networking +++ b/ansible_collections/cisco/aci/tests/integration/inventory.networking @@ -1,13 +1,13 @@ [aci] cn-dmz-apic-m1-02-v42 ansible_host=173.36.219.68 aci_hostname=173.36.219.68 cn-dmz-apic-m1-03-v52 ansible_host=173.36.219.69 aci_hostname=173.36.219.69 -cn-dmz-apic-m1-04-v60 ansible_host=173.36.219.70 aci_hostname=173.36.219.70 -cn-dmz-apic-m1-07-v32 ansible_host=173.36.219.73 aci_hostname=173.36.219.73 +cn-dmz-apic-m1-04-v602h ansible_host=173.36.219.70 aci_hostname=173.36.219.70 aws_cloud ansible_host=52.52.20.121 aci_hostname=52.52.20.121 cloud_type=aws region=us-east-1 region_2=us-west-1 availability_zone=us-west-1a -azure_cloud ansible_host=20.245.236.136 aci_hostname=20.245.236.136 cloud_type=azure region=westus region_2=westus2 vnet_gateway=true +azure_cloud ansible_host=20.245.236.136 aci_hostname=20.245.236.136 cloud_type=azure region=westus region_2=westus2 vnet_gateway=true az_region=westus2 [aci:vars] aci_username=ansible_github_ci +aci_remote_username="apic:test\\r_ansible_github_ci" aci_password="sJ94G92#8dq2hx*K4qh" ansible_network_os=cisco.aci.aci ansible_connection=local diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_aaa_certificate_authority/aliases b/ansible_collections/cisco/aci/tests/integration/targets/aci_aaa_certificate_authority/aliases new file mode 100644 index 000000000..209b793f9 --- /dev/null +++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_aaa_certificate_authority/aliases @@ -0,0 +1,2 @@ +# No ACI simulator yet, so not enabled +# unsupported diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_aaa_certificate_authority/pki/admin.crt b/ansible_collections/cisco/aci/tests/integration/targets/aci_aaa_certificate_authority/pki/admin.crt new file mode 100644 index 000000000..cfac5531e --- /dev/null +++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_aaa_certificate_authority/pki/admin.crt @@ -0,0 +1,14 @@ +-----BEGIN CERTIFICATE----- +MIICODCCAaGgAwIBAgIJAIt8XMntue0VMA0GCSqGSIb3DQEBCwUAMDQxDjAMBgNV +BAMMBUFkbWluMRUwEwYDVQQKDAxZb3VyIENvbXBhbnkxCzAJBgNVBAYTAlVTMCAX +DTE4MDEwOTAwNTk0NFoYDzIxMTcxMjE2MDA1OTQ0WjA0MQ4wDAYDVQQDDAVBZG1p +bjEVMBMGA1UECgwMWW91ciBDb21wYW55MQswCQYDVQQGEwJVUzCBnzANBgkqhkiG +9w0BAQEFAAOBjQAwgYkCgYEAohG/7axtt7CbSaMP7r+2mhTKbNgh0Ww36C7Ta14i +v+VmLyKkQHnXinKGhp6uy3Nug+15a+eIu7CrgpBVMQeCiWfsnwRocKcQJWIYDrWl +XHxGQn31yYKR6mylE7Dcj3rMFybnyhezr5D8GcP85YRPmwG9H2hO/0Y1FUnWu9Iw +AQkCAwEAAaNQME4wHQYDVR0OBBYEFD0jLXfpkrU/ChzRvfruRs/fy1VXMB8GA1Ud +IwQYMBaAFD0jLXfpkrU/ChzRvfruRs/fy1VXMAwGA1UdEwQFMAMBAf8wDQYJKoZI +hvcNAQELBQADgYEAOmvre+5tgZ0+F3DgsfxNQqLTrGiBgGCIymPkP/cBXXkNuJyl +3ac7tArHQc7WEA4U2R2rZbEq8FC3UJJm4nUVtCPvEh3G9OhN2xwYev79yt6pIn/l +KU0Td2OpVyo0eLqjoX5u2G90IBWzhyjFbo+CcKMrSVKj1YOdG0E3OuiJf00= +-----END CERTIFICATE----- diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_aaa_certificate_authority/tasks/main.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_aaa_certificate_authority/tasks/main.yml new file mode 100644 index 000000000..15cdeeb60 --- /dev/null +++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_aaa_certificate_authority/tasks/main.yml @@ -0,0 +1,305 @@ +# Test code for the ACI modules +# Copyright: (c) 2024, Akini Ross (@akinross) +# +# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) + +- name: Test that we have an ACI APIC host, ACI username and ACI password + ansible.builtin.fail: + msg: 'Please define the following variables: aci_hostname, aci_username and aci_password.' + when: aci_hostname is not defined or aci_username is not defined or aci_password is not defined + +- name: Set vars + ansible.builtin.set_fact: + aci_info: &aci_info + host: "{{ aci_hostname }}" + username: "{{ aci_username }}" + password: "{{ aci_password }}" + validate_certs: '{{ aci_validate_certs | default(false) }}' + use_ssl: '{{ aci_use_ssl | default(true) }}' + use_proxy: '{{ aci_use_proxy | default(true) }}' + output_level: '{{ aci_use_proxy | default("debug") }}' + +- name: Verify Cloud and Non-Cloud Sites in use. + ansible.builtin.include_tasks: ../../../../../../integration/targets/aci_cloud_provider/tasks/main.yml + +# CLEAN ENVIRONMENT +- name: Clean certificate_authority_1 + cisco.aci.aci_aaa_certificate_authority: &certificate_authority_1_absent + <<: *aci_info + name: certificate_authority_1 + state: absent + +- name: Clean certificate_authority_2 + cisco.aci.aci_aaa_certificate_authority: &certificate_authority_2_absent + <<: *aci_info + name: certificate_authority_2 + state: absent + register: result + until: result is not failed + delay: 2 + retries: 4 + +# CREATE +- name: Create a certificate authority (check_mode) + cisco.aci.aci_aaa_certificate_authority: &certificate_authority_1_present + <<: *certificate_authority_1_absent + certificate_chain: "{{ lookup('file', 'pki/admin.crt') }}" + state: present + check_mode: true + register: cm_create_certificate_authority_1 + +- name: Create a certificate authority + cisco.aci.aci_aaa_certificate_authority: + <<: *certificate_authority_1_present + register: nm_create_certificate_authority_1 + until: nm_create_certificate_authority_1 is not failed + delay: 2 + retries: 4 + +- name: Create a certificate authority again + cisco.aci.aci_aaa_certificate_authority: + <<: *certificate_authority_1_present + register: nm_create_certificate_authority_1_again + until: nm_create_certificate_authority_1_again is not failed + delay: 2 + retries: 4 + +- name: Assertions for creating a certificate authority + ansible.builtin.assert: + that: + - cm_create_certificate_authority_1 is changed + - cm_create_certificate_authority_1.previous == [] + - cm_create_certificate_authority_1.current == [] + - cm_create_certificate_authority_1.proposed.pkiTP.attributes.name == "certificate_authority_1" + - nm_create_certificate_authority_1 is changed + - nm_create_certificate_authority_1.previous == [] + - nm_create_certificate_authority_1.current.0.pkiTP.attributes.name == "certificate_authority_1" + - nm_create_certificate_authority_1.current.0.pkiTP.attributes.descr == "" + - nm_create_certificate_authority_1_again is not changed + - nm_create_certificate_authority_1_again.previous.0.pkiTP.attributes.name == "certificate_authority_1" + - nm_create_certificate_authority_1_again.previous.0.pkiTP.attributes.descr == "" + - nm_create_certificate_authority_1_again.current.0.pkiTP.attributes.name == "certificate_authority_1" + - nm_create_certificate_authority_1_again.current.0.pkiTP.attributes.descr == "" + +# UPDATE +- name: Update an existing certificate authority + cisco.aci.aci_aaa_certificate_authority: + <<: *certificate_authority_1_present + description: "This is a changed description." + register: nm_update_certificate_authority_1 + until: nm_update_certificate_authority_1 is not failed + delay: 2 + retries: 4 + +- name: Assertions for updating a certificate authority + ansible.builtin.assert: + that: + - nm_update_certificate_authority_1 is changed + - nm_update_certificate_authority_1.previous.0.pkiTP.attributes.name == "certificate_authority_1" + - nm_update_certificate_authority_1.previous.0.pkiTP.attributes.descr == "" + - nm_update_certificate_authority_1.current.0.pkiTP.attributes.name == "certificate_authority_1" + - nm_update_certificate_authority_1.current.0.pkiTP.attributes.descr == "This is a changed description." + +- name: Execute tasks only for cloud sites + when: query_cloud.current != [] # This condition will execute only non-cloud sites + block: # block specifies execution of tasks within, based on conditions + - name: Delete certificate authority for cloud site tenant + cisco.aci.aci_aaa_certificate_authority: &certificate_authority_cloud_absent + <<: *certificate_authority_1_present + cloud_tenant: cloud_tenant + name: certificate_authority_cloud + state: absent + register: nm_delete_certificate_authority_1_cloud + until: nm_delete_certificate_authority_1_cloud is not failed + delay: 2 + retries: 4 + + - name: Create tenant for cloud site + cisco.aci.aci_tenant: &cloud_tenant + <<: *aci_info + name: cloud_tenant + register: cloud_tenant + until: cloud_tenant is not failed + delay: 2 + retries: 4 + + - name: Create certificate authority for cloud site tenant (check_mode) + cisco.aci.aci_aaa_certificate_authority: &certificate_authority_cloud_present + <<: *certificate_authority_cloud_absent + state: present + check_mode: true + register: cm_create_certificate_authority_1_cloud + until: cm_create_certificate_authority_1_cloud is not failed + delay: 2 + retries: 4 + + - name: Create certificate authority for cloud site tenant + cisco.aci.aci_aaa_certificate_authority: + <<: *certificate_authority_cloud_present + register: nm_create_certificate_authority_1_cloud + until: nm_create_certificate_authority_1_cloud is not failed + delay: 2 + retries: 4 + + - name: Create certificate authority for cloud site tenant again + cisco.aci.aci_aaa_certificate_authority: + <<: *certificate_authority_cloud_present + register: nm_create_certificate_authority_1_cloud_again + until: nm_create_certificate_authority_1_cloud is not failed + delay: 2 + retries: 4 + + - name: Verify certificate authority is created in cloud tenant + ansible.builtin.assert: + that: + - cm_create_certificate_authority_1_cloud is changed + - cm_create_certificate_authority_1_cloud.previous == [] + - cm_create_certificate_authority_1_cloud.current == [] + - cm_create_certificate_authority_1_cloud.proposed.pkiTP.attributes.name == "certificate_authority_cloud" + - '"tn-cloud_tenant/certstore/tp-certificate_authority_cloud" in cm_create_certificate_authority_1_cloud.url' + - nm_create_certificate_authority_1_cloud is changed + - nm_create_certificate_authority_1_cloud.previous == [] + - nm_create_certificate_authority_1_cloud.current.0.pkiTP.attributes.name == "certificate_authority_cloud" + - nm_create_certificate_authority_1_cloud.current.0.pkiTP.attributes.descr == "" + - '"tn-cloud_tenant/certstore/tp-certificate_authority_cloud" in nm_create_certificate_authority_1_cloud.url' + - nm_create_certificate_authority_1_cloud_again is not changed + - nm_create_certificate_authority_1_cloud_again.previous.0.pkiTP.attributes.name == "certificate_authority_cloud" + - nm_create_certificate_authority_1_cloud_again.previous.0.pkiTP.attributes.descr == "" + - nm_create_certificate_authority_1_cloud_again.current.0.pkiTP.attributes.name == "certificate_authority_cloud" + - nm_create_certificate_authority_1_cloud_again.current.0.pkiTP.attributes.descr == "" + - '"tn-cloud_tenant/certstore/tp-certificate_authority_cloud" in nm_create_certificate_authority_1_cloud_again.url' + + - name: Delete certificate authority for cloud site tenant (check_mode) + cisco.aci.aci_aaa_certificate_authority: + <<: *certificate_authority_cloud_absent + check_mode: true + register: cm_delete_certificate_authority_1_cloud + until: cm_delete_certificate_authority_1_cloud is not failed + delay: 2 + retries: 4 + + - name: Delete certificate authority for cloud site tenant + cisco.aci.aci_aaa_certificate_authority: + <<: *certificate_authority_cloud_absent + register: nm_delete_certificate_authority_1_cloud + until: nm_delete_certificate_authority_1_cloud is not failed + delay: 2 + retries: 4 + + - name: Delete certificate authority for cloud site tenant again + cisco.aci.aci_aaa_certificate_authority: + <<: *certificate_authority_cloud_absent + register: nm_delete_certificate_authority_1_cloud_again + until: nm_delete_certificate_authority_1_cloud_again is not failed + delay: 2 + retries: 4 + + - name: Verify certificate authority is deleted in cloud tenant + ansible.builtin.assert: + that: + - cm_delete_certificate_authority_1_cloud is changed + - cm_delete_certificate_authority_1_cloud.proposed == {} + - cm_delete_certificate_authority_1_cloud.previous.0.pkiTP.attributes.name == "certificate_authority_cloud" + - cm_delete_certificate_authority_1_cloud.previous.0.pkiTP.attributes.descr == "" + - cm_delete_certificate_authority_1_cloud.current.0.pkiTP.attributes.name == "certificate_authority_cloud" + - cm_delete_certificate_authority_1_cloud.current.0.pkiTP.attributes.descr == "" + - '"tn-cloud_tenant/certstore/tp-certificate_authority_cloud" in cm_delete_certificate_authority_1_cloud.url' + - nm_delete_certificate_authority_1_cloud is changed + - nm_delete_certificate_authority_1_cloud.previous.0.pkiTP.attributes.name == "certificate_authority_cloud" + - nm_delete_certificate_authority_1_cloud.previous.0.pkiTP.attributes.descr == "" + - nm_delete_certificate_authority_1_cloud.current == [] + - '"tn-cloud_tenant/certstore/tp-certificate_authority_cloud" in nm_delete_certificate_authority_1_cloud.url' + - nm_delete_certificate_authority_1_cloud_again is not changed + - nm_delete_certificate_authority_1_cloud_again.previous == [] + - nm_delete_certificate_authority_1_cloud_again.current == [] + - '"tn-cloud_tenant/certstore/tp-certificate_authority_cloud" in nm_delete_certificate_authority_1_cloud_again.url' + + - name: Delete tenant for cloud site + cisco.aci.aci_tenant: + <<: *cloud_tenant + state: absent + register: cloud_tenant + until: cloud_tenant is not failed + delay: 2 + retries: 4 + +# QUERY +- name: Create another certificate authority + cisco.aci.aci_aaa_certificate_authority: + <<: *certificate_authority_2_absent + certificate_chain: "{{ lookup('file', 'pki/admin.crt') }}" + state: present + register: nm_create_certificate_authority_2 + until: nm_create_certificate_authority_2 is not failed + delay: 2 + retries: 4 + +- name: Query a certificate authority + cisco.aci.aci_aaa_certificate_authority: + <<: *certificate_authority_1_present + state: query + register: query_certificate_authority_1 + until: query_certificate_authority_1 is not failed + delay: 2 + retries: 4 + +- name: Query all fabric management access policies + cisco.aci.aci_aaa_certificate_authority: + <<: *aci_info + state: query + register: query_all + +- name: Assertions for querying fabric management access policies + ansible.builtin.assert: + that: + - query_certificate_authority_1 is not changed + - query_certificate_authority_1.current.0.pkiTP.attributes.name == "certificate_authority_1" + - query_certificate_authority_1.current.0.pkiTP.attributes.descr == "This is a changed description." + - query_certificate_authority_1.current | length == 1 + - query_all is not changed + - query_all.current | length >= 2 + +# DELETE +- name: Delete a certificate authority (check_mode) + cisco.aci.aci_aaa_certificate_authority: + <<: *certificate_authority_1_absent + check_mode: true + register: cm_delete_certificate_authority_1 + +- name: Delete a certificate authority + cisco.aci.aci_aaa_certificate_authority: + <<: *certificate_authority_1_absent + register: nm_delete_certificate_authority_1 + until: nm_delete_certificate_authority_1 is not failed + delay: 2 + retries: 4 + +- name: Delete a certificate authority again + cisco.aci.aci_aaa_certificate_authority: + <<: *certificate_authority_1_absent + register: nm_delete_certificate_authority_1_again + until: nm_delete_certificate_authority_1_again is not failed + delay: 2 + retries: 4 + +- name: Assertions for deleting a certificate authority + ansible.builtin.assert: + that: + - cm_delete_certificate_authority_1 is changed + - cm_delete_certificate_authority_1.proposed == {} + - cm_delete_certificate_authority_1.previous.0.pkiTP.attributes.name == "certificate_authority_1" + - cm_delete_certificate_authority_1.previous.0.pkiTP.attributes.descr == "This is a changed description." + - cm_delete_certificate_authority_1.current.0.pkiTP.attributes.name == "certificate_authority_1" + - cm_delete_certificate_authority_1.current.0.pkiTP.attributes.descr == "This is a changed description." + - nm_delete_certificate_authority_1 is changed + - nm_delete_certificate_authority_1.previous.0.pkiTP.attributes.name == "certificate_authority_1" + - nm_delete_certificate_authority_1.previous.0.pkiTP.attributes.descr == "This is a changed description." + - nm_delete_certificate_authority_1.current == [] + - nm_delete_certificate_authority_1_again is not changed + - nm_delete_certificate_authority_1_again.previous == [] + - nm_delete_certificate_authority_1_again.current == [] + +# CLEAN ENVIRONMENT +- name: Delete another certificate authority + cisco.aci.aci_aaa_certificate_authority: + <<: *certificate_authority_2_absent diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_aaa_custom_privilege/tasks/main.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_aaa_custom_privilege/tasks/main.yml index 04b7070e2..907d21772 100644 --- a/ansible_collections/cisco/aci/tests/integration/targets/aci_aaa_custom_privilege/tasks/main.yml +++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_aaa_custom_privilege/tasks/main.yml @@ -4,13 +4,13 @@ # GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) - name: Test that we have an ACI APIC host, ACI username and ACI password - fail: + ansible.builtin.fail: msg: 'Please define the following variables: aci_hostname, aci_username and aci_password.' when: aci_hostname is not defined or aci_username is not defined or aci_password is not defined # SET VARS - name: Set vars - set_fact: + ansible.builtin.set_fact: aci_info: &aci_info host: '{{ aci_hostname }}' username: '{{ aci_username }}' @@ -47,7 +47,7 @@ register: cm_cp_present - name: Assertions check for add a custom privilege with check mode - assert: + ansible.builtin.assert: that: - cm_cp_present is changed - cm_cp_present.current | length == 0 @@ -63,7 +63,7 @@ register: nm_cp_present - name: Assertions check for add a custom privilege with normal mode - assert: + ansible.builtin.assert: that: - nm_cp_present is changed - nm_cp_present.current | length == 1 @@ -79,7 +79,7 @@ register: idempotency_cp_present - name: Idempotency assertions check for add a custom privilege with normal mode - assert: + ansible.builtin.assert: that: - idempotency_cp_present is not changed - idempotency_cp_present.current | length == 1 @@ -106,7 +106,7 @@ register: cp_with_none_priv - name: Assertions check for add a custom privilege with none privileges - assert: + ansible.builtin.assert: that: - cp_with_none_priv is changed - cp_with_none_priv.current | length == 1 @@ -123,7 +123,7 @@ register: update_cp_with_priv - name: Assertions check for update fv_tenant_present custom privilege with 'custom-privilege-2' privilege - assert: + ansible.builtin.assert: that: - update_cp_with_priv is changed - update_cp_with_priv.current | length == 1 @@ -141,7 +141,7 @@ register: update_cp_w_priv_check - name: Assertions check for update fv_tenant_present - write_privilege to 'custom-privilege-3' privilege - assert: + ansible.builtin.assert: that: - update_cp_w_priv_check is changed - update_cp_w_priv_check.current | length == 1 @@ -161,7 +161,7 @@ register: query_a_cp_with_name - name: Assertions check for query a custom privilege with name - assert: + ansible.builtin.assert: that: - query_a_cp_with_name is not changed - query_a_cp_with_name.current | length == 1 @@ -176,7 +176,7 @@ register: query_all_cp - name: Assertions check for query all custom privileges - assert: + ansible.builtin.assert: that: - query_all_cp is not changed - query_all_cp.current | length >= 2 @@ -190,7 +190,7 @@ register: cm_cp_absent - name: Assertions check for remove a custom privilege with check mode - assert: + ansible.builtin.assert: that: - cm_cp_absent is changed - cm_cp_absent.current | length == 1 @@ -204,7 +204,7 @@ register: nm_cp_absent - name: Assertions check for remove a custom privilege with normal mode - assert: + ansible.builtin.assert: that: - nm_cp_absent is changed - nm_cp_absent.current == [] @@ -217,7 +217,7 @@ register: idempotency_cp_absent - name: Idempotency assertions check for remove a custom privilege with normal mode - assert: + ansible.builtin.assert: that: - idempotency_cp_absent is not changed - idempotency_cp_absent.current == [] @@ -231,7 +231,7 @@ register: removed_cp_query_result - name: Assertions check for Removed custom privilege with name - assert: + ansible.builtin.assert: that: - removed_cp_query_result is not changed - removed_cp_query_result.current == [] diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_aaa_domain/tasks/main.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_aaa_domain/tasks/main.yml index 55eaaff79..06bd25d78 100644 --- a/ansible_collections/cisco/aci/tests/integration/targets/aci_aaa_domain/tasks/main.yml +++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_aaa_domain/tasks/main.yml @@ -4,13 +4,13 @@ # GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) - name: Test that we have an ACI APIC host, ACI username and ACI password - fail: + ansible.builtin.fail: msg: 'Please define the following variables: aci_hostname, aci_username and aci_password.' when: aci_hostname is not defined or aci_username is not defined or aci_password is not defined # SET VARS - name: Set vars - set_fact: + ansible.builtin.set_fact: aci_info: &aci_info host: '{{ aci_hostname }}' username: '{{ aci_username }}' @@ -42,7 +42,7 @@ register: cm_sec_domain_present - name: Assertions check for add anstest_sec_domain security domain with check mode - assert: + ansible.builtin.assert: that: - cm_sec_domain_present is changed - cm_sec_domain_present.current | length == 0 @@ -55,7 +55,7 @@ register: nm_sec_domain_present - name: Assertions check for add anstest_sec_domain security domain with normal mode - assert: + ansible.builtin.assert: that: - nm_sec_domain_present is changed - nm_sec_domain_present.current | length == 1 @@ -63,7 +63,7 @@ - nm_sec_domain_present.current.0.aaaDomain.attributes.name == 'anstest_sec_domain' - name: Assertions check for nm_sec_domain_present in v5.0+ - assert: + ansible.builtin.assert: that: - nm_sec_domain_present.current.0.aaaDomain.attributes.restrictedRbacDomain == 'no' when: version.current.0.topSystem.attributes.version is version('5', '>=') @@ -74,7 +74,7 @@ register: idempotency_sec_domain_present - name: Idempotency assertions check for add anstest_sec_domain security domain with normal mode - assert: + ansible.builtin.assert: that: - idempotency_sec_domain_present is not changed - idempotency_sec_domain_present.current | length == 1 @@ -83,7 +83,7 @@ - idempotency_sec_domain_present.previous.0.aaaDomain.attributes.name == 'anstest_sec_domain' - name: Assertions check for idempotency_sec_domain_present in v5.0+ - assert: + ansible.builtin.assert: that: - idempotency_sec_domain_present.current.0.aaaDomain.attributes.restrictedRbacDomain == 'no' - idempotency_sec_domain_present.previous.0.aaaDomain.attributes.restrictedRbacDomain == 'no' @@ -99,7 +99,7 @@ register: update_sec_domain_present_true - name: Assertions check for update anstest_sec_domain security domain restricted_rbac_domain state to true - assert: + ansible.builtin.assert: that: - update_sec_domain_present_true is changed - update_sec_domain_present_true.current | length == 1 @@ -116,7 +116,7 @@ register: update_sec_domain_present_false - name: Assertions check for update anstest_sec_domain security domain restricted_rbac_domain state to false - assert: + ansible.builtin.assert: that: - update_sec_domain_present_false is changed - update_sec_domain_present_false.current | length == 1 @@ -134,7 +134,7 @@ register: query_sec_domain_with_name - name: Assertions check for query a security domain with name - assert: + ansible.builtin.assert: that: - query_sec_domain_with_name is not changed - query_sec_domain_with_name.current | length == 1 @@ -142,7 +142,7 @@ - query_sec_domain_with_name.current.0.aaaDomain.attributes.descr == 'Anstest Sec Domain Descr' - name: Assertions check for query_sec_domain_with_name in v5.0+ - assert: + ansible.builtin.assert: that: - query_sec_domain_with_name.current.0.aaaDomain.attributes.restrictedRbacDomain == 'no' when: version.current.0.topSystem.attributes.version is version('5', '>=') @@ -154,7 +154,7 @@ register: query_all_sec_domains - name: Assertions check for query all security domains - assert: + ansible.builtin.assert: that: - query_all_sec_domains is not changed - query_all_sec_domains.current | length >= 1 @@ -167,7 +167,7 @@ register: cm_sec_domain_absent - name: Assertions check for remove anstest_sec_domain security domain with check mode - assert: + ansible.builtin.assert: that: - cm_sec_domain_absent is changed - cm_sec_domain_absent.current | length == 1 @@ -176,7 +176,7 @@ - cm_sec_domain_absent.previous.0.aaaDomain.attributes.name == 'anstest_sec_domain' - name: Assertions check for cm_sec_domain_absent in v5.0+ - assert: + ansible.builtin.assert: that: - cm_sec_domain_absent.current.0.aaaDomain.attributes.restrictedRbacDomain == 'no' - cm_sec_domain_absent.previous.0.aaaDomain.attributes.restrictedRbacDomain == 'no' @@ -188,7 +188,7 @@ register: nm_sec_domain_absent - name: Assertions check for remove anstest_sec_domain security domain with normal mode - assert: + ansible.builtin.assert: that: - nm_sec_domain_absent is changed - nm_sec_domain_absent.current | length == 0 @@ -196,7 +196,7 @@ - nm_sec_domain_absent.previous.0.aaaDomain.attributes.name == 'anstest_sec_domain' - name: Assertions check for nm_sec_domain_absent in v5.0+ - assert: + ansible.builtin.assert: that: - nm_sec_domain_absent.previous.0.aaaDomain.attributes.restrictedRbacDomain == 'no' when: version.current.0.topSystem.attributes.version is version('5', '>=') @@ -207,7 +207,7 @@ register: idempotency_sec_domain_absent - name: Idempotency assertions check for remove anstest_sec_domain security domain with normal mode - assert: + ansible.builtin.assert: that: - idempotency_sec_domain_absent is not changed - idempotency_sec_domain_absent.current | length == 0 @@ -221,7 +221,7 @@ register: removed_sec_domain_with_name - name: Assertions check for query a removed security domain with name - assert: + ansible.builtin.assert: that: - removed_sec_domain_with_name is not changed - removed_sec_domain_with_name.current | length == 0 diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_aaa_key_ring/aliases b/ansible_collections/cisco/aci/tests/integration/targets/aci_aaa_key_ring/aliases new file mode 100644 index 000000000..209b793f9 --- /dev/null +++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_aaa_key_ring/aliases @@ -0,0 +1,2 @@ +# No ACI simulator yet, so not enabled +# unsupported diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_aaa_key_ring/pki/admin.crt b/ansible_collections/cisco/aci/tests/integration/targets/aci_aaa_key_ring/pki/admin.crt new file mode 100644 index 000000000..cfac5531e --- /dev/null +++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_aaa_key_ring/pki/admin.crt @@ -0,0 +1,14 @@ +-----BEGIN CERTIFICATE----- +MIICODCCAaGgAwIBAgIJAIt8XMntue0VMA0GCSqGSIb3DQEBCwUAMDQxDjAMBgNV +BAMMBUFkbWluMRUwEwYDVQQKDAxZb3VyIENvbXBhbnkxCzAJBgNVBAYTAlVTMCAX +DTE4MDEwOTAwNTk0NFoYDzIxMTcxMjE2MDA1OTQ0WjA0MQ4wDAYDVQQDDAVBZG1p +bjEVMBMGA1UECgwMWW91ciBDb21wYW55MQswCQYDVQQGEwJVUzCBnzANBgkqhkiG +9w0BAQEFAAOBjQAwgYkCgYEAohG/7axtt7CbSaMP7r+2mhTKbNgh0Ww36C7Ta14i +v+VmLyKkQHnXinKGhp6uy3Nug+15a+eIu7CrgpBVMQeCiWfsnwRocKcQJWIYDrWl +XHxGQn31yYKR6mylE7Dcj3rMFybnyhezr5D8GcP85YRPmwG9H2hO/0Y1FUnWu9Iw +AQkCAwEAAaNQME4wHQYDVR0OBBYEFD0jLXfpkrU/ChzRvfruRs/fy1VXMB8GA1Ud +IwQYMBaAFD0jLXfpkrU/ChzRvfruRs/fy1VXMAwGA1UdEwQFMAMBAf8wDQYJKoZI +hvcNAQELBQADgYEAOmvre+5tgZ0+F3DgsfxNQqLTrGiBgGCIymPkP/cBXXkNuJyl +3ac7tArHQc7WEA4U2R2rZbEq8FC3UJJm4nUVtCPvEh3G9OhN2xwYev79yt6pIn/l +KU0Td2OpVyo0eLqjoX5u2G90IBWzhyjFbo+CcKMrSVKj1YOdG0E3OuiJf00= +-----END CERTIFICATE----- diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_aaa_key_ring/pki/admin.key b/ansible_collections/cisco/aci/tests/integration/targets/aci_aaa_key_ring/pki/admin.key new file mode 100644 index 000000000..63bb00cc0 --- /dev/null +++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_aaa_key_ring/pki/admin.key @@ -0,0 +1,16 @@ +-----BEGIN PRIVATE KEY----- +MIICdwIBADANBgkqhkiG9w0BAQEFAASCAmEwggJdAgEAAoGBAKIRv+2sbbewm0mj +D+6/tpoUymzYIdFsN+gu02teIr/lZi8ipEB514pyhoaerstzboPteWvniLuwq4KQ +VTEHgoln7J8EaHCnECViGA61pVx8RkJ99cmCkepspROw3I96zBcm58oXs6+Q/BnD +/OWET5sBvR9oTv9GNRVJ1rvSMAEJAgMBAAECgYByu3QO0qF9h7X3JEu0Ld4cKBnB +giQ2uJC/et7KxIJ/LOvw9GopBthyt27KwG1ntBkJpkTuAaQHkyNns7vLkNB0S0IR ++owVFEcKYq9VCHTaiQU8TDp24gN+yPTrpRuH8YhDVq5SfVdVuTMgHVQdj4ya4VlF +Gj+a7+ipxtGiLsVGrQJBAM7p0Fm0xmzi+tBOASUAcVrPLcteFIaTBFwfq16dm/ON +00Khla8Et5kMBttTbqbukl8mxFjBEEBlhQqb6EdQQ0sCQQDIhHx1a9diG7y/4DQA +4KvR3FCYwP8PBORlSamegzCo+P1OzxiEo0amX7yQMA5UyiP/kUsZrme2JBZgna8S +p4R7AkEAr7rMhSOPUnMD6V4WgsJ5g1Jp5kqkzBaYoVUUSms5RASz4+cwJVCwTX91 +Y1jcpVIBZmaaY3a0wrx13ajEAa0dOQJBAIpjnb4wqpsEh7VpmJqOdSdGxb1XXfFQ +sA0T1OQYqQnFppWwqrxIL+d9pZdiA1ITnNqyvUFBNETqDSOrUHwwb2cCQGArE+vu +ffPUWQ0j+fiK+covFG8NL7H+26NSGB5+Xsn9uwOGLj7K/YT6CbBtr9hJiuWjM1Al +0V4ltlTuu2mTMaw= +-----END PRIVATE KEY----- diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_aaa_key_ring/tasks/main.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_aaa_key_ring/tasks/main.yml new file mode 100644 index 000000000..be3a14763 --- /dev/null +++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_aaa_key_ring/tasks/main.yml @@ -0,0 +1,364 @@ +# Test code for the ACI modules +# Copyright: (c) 2024, Akini Ross (@akinross) +# +# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) + +- name: Test that we have an ACI APIC host, ACI username and ACI password + ansible.builtin.fail: + msg: 'Please define the following variables: aci_hostname, aci_username and aci_password.' + when: aci_hostname is not defined or aci_username is not defined or aci_password is not defined + +- name: Verify Cloud and Non-Cloud Sites in use. + ansible.builtin.include_tasks: ../../../../../../integration/targets/aci_cloud_provider/tasks/main.yml + +- name: Set vars + ansible.builtin.set_fact: + aci_info: &aci_info + host: "{{ aci_hostname }}" + username: "{{ aci_username }}" + password: "{{ aci_password }}" + validate_certs: '{{ aci_validate_certs | default(false) }}' + use_ssl: '{{ aci_use_ssl | default(true) }}' + use_proxy: '{{ aci_use_proxy | default(true) }}' + output_level: '{{ aci_use_proxy | default("info") }}' + +- name: Query system information to fetch version + cisco.aci.aci_system: + <<: *aci_info + id: 1 + state: query + register: version + +# CLEAN ENVIRONMENT +- name: Ensure certificate_authority_1 exists + cisco.aci.aci_aaa_certificate_authority: &certificate_authority_1 + <<: *aci_info + name: certificate_authority_1 + certificate_chain: "{{ lookup('file', 'pki/admin.crt') }}" + state: present + +- name: Delete key_ring_1 + cisco.aci.aci_aaa_key_ring: &key_ring_1_absent + <<: *aci_info + name: key_ring_1 + state: absent + register: delete_key_ring_1 + until: delete_key_ring_1 is not failed + delay: 2 + retries: 4 + +# CREATE +- name: Create a key ring (check_mode) + cisco.aci.aci_aaa_key_ring: &key_ring_1_present + <<: *key_ring_1_absent + name: key_ring_1 + modulus: 1024 + state: present + check_mode: true + register: cm_create_key_ring_1 + +- name: Create a key ring + cisco.aci.aci_aaa_key_ring: + <<: *key_ring_1_present + register: nm_create_key_ring_1 + +- name: Create a key ring again + cisco.aci.aci_aaa_key_ring: + <<: *key_ring_1_present + register: nm_create_key_ring_1_again + +- name: Assertions for creating a key ring + ansible.builtin.assert: + that: + - cm_create_key_ring_1 is changed + - cm_create_key_ring_1.previous == [] + - cm_create_key_ring_1.current == [] + - cm_create_key_ring_1.proposed.pkiKeyRing.attributes.name == "key_ring_1" + - cm_create_key_ring_1.proposed.pkiKeyRing.attributes.modulus == "mod1024" + - nm_create_key_ring_1 is changed + - nm_create_key_ring_1.previous == [] + - nm_create_key_ring_1.current.0.pkiKeyRing.attributes.name == "key_ring_1" + - nm_create_key_ring_1.current.0.pkiKeyRing.attributes.descr == "" + - nm_create_key_ring_1.current.0.pkiKeyRing.attributes.modulus == "mod1024" + - nm_create_key_ring_1.current.0.pkiKeyRing.attributes.tp == "" + - nm_create_key_ring_1_again is not changed + - nm_create_key_ring_1_again.previous.0.pkiKeyRing.attributes.name == "key_ring_1" + - nm_create_key_ring_1_again.previous.0.pkiKeyRing.attributes.descr == "" + - nm_create_key_ring_1_again.previous.0.pkiKeyRing.attributes.modulus == "mod1024" + - nm_create_key_ring_1_again.previous.0.pkiKeyRing.attributes.tp == "" + - nm_create_key_ring_1_again.current.0.pkiKeyRing.attributes.name == "key_ring_1" + - nm_create_key_ring_1_again.current.0.pkiKeyRing.attributes.descr == "" + - nm_create_key_ring_1_again.current.0.pkiKeyRing.attributes.modulus == "mod1024" + - nm_create_key_ring_1_again.current.0.pkiKeyRing.attributes.tp == "" + +# UPDATE +- name: Update an existing key ring + cisco.aci.aci_aaa_key_ring: + <<: *key_ring_1_present + description: "This is a changed description." + modulus: 2048 + certificate: "{{ lookup('file', 'pki/admin.crt') }}" + certificate_authority: certificate_authority_1 + key: "{{ lookup('file', 'pki/admin.key') }}" + register: nm_update_key_ring_1 + +- name: Assertions for updating a key ring + ansible.builtin.assert: + that: + - nm_update_key_ring_1 is changed + - nm_update_key_ring_1.previous.0.pkiKeyRing.attributes.name == "key_ring_1" + - nm_update_key_ring_1.previous.0.pkiKeyRing.attributes.descr == "" + - nm_update_key_ring_1.previous.0.pkiKeyRing.attributes.modulus == "mod1024" + - nm_update_key_ring_1.current.0.pkiKeyRing.attributes.name == "key_ring_1" + - nm_update_key_ring_1.current.0.pkiKeyRing.attributes.descr == "This is a changed description." + - nm_update_key_ring_1.current.0.pkiKeyRing.attributes.modulus == "mod2048" + - nm_update_key_ring_1.current.0.pkiKeyRing.attributes.tp == "certificate_authority_1" + +# VERSION SPECIFIC TESTS +- name: Test updating a key ring with key_type + when: version.current.0.topSystem.attributes.version is version('6.0', '>=') and query_cloud.current == [] + block: + - name: Update an existing key ring with key type >= 6.0 + cisco.aci.aci_aaa_key_ring: &key_ring_2_present + <<: *key_ring_1_present + name: key_ring_2 + key_type: ecc + ecc_curve: P521 + register: nm_create_key_ring_2_key_type + + - name: Assertions for updating a key ring with key_type + ansible.builtin.assert: + that: + - nm_update_key_ring_1.current.0.pkiKeyRing.attributes.keyType == "RSA" + - nm_update_key_ring_1.current.0.pkiKeyRing.attributes.eccCurve == "none" + - nm_create_key_ring_2_key_type is changed + - nm_create_key_ring_2_key_type.current.0.pkiKeyRing.attributes.keyType == "ECC" + - nm_create_key_ring_2_key_type.current.0.pkiKeyRing.attributes.eccCurve == "secp521r1" + + - name: Delete key_ring_2 + cisco.aci.aci_aaa_key_ring: + <<: *key_ring_2_present + state: absent + +# CLOUD SPECIFIC TESTS +- name: Execute tasks only for cloud sites + when: query_cloud.current != [] # This condition will execute only non-cloud sites + block: # block specifies execution of tasks within, based on conditions + + - name: Delete a key ring in cloud with tenant (check_mode) + cisco.aci.aci_aaa_key_ring: &key_ring_cloud_tenant_absent + <<: *aci_info + name: key_ring_cloud_tenant + cloud_tenant: cloud_tenant + certificate_authority: certificate_authority_cloud + state: absent + + - name: Delete certificate authority for cloud site tenant + cisco.aci.aci_aaa_certificate_authority: &certificate_authority_cloud_absent + <<: *aci_info + cloud_tenant: cloud_tenant + name: certificate_authority_cloud + certificate_chain: "{{ lookup('file', 'pki/admin.crt') }}" + state: absent + + - name: Delete tenant for key ring + cisco.aci.aci_tenant: &cloud_tenant_absent + <<: *aci_info + name: cloud_tenant + state: absent + register: cloud_tenant + until: cloud_tenant is not failed + delay: 2 + retries: 4 + + - name: Create tenant for key ring + cisco.aci.aci_tenant: + <<: *cloud_tenant_absent + state: present + + - name: Create certificate authority for cloud site tenant + cisco.aci.aci_aaa_certificate_authority: + <<: *certificate_authority_cloud_absent + state: present + + - name: Create a key ring in cloud with tenant (check_mode) + cisco.aci.aci_aaa_key_ring: &key_ring_cloud_tenant_present + <<: *key_ring_cloud_tenant_absent + state: present + check_mode: true + register: cm_create_key_ring_cloud_tenant + until: cm_create_key_ring_cloud_tenant is not failed + delay: 2 + retries: 4 + + - name: Create a key ring in cloud with tenant + cisco.aci.aci_aaa_key_ring: + <<: *key_ring_cloud_tenant_present + register: nm_create_key_ring_cloud_tenant + + - name: Create a key ring in cloud with tenant again + cisco.aci.aci_aaa_key_ring: + <<: *key_ring_cloud_tenant_present + register: nm_create_key_ring_cloud_tenant_again + + - name: Assertions for creating a key ring in cloud with tenant + ansible.builtin.assert: + that: + - cm_create_key_ring_cloud_tenant is changed + - cm_create_key_ring_cloud_tenant.previous == [] + - cm_create_key_ring_cloud_tenant.current == [] + - cm_create_key_ring_cloud_tenant.proposed.pkiKeyRing.attributes.name == "key_ring_cloud_tenant" + - cm_create_key_ring_cloud_tenant.proposed.pkiKeyRing.attributes.tp == "certificate_authority_cloud" + - nm_create_key_ring_cloud_tenant is changed + - nm_create_key_ring_cloud_tenant.previous == [] + - nm_create_key_ring_cloud_tenant.current != [] + - nm_create_key_ring_cloud_tenant.current.0.pkiKeyRing.attributes.name == "key_ring_cloud_tenant" + - nm_create_key_ring_cloud_tenant.current.0.pkiKeyRing.attributes.tp == "certificate_authority_cloud" + - nm_create_key_ring_cloud_tenant.current.0.pkiKeyRing.attributes.descr == "" + - nm_create_key_ring_cloud_tenant_again is not changed + - nm_create_key_ring_cloud_tenant_again.previous.0.pkiKeyRing.attributes.name == "key_ring_cloud_tenant" + - nm_create_key_ring_cloud_tenant_again.previous.0.pkiKeyRing.attributes.tp == "certificate_authority_cloud" + - nm_create_key_ring_cloud_tenant_again.previous.0.pkiKeyRing.attributes.descr == "" + - nm_create_key_ring_cloud_tenant_again.current.0.pkiKeyRing.attributes.name == "key_ring_cloud_tenant" + - nm_create_key_ring_cloud_tenant_again.current.0.pkiKeyRing.attributes.tp == "certificate_authority_cloud" + - nm_create_key_ring_cloud_tenant_again.current.0.pkiKeyRing.attributes.descr == "" + + + - name: Update an existing key ring in cloud with tenant + cisco.aci.aci_aaa_key_ring: + <<: *key_ring_cloud_tenant_present + description: "This is a changed description." + certificate: "{{ lookup('file', 'pki/admin.crt') }}" + certificate_authority: certificate_authority_cloud + key: "{{ lookup('file', 'pki/admin.key') }}" + register: nm_update_key_ring_cloud_tenant + + - name: Assertions for updating a key ring in cloud with tenant + ansible.builtin.assert: + that: + - nm_update_key_ring_cloud_tenant is changed + - nm_update_key_ring_cloud_tenant.previous.0.pkiKeyRing.attributes.name == "key_ring_cloud_tenant" + - nm_update_key_ring_cloud_tenant.previous.0.pkiKeyRing.attributes.descr == "" + - nm_update_key_ring_cloud_tenant.previous.0.pkiKeyRing.attributes.tp == "certificate_authority_cloud" + - nm_update_key_ring_cloud_tenant.current.0.pkiKeyRing.attributes.name == "key_ring_cloud_tenant" + - nm_update_key_ring_cloud_tenant.current.0.pkiKeyRing.attributes.descr == "This is a changed description." + - nm_update_key_ring_cloud_tenant.current.0.pkiKeyRing.attributes.tp == "certificate_authority_cloud" + + - name: Delete a key ring in cloud with tenant (check_mode) + cisco.aci.aci_aaa_key_ring: + <<: *key_ring_cloud_tenant_absent + check_mode: true + register: cm_delete_key_ring_cloud_tenant + + - name: Delete a key ring in cloud with tenant + cisco.aci.aci_aaa_key_ring: + <<: *key_ring_cloud_tenant_absent + register: nm_delete_key_ring_cloud_tenant + + - name: Delete a key ring in cloud with tenant again + cisco.aci.aci_aaa_key_ring: + <<: *key_ring_cloud_tenant_absent + register: nm_delete_key_ring_cloud_tenant_again + + - name: Assertions for deleting a key ring in cloud with tenant + ansible.builtin.assert: + that: + - cm_delete_key_ring_cloud_tenant is changed + - cm_delete_key_ring_cloud_tenant.previous.0.pkiKeyRing.attributes.name == "key_ring_cloud_tenant" + - cm_delete_key_ring_cloud_tenant.previous.0.pkiKeyRing.attributes.descr == "This is a changed description." + - cm_delete_key_ring_cloud_tenant.previous.0.pkiKeyRing.attributes.tp == "certificate_authority_cloud" + - cm_delete_key_ring_cloud_tenant.current.0.pkiKeyRing.attributes.name == "key_ring_cloud_tenant" + - cm_delete_key_ring_cloud_tenant.current.0.pkiKeyRing.attributes.descr == "This is a changed description." + - cm_delete_key_ring_cloud_tenant.current.0.pkiKeyRing.attributes.tp == "certificate_authority_cloud" + - cm_delete_key_ring_cloud_tenant.proposed == {} + - nm_delete_key_ring_cloud_tenant is changed + - nm_delete_key_ring_cloud_tenant.previous.0.pkiKeyRing.attributes.name == "key_ring_cloud_tenant" + - nm_delete_key_ring_cloud_tenant.previous.0.pkiKeyRing.attributes.descr == "This is a changed description." + - nm_delete_key_ring_cloud_tenant.previous.0.pkiKeyRing.attributes.tp == "certificate_authority_cloud" + - nm_delete_key_ring_cloud_tenant.current == [] + - nm_delete_key_ring_cloud_tenant_again is not changed + - nm_delete_key_ring_cloud_tenant_again.previous == [] + - nm_delete_key_ring_cloud_tenant_again.current == [] + + - name: Delete certificate authority for cloud site tenant + cisco.aci.aci_aaa_certificate_authority: + <<: *certificate_authority_cloud_absent + + - name: Delete tenant for key ring + cisco.aci.aci_tenant: + <<: *cloud_tenant_absent + register: cloud_tenant + until: cloud_tenant is not failed + delay: 2 + retries: 4 + +# QUERY +- name: Query a key ring + cisco.aci.aci_aaa_key_ring: + <<: *key_ring_1_present + state: query + register: query_key_ring_1 + +- name: Query all fabric management access policies + cisco.aci.aci_aaa_key_ring: + <<: *aci_info + state: query + register: query_all + +- name: Assertions for querying fabric management access policies + ansible.builtin.assert: + that: + - query_key_ring_1 is not changed + - query_key_ring_1.current.0.pkiKeyRing.attributes.name == "key_ring_1" + - query_key_ring_1.current.0.pkiKeyRing.attributes.descr == "This is a changed description." + - query_key_ring_1.current.0.pkiKeyRing.attributes.modulus == "mod2048" + - query_key_ring_1.current.0.pkiKeyRing.attributes.tp == "certificate_authority_1" + - query_key_ring_1.current | length == 1 + - query_all is not changed + - query_all.current | length >= 2 + +# DELETE +- name: Delete a key ring (check_mode) + cisco.aci.aci_aaa_key_ring: + <<: *key_ring_1_absent + check_mode: true + register: cm_delete_key_ring_1 + +- name: Delete a key ring + cisco.aci.aci_aaa_key_ring: + <<: *key_ring_1_absent + register: nm_delete_key_ring_1 + +- name: Delete a key ring again + cisco.aci.aci_aaa_key_ring: + <<: *key_ring_1_absent + register: nm_delete_key_ring_1_again + +- name: Assertions for deleting a key ring + ansible.builtin.assert: + that: + - cm_delete_key_ring_1 is changed + - cm_delete_key_ring_1.proposed == {} + - cm_delete_key_ring_1.previous.0.pkiKeyRing.attributes.name == "key_ring_1" + - cm_delete_key_ring_1.previous.0.pkiKeyRing.attributes.descr == "This is a changed description." + - cm_delete_key_ring_1.previous.0.pkiKeyRing.attributes.modulus == "mod2048" + - cm_delete_key_ring_1.previous.0.pkiKeyRing.attributes.tp == "certificate_authority_1" + - cm_delete_key_ring_1.current.0.pkiKeyRing.attributes.name == "key_ring_1" + - cm_delete_key_ring_1.current.0.pkiKeyRing.attributes.descr == "This is a changed description." + - cm_delete_key_ring_1.current.0.pkiKeyRing.attributes.modulus == "mod2048" + - cm_delete_key_ring_1.current.0.pkiKeyRing.attributes.tp == "certificate_authority_1" + - nm_delete_key_ring_1 is changed + - nm_delete_key_ring_1.previous.0.pkiKeyRing.attributes.name == "key_ring_1" + - nm_delete_key_ring_1.previous.0.pkiKeyRing.attributes.descr == "This is a changed description." + - nm_delete_key_ring_1.previous.0.pkiKeyRing.attributes.modulus == "mod2048" + - nm_delete_key_ring_1.previous.0.pkiKeyRing.attributes.tp == "certificate_authority_1" + - nm_delete_key_ring_1.current == [] + - nm_delete_key_ring_1_again is not changed + - nm_delete_key_ring_1_again.previous == [] + - nm_delete_key_ring_1_again.current == [] + +# CLEAN ENVIRONMENT +- name: Delete certificate_authority_1 + cisco.aci.aci_aaa_certificate_authority: + <<: *certificate_authority_1 + state: absent diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_aaa_role/tasks/main.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_aaa_role/tasks/main.yml index dce0fd4c6..f7735bc11 100644 --- a/ansible_collections/cisco/aci/tests/integration/targets/aci_aaa_role/tasks/main.yml +++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_aaa_role/tasks/main.yml @@ -4,13 +4,13 @@ # GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) - name: Test that we have an ACI APIC host, ACI username and ACI password - fail: + ansible.builtin.fail: msg: 'Please define the following variables: aci_hostname, aci_username and aci_password.' when: aci_hostname is not defined or aci_username is not defined or aci_password is not defined # SET VARS - name: Set vars - set_fact: + ansible.builtin.set_fact: aci_info: &aci_info host: '{{ aci_hostname }}' username: '{{ aci_username }}' @@ -42,7 +42,7 @@ register: cm_anstest_role_present - name: Assertions check for add an anstest_role aaa role with check mode - assert: + ansible.builtin.assert: that: - cm_anstest_role_present is changed - cm_anstest_role_present.current | length == 0 @@ -56,7 +56,7 @@ register: nm_anstest_role_present - name: Assertions check for add an anstest_role aaa role with normal mode - assert: + ansible.builtin.assert: that: - nm_anstest_role_present is changed - nm_anstest_role_present.current | length == 1 @@ -70,7 +70,7 @@ register: idempotency_anstest_role_present - name: Idempotency assertions check for add an anstest_role aaa role with normal mode - assert: + ansible.builtin.assert: that: - idempotency_anstest_role_present is not changed - idempotency_anstest_role_present.current | length == 1 @@ -87,7 +87,7 @@ register: anstest_role_with_list_priv - name: Assertions check for update an anstest_role with list of privileges - assert: + ansible.builtin.assert: that: - anstest_role_with_list_priv is changed - anstest_role_with_list_priv.current | length == 1 @@ -97,13 +97,13 @@ - anstest_role_with_list_priv.previous.0.aaaRole.attributes.priv == 'aaa' - name: Assertions check for anstest_role_with_list_priv on v4.2 or earlier - assert: + ansible.builtin.assert: that: - anstest_role_with_list_priv.current.0.aaaRole.attributes.priv == 'aaa,admin' when: version.current.0.topSystem.attributes.version is version('5', '<') - name: Assertions check for anstest_role_with_list_priv on v5+ - assert: + ansible.builtin.assert: that: - anstest_role_with_list_priv.current.0.aaaRole.attributes.priv == 'aaa,admin,tenant-connectivity' when: version.current.0.topSystem.attributes.version is version('5', '>=') @@ -116,7 +116,7 @@ register: anstest_role_with_valid_priv - name: Assertions check for update an anstest_role with admin privilege - assert: + ansible.builtin.assert: that: - anstest_role_with_valid_priv is changed - anstest_role_with_valid_priv.current | length == 1 @@ -126,13 +126,13 @@ - anstest_role_with_valid_priv.current.0.aaaRole.attributes.priv == 'admin' - name: Assertions check for anstest_role_with_valid_priv on v4.2 or earlier - assert: + ansible.builtin.assert: that: - anstest_role_with_valid_priv.previous.0.aaaRole.attributes.priv == 'aaa,admin' when: version.current.0.topSystem.attributes.version is version('5', '<') - name: Assertions check for anstest_role_with_valid_priv on v5+ - assert: + ansible.builtin.assert: that: - anstest_role_with_valid_priv.previous.0.aaaRole.attributes.priv == 'aaa,admin,tenant-connectivity' when: version.current.0.topSystem.attributes.version is version('5', '>=') @@ -152,7 +152,7 @@ ignore_errors: true - name: Assertions check for query a aaa role with name - assert: + ansible.builtin.assert: that: - anstest_role_with_invalid_list_priv.msg.startswith("value of privileges must be one or more of") - anstest_role_with_invalid_priv.msg.startswith("value of privileges must be one or more of") @@ -165,7 +165,7 @@ register: anstest_role_query_result - name: Assertions check for query a aaa role with name - assert: + ansible.builtin.assert: that: - anstest_role_query_result is not changed - anstest_role_query_result.current | length == 1 @@ -179,7 +179,7 @@ register: query_all_roles - name: Assertions check for query all aaa roles - assert: + ansible.builtin.assert: that: - query_all_roles is not changed - query_all_roles.current | length >= 1 @@ -192,7 +192,7 @@ register: cm_anstest_role_absent - name: Assertions check for remove an anstest_role aaa role with check mode - assert: + ansible.builtin.assert: that: - cm_anstest_role_absent is changed - cm_anstest_role_absent.current | length == 1 @@ -208,7 +208,7 @@ register: nm_anstest_role_absent - name: Assertions check for remove an anstest_role aaa role with normal mode - assert: + ansible.builtin.assert: that: - nm_anstest_role_absent is changed - nm_anstest_role_absent.current | length == 0 @@ -222,7 +222,7 @@ register: idempotency_anstest_role_absent - name: Idempotency assertions check for remove an anstest_role aaa role with normal mode - assert: + ansible.builtin.assert: that: - idempotency_anstest_role_absent is not changed - idempotency_anstest_role_absent.current | length == 0 diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_aaa_security_default_settings/aliases b/ansible_collections/cisco/aci/tests/integration/targets/aci_aaa_security_default_settings/aliases new file mode 100644 index 000000000..209b793f9 --- /dev/null +++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_aaa_security_default_settings/aliases @@ -0,0 +1,2 @@ +# No ACI simulator yet, so not enabled +# unsupported diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_aaa_security_default_settings/tasks/main.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_aaa_security_default_settings/tasks/main.yml new file mode 100644 index 000000000..24b63693e --- /dev/null +++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_aaa_security_default_settings/tasks/main.yml @@ -0,0 +1,235 @@ +# Test code for the ACI modules +# Copyright: (c) 2024, Akini Ross (@akinross) + +# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) + +- name: Test that we have an ACI APIC host, ACI username and ACI password + ansible.builtin.fail: + msg: "Please define the following variables: aci_hostname, aci_username and aci_password." + when: aci_hostname is not defined or aci_username is not defined or aci_password is not defined + +- name: Verify Cloud and Non-Cloud Sites in use. + ansible.builtin.include_tasks: ../../../../../../integration/targets/aci_cloud_provider/tasks/main.yml + +# SET VARS +- name: Set vars + ansible.builtin.set_fact: + aci_info: &aci_info + host: "{{ aci_hostname }}" + username: "{{ aci_remote_username }}" + password: "{{ aci_password }}" + validate_certs: "{{ aci_validate_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: Always set aaa_password_update_required to false and security settings back to defaults + when: query_cloud.current == [] # This condition will execute only non-cloud sites + block: + # CLEAN + - name: Set AAA Security Default Settings to Default Values + cisco.aci.aci_aaa_security_default_settings: &security_settings_defaults + <<: *aci_info + password_strength_check: true + password_strength_profile: + enable: false + password_change: + enable: false + interval: 48 + allowed_changes: 2 + minimum_period_between_password_changes: 24 + history_storage_amount: 5 + lockout: + enable: false + max_attempts: 5 + window: 5 + duration: 60 + web_token: + timeout: 600 + idle_timeout: 1200 + validity_period: 24 + refresh: false + state: present + + # QUERY + - name: Query AAA security default settings + cisco.aci.aci_aaa_security_default_settings: + <<: *aci_info + state: query + register: query_security_settings + + - name: Assertions for enabling a AAA security default settings + ansible.builtin.assert: + that: + - query_security_settings is not changed + - query_security_settings.current.0.aaaUserEp.attributes.pwdStrengthCheck == "yes" + - query_security_settings.current.0.aaaUserEp.children.0.aaaBlockLoginProfile.attributes.blockDuration == "60" + - query_security_settings.current.0.aaaUserEp.children.0.aaaBlockLoginProfile.attributes.enableLoginBlock == "disable" + - query_security_settings.current.0.aaaUserEp.children.0.aaaBlockLoginProfile.attributes.maxFailedAttempts == "5" + - query_security_settings.current.0.aaaUserEp.children.0.aaaBlockLoginProfile.attributes.maxFailedAttemptsWindow == "5" + - query_security_settings.current.0.aaaUserEp.children.1.aaaPwdProfile.attributes.changeCount == "2" + - query_security_settings.current.0.aaaUserEp.children.1.aaaPwdProfile.attributes.changeInterval == "48" + - query_security_settings.current.0.aaaUserEp.children.1.aaaPwdProfile.attributes.historyCount == "5" + - query_security_settings.current.0.aaaUserEp.children.1.aaaPwdProfile.attributes.noChangeInterval == "24" + - query_security_settings.current.0.aaaUserEp.children.2.pkiEp.children.0.pkiWebTokenData.attributes.maximumValidityPeriod == "24" + - query_security_settings.current.0.aaaUserEp.children.2.pkiEp.children.0.pkiWebTokenData.attributes.sessionRecordFlags == "login,logout" + - query_security_settings.current.0.aaaUserEp.children.2.pkiEp.children.0.pkiWebTokenData.attributes.uiIdleTimeoutSeconds == "1200" + - query_security_settings.current.0.aaaUserEp.children.2.pkiEp.children.0.pkiWebTokenData.attributes.webtokenTimeoutSeconds == "600" + + # UPDATE + - name: Update AAA security default settings password_strength_check + cisco.aci.aci_aaa_security_default_settings: + <<: *aci_info + password_strength_check: false + + - name: Update AAA security default settings (check_mode) + cisco.aci.aci_aaa_security_default_settings: &security_settings + <<: *aci_info + password_strength_check: true + password_strength_profile: + enable: true # do not test with true as it will for for password change and locks out the user + type: custom + min_length: 9 + max_length: 25 + class_flags: + - digits + - lowercase + - uppercase + password_change: + enable: true # do not test with true as it will for for password change and locks out the user + interval: 60 + allowed_changes: 3 + minimum_period_between_password_changes: 25 + history_storage_amount: 6 + lockout: + enable: true + max_attempts: 6 + window: 6 + duration: 30 + web_token: + timeout: 601 + idle_timeout: 1201 + validity_period: 23 + refresh: true + check_mode: true + register: cm_update_security_settings + + - name: Update AAA security default settings + cisco.aci.aci_aaa_security_default_settings: + <<: *security_settings + register: nm_update_security_settings + + - name: Update AAA security default settings again + cisco.aci.aci_aaa_security_default_settings: + <<: *security_settings + register: nm_update_security_settings_again + + - name: Assertions for enabling a AAA security default settings + ansible.builtin.assert: + that: + - cm_update_security_settings is changed + - cm_update_security_settings.current.0.aaaUserEp.attributes.pwdStrengthCheck == "no" + - cm_update_security_settings.current.0.aaaUserEp.children.0.aaaBlockLoginProfile.attributes.blockDuration == "60" + - cm_update_security_settings.current.0.aaaUserEp.children.0.aaaBlockLoginProfile.attributes.enableLoginBlock == "disable" + - cm_update_security_settings.current.0.aaaUserEp.children.0.aaaBlockLoginProfile.attributes.maxFailedAttempts == "5" + - cm_update_security_settings.current.0.aaaUserEp.children.0.aaaBlockLoginProfile.attributes.maxFailedAttemptsWindow == "5" + - cm_update_security_settings.current.0.aaaUserEp.children.1.aaaPwdProfile.attributes.changeCount == "2" + - cm_update_security_settings.current.0.aaaUserEp.children.1.aaaPwdProfile.attributes.changeInterval == "48" + - cm_update_security_settings.current.0.aaaUserEp.children.1.aaaPwdProfile.attributes.historyCount == "5" + - cm_update_security_settings.current.0.aaaUserEp.children.1.aaaPwdProfile.attributes.noChangeInterval == "24" + - cm_update_security_settings.current.0.aaaUserEp.children.2.pkiEp.children.0.pkiWebTokenData.attributes.maximumValidityPeriod == "24" + - cm_update_security_settings.current.0.aaaUserEp.children.2.pkiEp.children.0.pkiWebTokenData.attributes.sessionRecordFlags == "login,logout" + - cm_update_security_settings.current.0.aaaUserEp.children.2.pkiEp.children.0.pkiWebTokenData.attributes.uiIdleTimeoutSeconds == "1200" + - cm_update_security_settings.current.0.aaaUserEp.children.2.pkiEp.children.0.pkiWebTokenData.attributes.webtokenTimeoutSeconds == "600" + - cm_update_security_settings.proposed.aaaUserEp.attributes.pwdStrengthCheck == "yes" + - cm_update_security_settings.proposed.aaaUserEp.children.0.aaaPwdStrengthProfile.attributes.pwdClassFlags == "digits,lowercase,uppercase" + - cm_update_security_settings.proposed.aaaUserEp.children.0.aaaPwdStrengthProfile.attributes.pwdMaxLength == "25" + - cm_update_security_settings.proposed.aaaUserEp.children.0.aaaPwdStrengthProfile.attributes.pwdMinLength == "9" + - cm_update_security_settings.proposed.aaaUserEp.children.0.aaaPwdStrengthProfile.attributes.pwdStrengthTestType == "custom" + - cm_update_security_settings.proposed.aaaUserEp.children.2.aaaBlockLoginProfile.attributes.blockDuration == "30" + - cm_update_security_settings.proposed.aaaUserEp.children.2.aaaBlockLoginProfile.attributes.enableLoginBlock == "enable" + - cm_update_security_settings.proposed.aaaUserEp.children.2.aaaBlockLoginProfile.attributes.maxFailedAttempts == "6" + - cm_update_security_settings.proposed.aaaUserEp.children.2.aaaBlockLoginProfile.attributes.maxFailedAttemptsWindow == "6" + - cm_update_security_settings.proposed.aaaUserEp.children.1.aaaPwdProfile.attributes.changeCount == "3" + - cm_update_security_settings.proposed.aaaUserEp.children.1.aaaPwdProfile.attributes.changeInterval == "60" + - cm_update_security_settings.proposed.aaaUserEp.children.1.aaaPwdProfile.attributes.historyCount == "6" + - cm_update_security_settings.proposed.aaaUserEp.children.1.aaaPwdProfile.attributes.noChangeInterval == "25" + - cm_update_security_settings.proposed.aaaUserEp.children.3.pkiEp.children.0.pkiWebTokenData.attributes.maximumValidityPeriod == "23" + - cm_update_security_settings.proposed.aaaUserEp.children.3.pkiEp.children.0.pkiWebTokenData.attributes.sessionRecordFlags == "login,logout,refresh" + - cm_update_security_settings.proposed.aaaUserEp.children.3.pkiEp.children.0.pkiWebTokenData.attributes.uiIdleTimeoutSeconds == "1201" + - cm_update_security_settings.proposed.aaaUserEp.children.3.pkiEp.children.0.pkiWebTokenData.attributes.webtokenTimeoutSeconds == "601" + - nm_update_security_settings is changed + - nm_update_security_settings.previous.0.aaaUserEp.attributes.pwdStrengthCheck == "no" + - nm_update_security_settings.previous.0.aaaUserEp.children.0.aaaBlockLoginProfile.attributes.blockDuration == "60" + - nm_update_security_settings.previous.0.aaaUserEp.children.0.aaaBlockLoginProfile.attributes.enableLoginBlock == "disable" + - nm_update_security_settings.previous.0.aaaUserEp.children.0.aaaBlockLoginProfile.attributes.maxFailedAttempts == "5" + - nm_update_security_settings.previous.0.aaaUserEp.children.0.aaaBlockLoginProfile.attributes.maxFailedAttemptsWindow == "5" + - nm_update_security_settings.previous.0.aaaUserEp.children.1.aaaPwdProfile.attributes.changeCount == "2" + - nm_update_security_settings.previous.0.aaaUserEp.children.1.aaaPwdProfile.attributes.changeInterval == "48" + - nm_update_security_settings.previous.0.aaaUserEp.children.1.aaaPwdProfile.attributes.historyCount == "5" + - nm_update_security_settings.previous.0.aaaUserEp.children.1.aaaPwdProfile.attributes.noChangeInterval == "24" + - nm_update_security_settings.previous.0.aaaUserEp.children.2.pkiEp.children.0.pkiWebTokenData.attributes.maximumValidityPeriod == "24" + - nm_update_security_settings.previous.0.aaaUserEp.children.2.pkiEp.children.0.pkiWebTokenData.attributes.sessionRecordFlags == "login,logout" + - nm_update_security_settings.previous.0.aaaUserEp.children.2.pkiEp.children.0.pkiWebTokenData.attributes.uiIdleTimeoutSeconds == "1200" + - nm_update_security_settings.previous.0.aaaUserEp.children.2.pkiEp.children.0.pkiWebTokenData.attributes.webtokenTimeoutSeconds == "600" + - nm_update_security_settings.current.0.aaaUserEp.attributes.pwdStrengthCheck == "yes" + - nm_update_security_settings.current.0.aaaUserEp.children.0.aaaBlockLoginProfile.attributes.blockDuration == "30" + - nm_update_security_settings.current.0.aaaUserEp.children.0.aaaBlockLoginProfile.attributes.enableLoginBlock == "enable" + - nm_update_security_settings.current.0.aaaUserEp.children.0.aaaBlockLoginProfile.attributes.maxFailedAttempts == "6" + - nm_update_security_settings.current.0.aaaUserEp.children.0.aaaBlockLoginProfile.attributes.maxFailedAttemptsWindow == "6" + - nm_update_security_settings.current.0.aaaUserEp.children.1.aaaPwdStrengthProfile.attributes.pwdClassFlags == "digits,lowercase,uppercase" + - nm_update_security_settings.current.0.aaaUserEp.children.1.aaaPwdStrengthProfile.attributes.pwdMaxLength == "25" + - nm_update_security_settings.current.0.aaaUserEp.children.1.aaaPwdStrengthProfile.attributes.pwdMinLength == "9" + - nm_update_security_settings.current.0.aaaUserEp.children.1.aaaPwdStrengthProfile.attributes.pwdStrengthTestType == "custom" + - nm_update_security_settings.current.0.aaaUserEp.children.2.aaaPwdProfile.attributes.changeCount == "3" + - nm_update_security_settings.current.0.aaaUserEp.children.2.aaaPwdProfile.attributes.changeInterval == "60" + - nm_update_security_settings.current.0.aaaUserEp.children.2.aaaPwdProfile.attributes.historyCount == "6" + - nm_update_security_settings.current.0.aaaUserEp.children.2.aaaPwdProfile.attributes.noChangeInterval == "25" + - nm_update_security_settings.current.0.aaaUserEp.children.3.pkiEp.children.0.pkiWebTokenData.attributes.maximumValidityPeriod == "23" + - nm_update_security_settings.current.0.aaaUserEp.children.3.pkiEp.children.0.pkiWebTokenData.attributes.sessionRecordFlags == "login,logout,refresh" + - nm_update_security_settings.current.0.aaaUserEp.children.3.pkiEp.children.0.pkiWebTokenData.attributes.uiIdleTimeoutSeconds == "1201" + - nm_update_security_settings.current.0.aaaUserEp.children.3.pkiEp.children.0.pkiWebTokenData.attributes.webtokenTimeoutSeconds == "601" + - nm_update_security_settings_again is not changed + - nm_update_security_settings_again.previous.0.aaaUserEp.children.0.aaaBlockLoginProfile.attributes.blockDuration == "30" + - nm_update_security_settings_again.previous.0.aaaUserEp.children.0.aaaBlockLoginProfile.attributes.enableLoginBlock == "enable" + - nm_update_security_settings_again.previous.0.aaaUserEp.children.0.aaaBlockLoginProfile.attributes.maxFailedAttempts == "6" + - nm_update_security_settings_again.previous.0.aaaUserEp.children.0.aaaBlockLoginProfile.attributes.maxFailedAttemptsWindow == "6" + - nm_update_security_settings_again.previous.0.aaaUserEp.children.1.aaaPwdStrengthProfile.attributes.pwdClassFlags == "digits,lowercase,uppercase" + - nm_update_security_settings_again.previous.0.aaaUserEp.children.1.aaaPwdStrengthProfile.attributes.pwdMaxLength == "25" + - nm_update_security_settings_again.previous.0.aaaUserEp.children.1.aaaPwdStrengthProfile.attributes.pwdMinLength == "9" + - nm_update_security_settings_again.previous.0.aaaUserEp.children.1.aaaPwdStrengthProfile.attributes.pwdStrengthTestType == "custom" + - nm_update_security_settings_again.previous.0.aaaUserEp.children.2.aaaPwdProfile.attributes.changeCount == "3" + - nm_update_security_settings_again.previous.0.aaaUserEp.children.2.aaaPwdProfile.attributes.changeInterval == "60" + - nm_update_security_settings_again.previous.0.aaaUserEp.children.2.aaaPwdProfile.attributes.historyCount == "6" + - nm_update_security_settings_again.previous.0.aaaUserEp.children.2.aaaPwdProfile.attributes.noChangeInterval == "25" + - nm_update_security_settings_again.previous.0.aaaUserEp.children.3.pkiEp.children.0.pkiWebTokenData.attributes.maximumValidityPeriod == "23" + - nm_update_security_settings_again.previous.0.aaaUserEp.children.3.pkiEp.children.0.pkiWebTokenData.attributes.sessionRecordFlags == "login,logout,refresh" + - nm_update_security_settings_again.previous.0.aaaUserEp.children.3.pkiEp.children.0.pkiWebTokenData.attributes.uiIdleTimeoutSeconds == "1201" + - nm_update_security_settings_again.previous.0.aaaUserEp.children.3.pkiEp.children.0.pkiWebTokenData.attributes.webtokenTimeoutSeconds == "601" + - nm_update_security_settings_again.current.0.aaaUserEp.children.0.aaaBlockLoginProfile.attributes.blockDuration == "30" + - nm_update_security_settings_again.current.0.aaaUserEp.children.0.aaaBlockLoginProfile.attributes.enableLoginBlock == "enable" + - nm_update_security_settings_again.current.0.aaaUserEp.children.0.aaaBlockLoginProfile.attributes.maxFailedAttempts == "6" + - nm_update_security_settings_again.current.0.aaaUserEp.children.0.aaaBlockLoginProfile.attributes.maxFailedAttemptsWindow == "6" + - nm_update_security_settings_again.current.0.aaaUserEp.children.1.aaaPwdStrengthProfile.attributes.pwdClassFlags == "digits,lowercase,uppercase" + - nm_update_security_settings_again.current.0.aaaUserEp.children.1.aaaPwdStrengthProfile.attributes.pwdMaxLength == "25" + - nm_update_security_settings_again.current.0.aaaUserEp.children.1.aaaPwdStrengthProfile.attributes.pwdMinLength == "9" + - nm_update_security_settings_again.current.0.aaaUserEp.children.1.aaaPwdStrengthProfile.attributes.pwdStrengthTestType == "custom" + - nm_update_security_settings_again.current.0.aaaUserEp.children.2.aaaPwdProfile.attributes.changeCount == "3" + - nm_update_security_settings_again.current.0.aaaUserEp.children.2.aaaPwdProfile.attributes.changeInterval == "60" + - nm_update_security_settings_again.current.0.aaaUserEp.children.2.aaaPwdProfile.attributes.historyCount == "6" + - nm_update_security_settings_again.current.0.aaaUserEp.children.2.aaaPwdProfile.attributes.noChangeInterval == "25" + - nm_update_security_settings_again.current.0.aaaUserEp.children.3.pkiEp.children.0.pkiWebTokenData.attributes.maximumValidityPeriod == "23" + - nm_update_security_settings_again.current.0.aaaUserEp.children.3.pkiEp.children.0.pkiWebTokenData.attributes.sessionRecordFlags == "login,logout,refresh" + - nm_update_security_settings_again.current.0.aaaUserEp.children.3.pkiEp.children.0.pkiWebTokenData.attributes.uiIdleTimeoutSeconds == "1201" + - nm_update_security_settings_again.current.0.aaaUserEp.children.3.pkiEp.children.0.pkiWebTokenData.attributes.webtokenTimeoutSeconds == "601" + + always: + - name: Set aaa_password_update_required back to false + cisco.aci.aci_aaa_user: + <<: *aci_info + aaa_user: "{{ aci_username }}" + aaa_password_update_required: false + + - name: Set AAA Security Default Settings to Default Values + cisco.aci.aci_aaa_security_default_settings: + <<: *security_settings_defaults diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_aaa_ssh_auth/tasks/main.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_aaa_ssh_auth/tasks/main.yml index 46113c0f9..9c2462bb4 100644 --- a/ansible_collections/cisco/aci/tests/integration/targets/aci_aaa_ssh_auth/tasks/main.yml +++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_aaa_ssh_auth/tasks/main.yml @@ -5,12 +5,12 @@ # GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) - name: Test that we have an ACI APIC host, ACI username and ACI password - fail: + ansible.builtin.fail: msg: 'Please define the following variables: aci_hostname, aci_username and aci_password.' when: aci_hostname is not defined or aci_username is not defined or aci_password is not defined - name: Set vars - set_fact: + ansible.builtin.set_fact: aci_info: &aci_info host: "{{ aci_hostname }}" username: "{{ aci_username }}" @@ -64,7 +64,7 @@ register: nm_add_ssh_key_again - name: Verify add SSH key - assert: + ansible.builtin.assert: that: - cm_add_ssh_key is changed - nm_add_ssh_key is changed @@ -92,7 +92,7 @@ register: nm_query_all_ssh_keys - name: Verify query_all_ssh_keys - assert: + ansible.builtin.assert: that: - cm_query_all_ssh_keys is not changed - nm_query_all_ssh_keys is not changed @@ -111,7 +111,7 @@ register: nm_query_ssh_key - name: Verify query_ssh_key - assert: + ansible.builtin.assert: that: - cm_query_ssh_key is not changed - nm_query_ssh_key is not changed @@ -148,7 +148,7 @@ register: nm_remove_ssh_key_again - name: Verify remove_user - assert: + ansible.builtin.assert: that: - cm_remove_ssh_key is changed - nm_remove_ssh_key is changed diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_aaa_user/tasks/main.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_aaa_user/tasks/main.yml index 52f3ed0fb..8c25cef4c 100644 --- a/ansible_collections/cisco/aci/tests/integration/targets/aci_aaa_user/tasks/main.yml +++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_aaa_user/tasks/main.yml @@ -4,7 +4,7 @@ # GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) - name: Test that we have an ACI APIC host, ACI username and ACI password - fail: + ansible.builtin.fail: msg: 'Please define the following variables: aci_hostname, aci_username and aci_password.' when: aci_hostname is not defined or aci_username is not defined or aci_password is not defined @@ -84,7 +84,7 @@ register: nm_add_user_again - name: Verify add user - assert: + ansible.builtin.assert: that: - cm_add_user is changed - nm_add_user is changed @@ -134,7 +134,7 @@ register: nm_modify_user_again - name: Verify modify user - assert: + ansible.builtin.assert: that: - cm_modify_user is changed - err_modify_user_expiration.msg == "Failed to parse date format 'wrong_expiration', Unknown string format{{":"}} wrong_expiration" @@ -174,7 +174,7 @@ register: nm_clear_password_history_again - name: Verify clear password history - assert: + ansible.builtin.assert: that: # NOTE: Clearing password history is a changing action, everytime - cm_clear_password_history is changed @@ -203,7 +203,7 @@ register: nm_query_all_users - name: Verify query_all_users - assert: + ansible.builtin.assert: that: - cm_query_all_users is not changed - nm_query_all_users is not changed @@ -224,7 +224,7 @@ register: nm_query_user - name: Verify query_user - assert: + ansible.builtin.assert: that: - cm_query_user is not changed - nm_query_user is not changed @@ -257,7 +257,7 @@ register: nm_remove_user_again - name: Verify remove_user - assert: + ansible.builtin.assert: that: - cm_remove_user is changed - nm_remove_user is changed diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_aaa_user_certificate/tasks/main.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_aaa_user_certificate/tasks/main.yml index 3140816e0..7d21d5c27 100644 --- a/ansible_collections/cisco/aci/tests/integration/targets/aci_aaa_user_certificate/tasks/main.yml +++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_aaa_user_certificate/tasks/main.yml @@ -4,12 +4,12 @@ # GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) - name: Test that we have an ACI APIC host, ACI username and ACI password - fail: + ansible.builtin.fail: msg: 'Please define the following variables: aci_hostname, aci_username and aci_password.' when: aci_hostname is not defined or aci_username is not defined or aci_password is not defined - name: Set vars - set_fact: + ansible.builtin.set_fact: aci_info: &aci_info host: "{{ aci_hostname }}" username: "{{ aci_username }}" @@ -82,7 +82,7 @@ register: nm_add_cert_again - name: Verify add_cert - assert: + ansible.builtin.assert: that: - cm_add_cert is changed - nm_add_cert is change @@ -127,7 +127,7 @@ register: nm_query_all_certs - name: Verify query_all_certs - assert: + ansible.builtin.assert: that: - cm_query_all_certs is not changed - nm_query_all_certs is not changed @@ -142,7 +142,7 @@ register: nm_query_all_rsa - name: Verify nm_query_all_rsa - assert: + ansible.builtin.assert: that: - nm_query_all_rsa is not changed - nm_query_all_rsa.current.0.aaaUser.children | length >= 4 @@ -184,7 +184,7 @@ register: nm_query_cert - name: Verify query_cert - assert: + ansible.builtin.assert: that: - cm_query_cert is not changed - nm_query_cert is not changed @@ -283,7 +283,7 @@ register: nm_remove_cert_again - name: Verify remove_cert - assert: + ansible.builtin.assert: that: - cm_remove_cert is changed - nm_remove_cert is changed @@ -292,7 +292,7 @@ # Checking if changing certification_name to name throws an error. (#82) - name: Making sure current user has correct cert - aci_aaa_user_certificate: + cisco.aci.aci_aaa_user_certificate: <<: *aci_info aaa_user: '{{ aci_username }}' name: admin @@ -377,7 +377,7 @@ register: query_test_pk_content - name: Verify query_test - assert: + ansible.builtin.assert: that: - query_test is not changed - query_test_pk_file is not changed diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_aaa_user_domain/tasks/main.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_aaa_user_domain/tasks/main.yml index ac0d1d0f2..5bc3968bc 100644 --- a/ansible_collections/cisco/aci/tests/integration/targets/aci_aaa_user_domain/tasks/main.yml +++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_aaa_user_domain/tasks/main.yml @@ -6,13 +6,13 @@ # GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) - name: Test that we have an ACI APIC host, ACI username and ACI password - fail: + ansible.builtin.fail: msg: 'Please define the following variables: aci_hostname, aci_username and aci_password.' when: aci_hostname is not defined or aci_username is not defined or aci_password is not defined # SET VARS - name: Set vars - set_fact: + ansible.builtin.set_fact: aci_info: &aci_info host: '{{ aci_hostname }}' username: '{{ aci_username }}' @@ -70,7 +70,7 @@ register: cm_sec_domain_present - name: Assertions check for add user domain to aaa_user with check mode - assert: + ansible.builtin.assert: that: - cm_sec_domain_present is changed - cm_sec_domain_present.current | length == 0 @@ -83,7 +83,7 @@ register: nm_sec_domain_present - name: Assertions check for add user domain to aaa_user with normal mode - assert: + ansible.builtin.assert: that: - nm_sec_domain_present is changed - nm_sec_domain_present.current | length == 1 @@ -97,7 +97,7 @@ register: cm_idempotency_sec_domain_present - name: Idempotency assertions check for add user domain to aaa_user with check mode - assert: + ansible.builtin.assert: that: - cm_idempotency_sec_domain_present is not changed - cm_idempotency_sec_domain_present.current | length == 1 @@ -111,7 +111,7 @@ register: idempotency_sec_domain_present - name: Idempotency assertions check for add user domain to aaa_user with normal mode - assert: + ansible.builtin.assert: that: - idempotency_sec_domain_present is not changed - idempotency_sec_domain_present.current | length == 1 @@ -139,7 +139,7 @@ register: query_anstest_sec_domain - name: Assertions check for query a user domain from a aaa_user - assert: + ansible.builtin.assert: that: - query_anstest_sec_domain is not changed - query_anstest_sec_domain.current | length == 1 @@ -154,7 +154,7 @@ register: query_aaa_user_domains - name: Assertions check for query all user domains from a aaa_user - assert: + ansible.builtin.assert: that: - query_aaa_user_domains is not changed - query_aaa_user_domains.current | length == 1 @@ -167,7 +167,7 @@ register: query_all_aaa_user_domains - name: Assertions check for query all user domains - assert: + ansible.builtin.assert: that: - query_all_aaa_user_domains is not changed - query_all_aaa_user_domains.current | length >= 3 @@ -181,7 +181,7 @@ register: cm_sec_domain_absent - name: Assertions check for removing user domain from a aaa_user with check mode - assert: + ansible.builtin.assert: that: - cm_sec_domain_absent is changed - cm_sec_domain_absent.current | length == 1 @@ -196,7 +196,7 @@ register: nm_sec_domain_absent - name: Assertions check for removing user domain from a aaa_user with normal mode - assert: + ansible.builtin.assert: that: - nm_sec_domain_absent is changed - nm_sec_domain_absent.current == [] @@ -211,7 +211,7 @@ register: idempotency_sec_domain_absent - name: Idempotency assertions check for removing user domain - assert: + ansible.builtin.assert: that: - idempotency_sec_domain_absent is not changed - idempotency_sec_domain_absent.current == [] diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_aaa_user_role/tasks/main.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_aaa_user_role/tasks/main.yml index 4a4d34017..6aaaafbec 100644 --- a/ansible_collections/cisco/aci/tests/integration/targets/aci_aaa_user_role/tasks/main.yml +++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_aaa_user_role/tasks/main.yml @@ -6,13 +6,13 @@ # GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) - name: Test that we have an ACI APIC host, ACI username and ACI password - fail: + ansible.builtin.fail: msg: 'Please define the following variables: aci_hostname, aci_username and aci_password.' when: aci_hostname is not defined or aci_username is not defined or aci_password is not defined # SET VARS - name: Set vars - set_fact: + ansible.builtin.set_fact: aci_info: &aci_info host: '{{ aci_hostname }}' username: '{{ aci_username }}' @@ -87,7 +87,7 @@ register: cm_user_role_present - name: Assertions check for add user role to "anstest-security-domain" with check mode - assert: + ansible.builtin.assert: that: - cm_user_role_present is changed - cm_user_role_present.current | length == 0 @@ -101,7 +101,7 @@ register: nm_user_role_present - name: Assertions check for add user role to "anstest-security-domain" with normal mode - assert: + ansible.builtin.assert: that: - nm_user_role_present is changed - nm_user_role_present.current | length == 1 @@ -116,7 +116,7 @@ register: cm_idempotency_user_role_present - name: Idempotency assertions check for add user role to "anstest-security-domain" check mode - assert: + ansible.builtin.assert: that: - cm_idempotency_user_role_present is not changed - cm_idempotency_user_role_present.previous | length == 1 @@ -132,7 +132,7 @@ register: idempotency_user_role_present - name: Idempotency assertions check for add user role to "anstest-security-domain" - assert: + ansible.builtin.assert: that: - idempotency_user_role_present is not changed - idempotency_user_role_present.previous | length == 1 @@ -152,7 +152,7 @@ register: user_role_present_sec_domain1 - name: Assertions check for add a user role to "anstest-security-domain-1" - assert: + ansible.builtin.assert: that: - user_role_present_sec_domain1 is changed - user_role_present_sec_domain1.current | length == 1 @@ -169,7 +169,7 @@ register: cm_update_user_role_present - name: Assertions check for update user role to "anstest-security-domain" with check mode - assert: + ansible.builtin.assert: that: - cm_update_user_role_present is changed - cm_update_user_role_present.current | length == 1 @@ -183,7 +183,7 @@ register: update_user_role_present - name: Assertions check for update user role to "anstest-security-domain" with normal mode - assert: + ansible.builtin.assert: that: - update_user_role_present is changed - update_user_role_present.current | length == 1 @@ -217,7 +217,7 @@ register: query_user_role_from_sec_domain - name: Assertions check for query a user role from "anstest-security-domain-1" user domain - assert: + ansible.builtin.assert: that: - query_user_role_from_sec_domain is not changed - query_user_role_from_sec_domain.current | length == 1 @@ -235,7 +235,7 @@ register: query_all_user_roles_of_sec_domain - name: Assertions check for query all user roles from "anstest-security-domain" user domain - assert: + ansible.builtin.assert: that: - query_all_user_roles_of_sec_domain is not changed - query_all_user_roles_of_sec_domain.current | length == 1 @@ -250,7 +250,7 @@ register: query_all_user_roles_from_a_user - name: Assertions check for query all user roles from a user - assert: + ansible.builtin.assert: that: - query_all_user_roles_from_a_user is not changed - query_all_user_roles_from_a_user.current | length == 1 @@ -264,7 +264,7 @@ register: query_all_user_roles - name: Assertions check for query all user roles - assert: + ansible.builtin.assert: that: - query_all_user_roles is not changed - query_all_user_roles.current | length >= 6 # count of user roles including common sec domain user role @@ -281,7 +281,7 @@ register: cm_user_role_absent - name: Assertions check for removing a user role from "anstest-security-domain-1" with check mode - assert: + ansible.builtin.assert: that: - cm_user_role_absent is changed - cm_user_role_absent.current | length == 1 @@ -297,7 +297,7 @@ register: nm_user_role_absent - name: Assertions check for removing a user role from "anstest-security-domain-1" with normal mode - assert: + ansible.builtin.assert: that: - nm_user_role_absent is changed - nm_user_role_absent.current == [] @@ -311,7 +311,7 @@ register: idempotency_user_role_absent - name: Idempotency assertions check for removing a user role from "anstest-security-domain-1" - assert: + ansible.builtin.assert: that: - idempotency_user_role_absent is not changed - idempotency_user_role_absent.current == [] diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_access_port_block_to_access_port/tasks/main.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_access_port_block_to_access_port/tasks/main.yml index 38bda95c8..ad838725f 100644 --- a/ansible_collections/cisco/aci/tests/integration/targets/aci_access_port_block_to_access_port/tasks/main.yml +++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_access_port_block_to_access_port/tasks/main.yml @@ -1,39 +1,54 @@ # Test code for the ACI modules # Copyright: (c) 2020, Shreyas Srish # Copyright: (c) 2017, Bruno Calogero +# Copyright: (c) 2024, Gaspard Micol (@gmicol) # GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) - name: Test that we have an ACI APIC host, ACI username and ACI password - fail: + ansible.builtin.fail: msg: 'Please define the following variables: aci_hostname, aci_username and aci_password.' when: aci_hostname is not defined or aci_username is not defined or aci_password is not defined +- name: Set vars + ansible.builtin.set_fact: + aci_info: &aci_info + host: "{{ aci_hostname }}" + username: "{{ aci_username }}" + password: "{{ aci_password }}" + validate_certs: '{{ aci_validate_certs | default(false) }}' + use_ssl: '{{ aci_use_ssl | default(true) }}' + use_proxy: '{{ aci_use_proxy | default(true) }}' + output_level: '{{ aci_output_level | default("info") }}' + - name: Verify Cloud and Non-Cloud Sites in use. - include_tasks: ../../../../../../integration/targets/aci_cloud_provider/tasks/main.yml + ansible.builtin.include_tasks: ../../../../../../integration/targets/aci_cloud_provider/tasks/main.yml - name: Execute tasks only for non-cloud sites when: query_cloud.current == [] # This condition will execute only non-cloud sites block: # block specifies execution of tasks within, based on conditions + + # CLEAN ENVIRONMENT - name: 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 + <<: *aci_info leaf_interface_profile: leafintprftest + state: absent 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 Spine profile does not exist + cisco.aci.aci_access_spine_interface_profile: &aci_interface_policy_spine_profile_absent + <<: *aci_info + spine_interface_profile: spineintprftest + state: absent + + # CREATE PARENT CLASS OBJECT - name: Ensuring Interface Policy Leaf profile exists for kick off cisco.aci.aci_interface_policy_leaf_profile: <<: *aci_interface_policy_leaf_profile_absent @@ -47,6 +62,11 @@ leaf_interface_profile: leafintprftest_fex state: present + - name: Ensuring Interface Policy Spine profile exists for kick off + cisco.aci.aci_access_spine_interface_profile: + <<: *aci_interface_policy_spine_profile_absent + 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 @@ -60,14 +80,14 @@ 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: Ensure Spine Interface Access Port Selector exists for kick of + cisco.aci.aci_access_spine_interface_selector: &aci_access_spine_interface_selector_present + <<: *aci_interface_policy_spine_profile_absent + access_port_selector: anstest_spineaccessportselector + state: present + # CREATION TASKS + # LEAF PORT BLOCK CREATION - 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 @@ -103,6 +123,7 @@ toPort: 15 register: accessportblock_to_accessport_update + # LEAF FEX PORT BLOCK CREATION - 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 @@ -152,9 +173,39 @@ toPort: 24 register: accessportblock_to_accessport_present_fex_update + # SPINE PORT BLOCK CREATION + - name: Bind an access port block to an access spine interface selector -check mode works + cisco.aci.aci_access_port_block_to_access_port: &aci_access_port_block_to_spine_access_port_present + <<: *aci_access_spine_interface_selector_present + port_blk: anstest_spineportblkname + port_blk_description: anstest_spineportblkdesc + fromPort: 10 + toPort: 15 + type: spine + state: present + check_mode: true + register: accessportblock_to_spineaccessport_check_mode_present + + - name: Bind an access port block to an access spine interface selector - creation works + cisco.aci.aci_access_port_block_to_access_port: + <<: *aci_access_port_block_to_spine_access_port_present + register: accessportblock_to_spineaccessport_present + + - name: Bind an access port block to an access spine interface selector - idempotency works + cisco.aci.aci_access_port_block_to_access_port: + <<: *aci_access_port_block_to_spine_access_port_present + register: accessportblock_to_spineaccessport_present_idempotent + + - name: Bind an access port block to an access spine interface selector - update works + cisco.aci.aci_access_port_block_to_access_port: + <<: *aci_access_port_block_to_spine_access_port_present + fromPort: 11 + toPort: 16 + register: accessportblock_to_spineaccessport_present_update + # TODO: also test for errors - name: present assertions - create / indempotency / update works - assert: + ansible.builtin.assert: that: - accessportblock_to_accessport_check_mode_present is changed - accessportblock_to_accessport_present is changed @@ -174,6 +225,31 @@ - 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' + - accessportblock_to_spineaccessport_check_mode_present is changed + - accessportblock_to_spineaccessport_check_mode_present.previous == [] + - accessportblock_to_spineaccessport_check_mode_present.current == [] + - accessportblock_to_spineaccessport_check_mode_present.proposed.infraPortBlk.attributes.name == "anstest_spineportblkname" + - accessportblock_to_spineaccessport_check_mode_present.proposed.infraPortBlk.attributes.descr == "anstest_spineportblkdesc" + - accessportblock_to_spineaccessport_check_mode_present.proposed.infraPortBlk.attributes.fromPort == "10" + - accessportblock_to_spineaccessport_check_mode_present.proposed.infraPortBlk.attributes.toPort == "15" + - accessportblock_to_spineaccessport_present is changed + - accessportblock_to_spineaccessport_present.previous == [] + - accessportblock_to_spineaccessport_present.current.0.infraPortBlk.attributes.name == "anstest_spineportblkname" + - accessportblock_to_spineaccessport_present.current.0.infraPortBlk.attributes.descr == "anstest_spineportblkdesc" + - accessportblock_to_spineaccessport_present.current.0.infraPortBlk.attributes.fromPort == "10" + - accessportblock_to_spineaccessport_present.current.0.infraPortBlk.attributes.toPort == "15" + - accessportblock_to_spineaccessport_present_idempotent is not changed + - accessportblock_to_spineaccessport_present_idempotent.current == accessportblock_to_spineaccessport_present.current + - accessportblock_to_spineaccessport_present_update is changed + - accessportblock_to_spineaccessport_present_update.current.0.infraPortBlk.attributes.fromPort == "11" + - accessportblock_to_spineaccessport_present_update.current.0.infraPortBlk.attributes.toPort == "16" + + # QUEY TASKS + - name: Query all port block and access_port_selector bindings + cisco.aci.aci_access_port_block_to_access_port: + <<: *aci_info + state: query + register: binding_query_all - name: Query Specific port block and access_port_selector binding cisco.aci.aci_access_port_block_to_access_port: @@ -191,15 +267,30 @@ state: query register: binding_query_fex + - name: Query Specific port block and access_port_selector binding spine + cisco.aci.aci_access_port_block_to_access_port: + <<: *aci_access_spine_interface_selector_present + type: spine + port_blk: anstest_spineportblkname + state: query + register: binding_query_spine + - name: query assertions - assert: + ansible.builtin.assert: that: + - binding_query_all is not changed + - binding_query_all.current | length >= 3 - 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' + - binding_query_spine is not changed + - binding_query_spine.current.0.infraPortBlk.attributes.name == "anstest_spineportblkname" + - binding_query_spine.current.0.infraPortBlk.attributes.descr == "anstest_spineportblkdesc" + - binding_query_spine.current.0.infraPortBlk.attributes.fromPort == "11" + - binding_query_spine.current.0.infraPortBlk.attributes.toPort == "16" + # DELETE TASKS - 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 @@ -217,7 +308,7 @@ <<: *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 + - name: Remove binding of Access Port Block and Interface Access Port Selector - missing parameter cisco.aci.aci_access_port_block_to_access_port: <<: *aci_access_port_to_interface_policy_leaf_profile_present #leaf_port_blk: anstest_leafportblkname @@ -235,9 +326,14 @@ state: absent register: accessportblock_to_accessport_absent_fex + - name: Remove binding of Access Port Block and Spine Interface Access Port Selector - delete works + cisco.aci.aci_access_port_block_to_access_port: + <<: *aci_access_port_block_to_spine_access_port_present + state: absent + register: accessportblock_to_accessport_absent_spine - name: absent assertions - assert: + ansible.builtin.assert: that: - accessportblock_to_accessport_check_mode_absent is changed - accessportblock_to_accessport_check_mode_absent.previous != [] @@ -248,6 +344,10 @@ - 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 + - accessportblock_to_accessport_absent_spine is changed + - accessportblock_to_accessport_absent_spine.previous != [] + - accessportblock_to_accessport_absent_spine.proposed == {} + - accessportblock_to_accessport_absent_spine.current == [] - name: Ensuring Interface Policy Leaf profile does not exist cisco.aci.aci_interface_policy_leaf_profile: @@ -258,4 +358,8 @@ 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 + leaf_interface_profile: leafintprftest_fex + + - name: Ensuring Interface Policy Spine profile does not exist + cisco.aci.aci_access_spine_interface_profile: + <<: *aci_interface_policy_spine_profile_absent diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_access_port_to_interface_policy_leaf_profile/tasks/main.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_access_port_to_interface_policy_leaf_profile/tasks/main.yml index 2244e0b16..a3005fbd7 100644 --- a/ansible_collections/cisco/aci/tests/integration/targets/aci_access_port_to_interface_policy_leaf_profile/tasks/main.yml +++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_access_port_to_interface_policy_leaf_profile/tasks/main.yml @@ -5,13 +5,13 @@ # GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) - name: Test that we have an ACI APIC host, ACI username and ACI password - fail: + ansible.builtin.fail: msg: "Please define the following variables: aci_hostname, aci_username and aci_password." when: aci_hostname is not defined or aci_username is not defined or aci_password is not defined # SET VARS - name: Set vars - set_fact: + ansible.builtin.set_fact: aci_info: &aci_info host: "{{ aci_hostname }}" username: "{{ aci_username }}" @@ -22,7 +22,7 @@ output_level: '{{ aci_output_level | default("info") }}' - name: Verify Cloud and Non-Cloud Sites in use. - include_tasks: ../../../../../../integration/targets/aci_cloud_provider/tasks/main.yml + ansible.builtin.include_tasks: ../../../../../../integration/targets/aci_cloud_provider/tasks/main.yml - name: Execute tasks only for non-cloud sites when: query_cloud.current == [] # This condition will execute only non-cloud sites @@ -80,7 +80,7 @@ register: fexintprftest_policy_group_present - name: Assertions check for remove fex policy group from the fexintprftest fex profile - assert: + ansible.builtin.assert: that: - fexintprftest_policy_group_present is changed - fexintprftest_policy_group_present.current | length == 1 @@ -141,7 +141,7 @@ # TODO: also test for errors - name: present assertions - assert: + ansible.builtin.assert: that: - accessport_to_intf_check_mode_present is changed - accessport_to_intf_present is changed @@ -180,7 +180,7 @@ register: binding_query_fex - name: present assertions - assert: + ansible.builtin.assert: that: - binding_query is not changed - binding_query_fex is not changed @@ -203,7 +203,7 @@ register: bind_fexintprftest_policy_group - name: Assertions check for bind anstest_fex_accessportselector with fexintprftest - Fex Profile Policy Group - assert: + ansible.builtin.assert: that: - bind_fexintprftest_policy_group is changed - bind_fexintprftest_policy_group.previous | length == 0 @@ -226,7 +226,7 @@ register: bind_fexintprftest_policy_group_2 - name: Assertions check for bind anstest_fex_accessportselector with fexintprftest - Fex Profile Policy Group - assert: + ansible.builtin.assert: that: - bind_fexintprftest_policy_group_2 is changed - bind_fexintprftest_policy_group_2.previous | length == 0 @@ -241,7 +241,7 @@ register: fexintprftest_policy_group_absent - name: Assertions check for remove fex policy group from the fexintprftest fex profile - assert: + ansible.builtin.assert: that: - fexintprftest_policy_group_absent is changed - fexintprftest_policy_group_absent.current | length == 0 @@ -275,7 +275,7 @@ register: accessport_to_intf_absent_fex - name: absent assertions - assert: + ansible.builtin.assert: that: - accessport_to_intf_check_mode_absent is changed - accessport_to_intf_absent_fex is changed @@ -318,7 +318,7 @@ register: cm_fpc_present - name: Assertion check for bind anstest_fex_port_channel Access Port Selector with policygroupname_link_fpc Policy Group - check mode - assert: + ansible.builtin.assert: that: - cm_fpc_present.current | length == 0 - cm_fpc_present.previous | length == 0 @@ -331,7 +331,7 @@ register: nm_fpc_present - name: Assertion check for bind anstest_fex_port_channel Access Port Selector with policygroupname_link_fpc Policy Group - normal mode - assert: + ansible.builtin.assert: that: - nm_fpc_present.current | length == 1 - nm_fpc_present.previous | length == 0 @@ -347,7 +347,7 @@ register: cm_fpc_absent - name: Assertion check for remove anstest_fex_port_channel Access Port Selector with policygroupname_link_fpc Policy Group - check mode - assert: + ansible.builtin.assert: that: - cm_fpc_absent.current | length == 1 - cm_fpc_absent.previous | length == 1 @@ -364,7 +364,7 @@ register: nm_fpc_absent - name: Assertion check for remove anstest_fex_port_channel Access Port Selector with policygroupname_link_fpc Policy Group - normal mode - assert: + ansible.builtin.assert: that: - nm_fpc_absent.current | length == 0 - nm_fpc_absent.previous | length == 1 @@ -380,7 +380,7 @@ register: anstest_fex_vpc_present - name: Assertion check for add anstest_fex_vpc - Interface Policy Leaf Profile with type Fex - assert: + ansible.builtin.assert: that: - anstest_fex_vpc_present.current | length == 1 - anstest_fex_vpc_present.current.0.infraFexP.attributes.name == "anstest_fex_vpc" @@ -397,7 +397,7 @@ register: policygroupname_node_fvpc_present - name: Assertion check for add policygroupname_node_fvpc - Policy Group with lag type node - assert: + ansible.builtin.assert: that: - policygroupname_node_fvpc_present.current | length == 1 - policygroupname_node_fvpc_present.current.0.infraAccBndlGrp.attributes.name == "policygroupname_node_fvpc" @@ -414,7 +414,7 @@ register: cm_fex_vpc_present - name: Assertion check for bind anstest_fex_vpc Access Port Selector with policygroupname_node_fvpc Policy Group - check mode - assert: + ansible.builtin.assert: that: - cm_fex_vpc_present.current | length == 0 - cm_fex_vpc_present.previous | length == 0 @@ -427,7 +427,7 @@ register: nm_fex_vpc_present - name: Assertion check for bind anstest_fex_vpc Access Port Selector with policygroupname_node_fvpc Policy Group - normal mode - assert: + ansible.builtin.assert: that: - nm_fex_vpc_present.current | length == 1 - nm_fex_vpc_present.previous | length == 0 @@ -443,7 +443,7 @@ register: cm_fex_vpc_absent - name: Assertion check for remove anstest_fex_vpc Access Port Selector with policygroupname_node_fvpc Policy Group - check mode - assert: + ansible.builtin.assert: that: - cm_fex_vpc_absent.current | length == 1 - cm_fex_vpc_absent.previous | length == 1 @@ -460,7 +460,7 @@ register: nm_fex_vpc_absent - name: Assertion check for remove anstest_fex_vpc Access Port Selector with policygroupname_node_fvpc Policy Group - normal mode - assert: + ansible.builtin.assert: that: - nm_fex_vpc_absent.current | length == 0 - nm_fex_vpc_absent.previous | length == 1 @@ -476,7 +476,7 @@ register: anstest_fex_vpc_absent - name: Assertion check for remove anstest_fex_vpc - Interface Policy Leaf Profile with type Fex - assert: + ansible.builtin.assert: that: - anstest_fex_vpc_absent.current | length == 0 - anstest_fex_vpc_absent.previous | length == 1 @@ -489,7 +489,7 @@ register: anstest_fex_port_channel_absent - name: Assertion check for remove anstest_fex_port_channel - Interface Policy Leaf Profile with type Fex - assert: + ansible.builtin.assert: that: - anstest_fex_port_channel_absent.current | length == 0 - anstest_fex_port_channel_absent.previous | length == 1 @@ -504,7 +504,7 @@ register: anstest_leaf_profile_absent - name: Assertion check for ensure anstest_leaf_profile interface does not exists - assert: + ansible.builtin.assert: that: - anstest_leaf_profile_absent.current | length == 0 @@ -517,7 +517,7 @@ register: anstest_fex_profile_absent - name: Assertion check for ensure anstest_fex_profile interface does not exists - assert: + ansible.builtin.assert: that: - anstest_fex_profile_absent.current | length == 0 @@ -530,7 +530,7 @@ register: temp_anstest_fex_profile_absent - name: Assertion check for ensure temp_anstest_fex_profile interface does not exists - assert: + ansible.builtin.assert: that: - temp_anstest_fex_profile_absent.current | length == 0 @@ -541,7 +541,7 @@ register: anstest_leaf_profile_present - name: Assertion check for add a new anstest_leaf_profile with profile type leaf - assert: + ansible.builtin.assert: that: - anstest_leaf_profile_present is changed - anstest_leaf_profile_present.current | length == 1 @@ -556,7 +556,7 @@ register: anstest_fex_profile_present - name: Assertion check for add a new anstest_fex_profile with profile type fex - assert: + ansible.builtin.assert: that: - anstest_fex_profile_present is changed - anstest_fex_profile_present.current | length == 1 @@ -571,7 +571,7 @@ register: temp_anstest_fex_profile_present - name: Assertion check for add a new temp_anstest_fex_profile with profile type fex - assert: + ansible.builtin.assert: that: - temp_anstest_fex_profile_present is changed - temp_anstest_fex_profile_present.current | length == 1 @@ -589,7 +589,7 @@ register: temp_anstest_fex_profile_policy_group_present - name: Assertion check for add a new policy_group with the same name of interface profile - temp_anstest_fex_profile - assert: + ansible.builtin.assert: that: - temp_anstest_fex_profile_policy_group_present is changed - temp_anstest_fex_profile_policy_group_present.current | length == 1 @@ -611,7 +611,7 @@ ignore_errors: true - name: Assertion check for bind temp_anstest_fex_profile with anstest_fex_profile - Fex Profile Policy Group - assert: + ansible.builtin.assert: that: - temp_anstest_fex_profile_access_port_present.msg == "Invalid Configuration - interface_type fex_profile can not be configured with a profile of type fex" @@ -621,7 +621,7 @@ register: remove_anstest_fex_profile_absent - name: Assertion check for remove temp_anstest_fex_profile - assert: + ansible.builtin.assert: that: - remove_anstest_fex_profile_absent is changed - remove_anstest_fex_profile_absent.current | length == 0 @@ -637,7 +637,7 @@ register: anstest_fex_profile_policy_group_present - name: Assertion check for add a new policy_group with the same name of interface profile - anstest_fex_profile - assert: + ansible.builtin.assert: that: - anstest_fex_profile_policy_group_present is changed - anstest_fex_profile_policy_group_present.current | length == 1 @@ -659,7 +659,7 @@ register: anstest_leaf_profile_access_port_present - name: Assertion check for bind anstest_leaf_profile with anstest_fex_profile - Fex Profile Policy Group - assert: + ansible.builtin.assert: that: - anstest_leaf_profile_access_port_present is changed - anstest_leaf_profile_access_port_present.current | length == 1 @@ -682,7 +682,7 @@ register: anstest_leaf_profile_access_port_wrong_fex_id - name: Assertion check for bind anstest_leaf_profile with wrong fex_id - assert: + ansible.builtin.assert: that: - anstest_leaf_profile_access_port_wrong_fex_id.msg == "A valid FEX ID is between 101 to 199" @@ -699,7 +699,7 @@ register: anstest_leaf_profile_access_port_no_fex_id - name: Assertion check for bind anstest_leaf_profile with no fex_id - assert: + ansible.builtin.assert: that: - anstest_leaf_profile_access_port_no_fex_id.msg == "The fex_id must not be None, when interface_type is fex_profile" @@ -709,7 +709,7 @@ register: anstest_leaf_profile_cleanup - name: Assertion check for remove anstest_leaf_profile - assert: + ansible.builtin.assert: that: - anstest_leaf_profile_cleanup is changed - anstest_leaf_profile_cleanup.previous | length == 1 @@ -721,7 +721,7 @@ register: anstest_fex_profile_cleanup - name: Assertion check for remove anstest_fex_profile - assert: + ansible.builtin.assert: that: - anstest_fex_profile_cleanup is changed - anstest_fex_profile_cleanup.previous | length == 1 diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_access_span_dst_group/tasks/main.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_access_span_dst_group/tasks/main.yml index 03c2e92c2..1c4329f4b 100644 --- a/ansible_collections/cisco/aci/tests/integration/targets/aci_access_span_dst_group/tasks/main.yml +++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_access_span_dst_group/tasks/main.yml @@ -4,7 +4,7 @@ # GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) - name: Test that we have an ACI APIC host, ACI username and ACI password - fail: + ansible.builtin.fail: msg: 'Please define the following variables: aci_hostname, aci_username and aci_password.' when: aci_hostname is not defined or aci_username is not defined or aci_password is not defined diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_access_span_filter_group/tasks/main.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_access_span_filter_group/tasks/main.yml index c071f747a..4f04e42ed 100644 --- a/ansible_collections/cisco/aci/tests/integration/targets/aci_access_span_filter_group/tasks/main.yml +++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_access_span_filter_group/tasks/main.yml @@ -4,7 +4,7 @@ # GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) - name: Test that we have an ACI APIC host, ACI username and ACI password - fail: + ansible.builtin.fail: msg: 'Please define the following variables: aci_hostname, aci_username and aci_password.' when: aci_hostname is not defined or aci_username is not defined or aci_password is not defined @@ -20,7 +20,7 @@ output_level: '{{ aci_output_level | default("info") }}' - name: Verify Cloud and Non-Cloud Sites in use. - include_tasks: ../../../../../../integration/targets/aci_cloud_provider/tasks/main.yml + ansible.builtin.include_tasks: ../../../../../../integration/targets/aci_cloud_provider/tasks/main.yml - name: Execute tasks only for non-cloud sites when: diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_access_span_filter_group_entry/tasks/main.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_access_span_filter_group_entry/tasks/main.yml index 788658f13..421956534 100644 --- a/ansible_collections/cisco/aci/tests/integration/targets/aci_access_span_filter_group_entry/tasks/main.yml +++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_access_span_filter_group_entry/tasks/main.yml @@ -4,7 +4,7 @@ # GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) - name: Test that we have an ACI APIC host, ACI username and ACI password - fail: + ansible.builtin.fail: msg: 'Please define the following variables: aci_hostname, aci_username and aci_password.' when: aci_hostname is not defined or aci_username is not defined or aci_password is not defined @@ -20,7 +20,7 @@ output_level: '{{ aci_output_level | default("info") }}' - name: Verify Cloud and Non-Cloud Sites in use. - include_tasks: ../../../../../../integration/targets/aci_cloud_provider/tasks/main.yml + ansible.builtin.include_tasks: ../../../../../../integration/targets/aci_cloud_provider/tasks/main.yml - name: Execute tasks only for non-cloud sites when: diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_access_span_src_group/tasks/main.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_access_span_src_group/tasks/main.yml index e2d00e525..b55d5ced0 100644 --- a/ansible_collections/cisco/aci/tests/integration/targets/aci_access_span_src_group/tasks/main.yml +++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_access_span_src_group/tasks/main.yml @@ -4,12 +4,12 @@ # GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) - name: Test that we have an ACI APIC host, ACI username and ACI password - fail: + ansible.builtin.fail: msg: 'Please define the following variables: aci_hostname, aci_username and aci_password.' when: aci_hostname is not defined or aci_username is not defined or aci_password is not defined - name: Set vars - set_fact: + ansible.builtin.set_fact: aci_info: &aci_info host: "{{ aci_hostname }}" username: "{{ aci_username }}" @@ -20,7 +20,7 @@ output_level: '{{ aci_output_level | default("info") }}' - name: Verify Cloud and Non-Cloud Sites in use. - include_tasks: ../../../../../../integration/targets/aci_cloud_provider/tasks/main.yml + ansible.builtin.include_tasks: ../../../../../../integration/targets/aci_cloud_provider/tasks/main.yml # CLEAN TEST ENVIRONMENT BEFORE TESTS diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_access_span_src_group_src/tasks/main.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_access_span_src_group_src/tasks/main.yml index a0fe48f08..ce033f911 100644 --- a/ansible_collections/cisco/aci/tests/integration/targets/aci_access_span_src_group_src/tasks/main.yml +++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_access_span_src_group_src/tasks/main.yml @@ -4,12 +4,12 @@ # GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) - name: Test that we have an ACI APIC host, ACI username and ACI password - fail: + ansible.builtin.fail: msg: 'Please define the following variables: aci_hostname, aci_username and aci_password.' when: aci_hostname is not defined or aci_username is not defined or aci_password is not defined - name: Set vars - set_fact: + ansible.builtin.set_fact: aci_info: &aci_info host: "{{ aci_hostname }}" username: "{{ aci_username }}" @@ -20,7 +20,7 @@ output_level: '{{ aci_output_level | default("info") }}' - name: Verify Cloud and Non-Cloud Sites in use. - include_tasks: ../../../../../../integration/targets/aci_cloud_provider/tasks/main.yml + ansible.builtin.include_tasks: ../../../../../../integration/targets/aci_cloud_provider/tasks/main.yml # CLEAN TEST ENVIRONMENT BEFORE TESTS diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_access_span_src_group_src_path/tasks/main.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_access_span_src_group_src_path/tasks/main.yml index f370b1323..3196e78de 100644 --- a/ansible_collections/cisco/aci/tests/integration/targets/aci_access_span_src_group_src_path/tasks/main.yml +++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_access_span_src_group_src_path/tasks/main.yml @@ -4,12 +4,12 @@ # GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) - name: Test that we have an ACI APIC host, ACI username and ACI password - fail: + ansible.builtin.fail: msg: 'Please define the following variables: aci_hostname, aci_username and aci_password.' when: aci_hostname is not defined or aci_username is not defined or aci_password is not defined - name: Set vars - set_fact: + ansible.builtin.set_fact: aci_info: &aci_info host: "{{ aci_hostname }}" username: "{{ aci_username }}" diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_access_spine_interface_profile/aliases b/ansible_collections/cisco/aci/tests/integration/targets/aci_access_spine_interface_profile/aliases new file mode 100644 index 000000000..209b793f9 --- /dev/null +++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_access_spine_interface_profile/aliases @@ -0,0 +1,2 @@ +# No ACI simulator yet, so not enabled +# unsupported diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_access_spine_interface_profile/tasks/main.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_access_spine_interface_profile/tasks/main.yml new file mode 100644 index 000000000..9f43513f0 --- /dev/null +++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_access_spine_interface_profile/tasks/main.yml @@ -0,0 +1,183 @@ +# Test code for the ACI modules +# Copyright: (c) 2023, Eric Girard <@netgirard> +# Copyright: (c) 2024, Gaspard Micol (@gmicol) + +# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) + +- name: Test that we have an ACI APIC host, ACI username and ACI password + ansible.builtin.fail: + msg: 'Please define the following variables: aci_hostname, aci_username and aci_password.' + when: aci_hostname is not defined or aci_username is not defined or aci_password is not defined + +- name: Set vars + ansible.builtin.set_fact: + aci_info: &aci_info + host: "{{ aci_hostname }}" + username: "{{ aci_username }}" + password: "{{ aci_password }}" + validate_certs: '{{ aci_validate_certs | default(false) }}' + use_ssl: '{{ aci_use_ssl | default(true) }}' + use_proxy: '{{ aci_use_proxy | default(true) }}' + output_level: '{{ aci_output_level | default("info") }}' + +- name: Verify Cloud and Non-Cloud Sites in use. + ansible.builtin.include_tasks: ../../../../../../integration/targets/aci_cloud_provider/tasks/main.yml + +- name: Execute tasks only for non-cloud sites + when: query_cloud.current == [] # This condition will execute only non-cloud sites + block: # block specifies execution of tasks within, based on conditions + # CLEAN ENVIRONMENT + - name: Remove all Access Spine Interface profiles + cisco.aci.aci_access_spine_interface_profile: &aci_access_spine_interface_profile_all_absent + <<: *aci_info + spine_interface_profile: "{{ item }}" + state: absent + loop: + - ansible_access_spine_interface_profile_1 + - ansible_access_spine_interface_profile_2 + + # CREATE ACCESS SPINE INTERFACE PROFILE + - name: Add a new Access Spine Interface Profile (check_mode) + cisco.aci.aci_access_spine_interface_profile: &aci_access_spine_interface_profile_present + <<: *aci_info + spine_interface_profile: ansible_access_spine_interface_profile_1 + description: Access Spine Interface Profile 1 + state: present + check_mode: true + register: cm_add_spine_interface_profile + + - name: Add a new Access Spine Interface Profile (normal_mode) + cisco.aci.aci_access_spine_interface_profile: + <<: *aci_access_spine_interface_profile_present + register: nm_add_spine_interface_profile + + - name: Add the first Access Spine Interface Profile again - testing idempotency + cisco.aci.aci_access_spine_interface_profile: + <<: *aci_access_spine_interface_profile_present + register: nm_add_spine_interface_profile_idempotency + + - name: Add a second Access Spine Interface Profile (normal_mode) + cisco.aci.aci_access_spine_interface_profile: &aci_access_spine_interface_profile_2_present + <<: *aci_info + spine_interface_profile: ansible_access_spine_interface_profile_2 + description: Access Spine Interface Profile 2 + state: present + register: nm_add_spine_interface_profile_2 + + - name: Asserts for Access Spine Interface Profile creation tasks + ansible.builtin.assert: + that: + - cm_add_spine_interface_profile is changed + - cm_add_spine_interface_profile.previous == [] + - cm_add_spine_interface_profile.current == [] + - cm_add_spine_interface_profile.proposed.infraSpAccPortP.attributes.name == "ansible_access_spine_interface_profile_1" + - cm_add_spine_interface_profile.proposed.infraSpAccPortP.attributes.descr == "Access Spine Interface Profile 1" + - nm_add_spine_interface_profile is changed + - nm_add_spine_interface_profile.previous == [] + - nm_add_spine_interface_profile.current.0.infraSpAccPortP.attributes.name == "ansible_access_spine_interface_profile_1" + - nm_add_spine_interface_profile.current.0.infraSpAccPortP.attributes.descr == "Access Spine Interface Profile 1" + - nm_add_spine_interface_profile.current.0.infraSpAccPortP.attributes.dn == "uni/infra/spaccportprof-ansible_access_spine_interface_profile_1" + - nm_add_spine_interface_profile_idempotency is not changed + - nm_add_spine_interface_profile_idempotency.current.0.infraSpAccPortP.attributes.name == "ansible_access_spine_interface_profile_1" + - nm_add_spine_interface_profile_idempotency.current.0.infraSpAccPortP.attributes.descr == "Access Spine Interface Profile 1" + - nm_add_spine_interface_profile_idempotency.current.0.infraSpAccPortP.attributes.dn == "uni/infra/spaccportprof-ansible_access_spine_interface_profile_1" + - nm_add_spine_interface_profile_2 is changed + - nm_add_spine_interface_profile_2.previous == [] + - nm_add_spine_interface_profile_2.current.0.infraSpAccPortP.attributes.name == "ansible_access_spine_interface_profile_2" + - nm_add_spine_interface_profile_2.current.0.infraSpAccPortP.attributes.descr == "Access Spine Interface Profile 2" + - nm_add_spine_interface_profile_2.current.0.infraSpAccPortP.attributes.dn == "uni/infra/spaccportprof-ansible_access_spine_interface_profile_2" + + # QUERY ACCESS SPINE INTERFACE PROFILE + - name: Query all Access Spine Interface Profiles + cisco.aci.aci_access_spine_interface_profile: + <<: *aci_info + state: query + register: query_all_spine_interface_profile + + - name: Query ansible_access_spine_interface_profile_1 + cisco.aci.aci_access_spine_interface_profile: + <<: *aci_access_spine_interface_profile_present + state: query + register: query_ansible_access_spine_interface_profile_1 + + - name: Asserts query tasks + ansible.builtin.assert: + that: + - query_all_spine_interface_profile is not changed + - query_all_spine_interface_profile.current|length >= 2 + - query_ansible_access_spine_interface_profile_1 is not changed + - query_ansible_access_spine_interface_profile_1.current|length == 1 + - query_ansible_access_spine_interface_profile_1.current.0.infraSpAccPortP.attributes.name == "ansible_access_spine_interface_profile_1" + - query_ansible_access_spine_interface_profile_1.current.0.infraSpAccPortP.attributes.descr == "Access Spine Interface Profile 1" + - query_ansible_access_spine_interface_profile_1.current.0.infraSpAccPortP.attributes.dn == "uni/infra/spaccportprof-ansible_access_spine_interface_profile_1" + + # UPDATE ACCESS SPINE INTERFACE PROFILE + - name: Update first Access Spine Interface Profile (check_mode) + cisco.aci.aci_access_spine_interface_profile: &aci_access_spine_interface_profile_update + <<: *aci_access_spine_interface_profile_present + description: Updated description for first ansible Access Spine Interface Profile + check_mode: true + register: cm_update_spine_interface_profile + + - name: Update first Access Spine Interface Profile (normal_mode) + cisco.aci.aci_access_spine_interface_profile: + <<: *aci_access_spine_interface_profile_update + register: nm_update_spine_interface_profile + + - name: Update first Access Spine Interface Profile again - testing idempotency + cisco.aci.aci_access_spine_interface_profile: + <<: *aci_access_spine_interface_profile_update + register: nm_udpate_spine_interface_profile_idempotency + + - name: Asserts for Access Spine Interface Profile update tasks + ansible.builtin.assert: + that: + - cm_update_spine_interface_profile is changed + - cm_update_spine_interface_profile.previous == cm_update_spine_interface_profile.current + - cm_update_spine_interface_profile.proposed.infraSpAccPortP.attributes.descr == "Updated description for first ansible Access Spine Interface Profile" + - nm_update_spine_interface_profile is changed + - nm_update_spine_interface_profile.current.0.infraSpAccPortP.attributes.name == "ansible_access_spine_interface_profile_1" + - nm_update_spine_interface_profile.current.0.infraSpAccPortP.attributes.descr == "Updated description for first ansible Access Spine Interface Profile" + - nm_udpate_spine_interface_profile_idempotency is not changed + - nm_udpate_spine_interface_profile_idempotency.current.0.infraSpAccPortP.attributes.name == "ansible_access_spine_interface_profile_1" + - nm_udpate_spine_interface_profile_idempotency.current.0.infraSpAccPortP.attributes.descr == "Updated description for first ansible Access Spine Interface Profile" + + # DELETE ACCESS SPINE INTERFACE PROFILE + - name: Remove Access Spine Interface Profile (check_mode) + cisco.aci.aci_access_spine_interface_profile: &aci_access_spine_interface_profile_absent + <<: *aci_access_spine_interface_profile_update + state: absent + check_mode: true + register: cm_remove_spine_interface_profile + + - name: Remove Access Spine Interface Profile (normal_mode) + cisco.aci.aci_access_spine_interface_profile: + <<: *aci_access_spine_interface_profile_absent + register: nm_remove_spine_interface_profile + + - name: Remove Access Spine Interface Profile - testing idempotency + cisco.aci.aci_access_spine_interface_profile: + <<: *aci_access_spine_interface_profile_absent + register: nm_remove_spine_interface_profile_idempotency + + - name: Asserts deletion tasks + ansible.builtin.assert: + that: + - cm_remove_spine_interface_profile is changed + - cm_remove_spine_interface_profile.current == cm_remove_spine_interface_profile.previous + - cm_remove_spine_interface_profile.proposed == {} + - nm_remove_spine_interface_profile is changed + - nm_remove_spine_interface_profile.previous != [] + - nm_remove_spine_interface_profile.proposed == {} + - nm_remove_spine_interface_profile.current == [] + - nm_remove_spine_interface_profile_idempotency is not changed + - nm_remove_spine_interface_profile_idempotency.previous == [] + - nm_remove_spine_interface_profile_idempotency.current == [] + + # CLEAN ENVIRONMENT BEFORE ENDING TESTS + - name: Remove all Access Spine Interface profiles - cleanup before ending tests + cisco.aci.aci_access_spine_interface_profile: + <<: *aci_access_spine_interface_profile_all_absent + loop: + - ansible_access_spine_interface_profile_1 + - ansible_access_spine_interface_profile_2 diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_access_spine_interface_profile_to_spine_switch_profile/aliases b/ansible_collections/cisco/aci/tests/integration/targets/aci_access_spine_interface_profile_to_spine_switch_profile/aliases new file mode 100644 index 000000000..209b793f9 --- /dev/null +++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_access_spine_interface_profile_to_spine_switch_profile/aliases @@ -0,0 +1,2 @@ +# No ACI simulator yet, so not enabled +# unsupported diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_access_spine_interface_profile_to_spine_switch_profile/tasks/main.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_access_spine_interface_profile_to_spine_switch_profile/tasks/main.yml new file mode 100644 index 000000000..00f3b48fe --- /dev/null +++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_access_spine_interface_profile_to_spine_switch_profile/tasks/main.yml @@ -0,0 +1,176 @@ +# Test code for the ACI modules +# Copyright: (c) 2023, Eric Girard <@netgirard> +# Copyright: (c) 2024, Gaspard Micol (@gmicol) + +# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) + +- name: Test that we have an ACI APIC host, ACI username and ACI password + ansible.builtin.fail: + msg: 'Please define the following variables: aci_hostname, aci_username and aci_password.' + when: aci_hostname is not defined or aci_username is not defined or aci_password is not defined + +- name: Set vars + ansible.builtin.set_fact: + aci_info: &aci_info + host: "{{ aci_hostname }}" + username: "{{ aci_username }}" + password: "{{ aci_password }}" + validate_certs: '{{ aci_validate_certs | default(false) }}' + use_ssl: '{{ aci_use_ssl | default(true) }}' + use_proxy: '{{ aci_use_proxy | default(true) }}' + output_level: '{{ aci_output_level | default("info") }}' + +- name: Verify Cloud and Non-Cloud Sites in use. + ansible.builtin.include_tasks: ../../../../../../integration/targets/aci_cloud_provider/tasks/main.yml + +- name: Execute tasks only for non-cloud sites + when: query_cloud.current == [] # This condition will execute only non-cloud sites + block: # block specifies execution of tasks within, based on conditions + # CLEAN ENVIRONMENT + - name: Remove Access Spine Switch profile + cisco.aci.aci_access_spine_switch_profile: &aci_access_spine_switch_profile_absent + <<: *aci_info + spine_switch_profile: ansible_access_spine_switch_profile + state: absent + + - name: Remove all Access Spine Interface Profiles + cisco.aci.aci_access_spine_interface_profile: &aci_access_spine_interface_profile_all_absent + <<: *aci_info + spine_interface_profile: "{{ item }}" + state: absent + loop: + - ansible_access_spine_interface_profile_1 + - ansible_access_spine_interface_profile_2 + + # CREATE ACCESS SPINE SWITCH AND INTERFACE PROFILES + - name: Add Access Spine Switch profile + cisco.aci.aci_access_spine_switch_profile: + <<: *aci_access_spine_switch_profile_absent + state: present + + - name: Add Access Spine Interface Profiles + cisco.aci.aci_access_spine_interface_profile: + <<: *aci_access_spine_interface_profile_all_absent + state: present + loop: + - ansible_access_spine_interface_profile_1 + - ansible_access_spine_interface_profile_2 + + # CREATE BINDING BETWEEN SPINE INTERFACE AND SWITCH PROFILES + - name: Add a new Binding between Spine Interface and Switch Profiles (check_mode) + cisco.aci.aci_access_spine_interface_profile_to_spine_switch_profile: &aci_access_spine_interface_profile_to_spine_switch_profile_present + <<: *aci_info + spine_switch_profile: ansible_access_spine_switch_profile + spine_interface_profile: ansible_access_spine_interface_profile_1 + state: present + check_mode: true + register: cm_add_binding_spine_interface_to_switch + + - name: Add a new Binding between Spine Interface and Switch Profiles (normal_mode) + cisco.aci.aci_access_spine_interface_profile_to_spine_switch_profile: + <<: *aci_access_spine_interface_profile_to_spine_switch_profile_present + register: nm_add_binding_spine_interface_to_switch + + - name: Add the first Binding between Spine Interface and Switch Profiles again - testing idempotency + cisco.aci.aci_access_spine_interface_profile_to_spine_switch_profile: + <<: *aci_access_spine_interface_profile_to_spine_switch_profile_present + register: nm_add_binding_spine_interface_to_switch_idempotency + + - name: Add a second Binding between Spine Interface and Switch Profiles (normal_mode) + cisco.aci.aci_access_spine_interface_profile_to_spine_switch_profile: &aci_access_spine_interface_profile_to_spine_switch_profile_2_present + <<: *aci_info + spine_switch_profile: ansible_access_spine_switch_profile + spine_interface_profile: ansible_access_spine_interface_profile_2 + state: present + register: nm_add_binding_spine_interface_to_switch_2 + + - name: Asserts for Binding between Spine Interface and Switch Profiles creation tasks + ansible.builtin.assert: + that: + - cm_add_binding_spine_interface_to_switch is changed + - cm_add_binding_spine_interface_to_switch.previous == [] + - cm_add_binding_spine_interface_to_switch.current == [] + - cm_add_binding_spine_interface_to_switch.proposed.infraRsSpAccPortP.attributes.dn == "uni/infra/spprof-ansible_access_spine_switch_profile/rsspAccPortP-[uni/infra/spaccportprof-ansible_access_spine_interface_profile_1]" + - cm_add_binding_spine_interface_to_switch.proposed.infraRsSpAccPortP.attributes.tDn == "uni/infra/spaccportprof-ansible_access_spine_interface_profile_1" + - nm_add_binding_spine_interface_to_switch is changed + - nm_add_binding_spine_interface_to_switch.previous == [] + - nm_add_binding_spine_interface_to_switch.current.0.infraRsSpAccPortP.attributes.dn == "uni/infra/spprof-ansible_access_spine_switch_profile/rsspAccPortP-[uni/infra/spaccportprof-ansible_access_spine_interface_profile_1]" + - nm_add_binding_spine_interface_to_switch.current.0.infraRsSpAccPortP.attributes.tDn == "uni/infra/spaccportprof-ansible_access_spine_interface_profile_1" + - nm_add_binding_spine_interface_to_switch_idempotency is not changed + - nm_add_binding_spine_interface_to_switch_idempotency.current.0.infraRsSpAccPortP.attributes.dn == "uni/infra/spprof-ansible_access_spine_switch_profile/rsspAccPortP-[uni/infra/spaccportprof-ansible_access_spine_interface_profile_1]" + - nm_add_binding_spine_interface_to_switch_idempotency.current.0.infraRsSpAccPortP.attributes.tDn == "uni/infra/spaccportprof-ansible_access_spine_interface_profile_1" + - nm_add_binding_spine_interface_to_switch_2 is changed + - nm_add_binding_spine_interface_to_switch_2.previous == [] + - nm_add_binding_spine_interface_to_switch_2.proposed.infraRsSpAccPortP.attributes.dn == "uni/infra/spprof-ansible_access_spine_switch_profile/rsspAccPortP-[uni/infra/spaccportprof-ansible_access_spine_interface_profile_2]" + - nm_add_binding_spine_interface_to_switch_2.proposed.infraRsSpAccPortP.attributes.tDn == "uni/infra/spaccportprof-ansible_access_spine_interface_profile_2" + - nm_add_binding_spine_interface_to_switch_2.current.0.infraRsSpAccPortP.attributes.dn == "uni/infra/spprof-ansible_access_spine_switch_profile/rsspAccPortP-[uni/infra/spaccportprof-ansible_access_spine_interface_profile_2]" + - nm_add_binding_spine_interface_to_switch_2.current.0.infraRsSpAccPortP.attributes.tDn == "uni/infra/spaccportprof-ansible_access_spine_interface_profile_2" + + # QUERY BINDING BETWEEN SPINE INTERFACE AND SWITCH PROFILES + - name: Query all Binding between Spine Interface Profiles and ansible_access_spine_switch_profile + cisco.aci.aci_access_spine_interface_profile_to_spine_switch_profile: + <<: *aci_info + spine_switch_profile: ansible_access_spine_switch_profile + state: query + register: query_all_binding_spine_interface_to_switch + + - name: Query Binding ansible_access_spine_interface_profile_1 to ansible_access_spine_switch_profile + cisco.aci.aci_access_spine_interface_profile_to_spine_switch_profile: + <<: *aci_access_spine_interface_profile_to_spine_switch_profile_present + state: query + register: query_binding_spine_interface_to_switch + + - name: Asserts query tasks + ansible.builtin.assert: + that: + - query_all_binding_spine_interface_to_switch is not changed + - query_all_binding_spine_interface_to_switch.current.0.infraSpineP.children|length >= 2 + - query_binding_spine_interface_to_switch is not changed + - query_binding_spine_interface_to_switch.current.0.infraSpineP.children|length == 1 + - query_binding_spine_interface_to_switch.current.0.infraSpineP.children.0.infraRsSpAccPortP.attributes.rn == "rsspAccPortP-[uni/infra/spaccportprof-ansible_access_spine_interface_profile_1]" + - query_binding_spine_interface_to_switch.current.0.infraSpineP.children.0.infraRsSpAccPortP.attributes.tDn == "uni/infra/spaccportprof-ansible_access_spine_interface_profile_1" + - query_binding_spine_interface_to_switch.current.0.infraSpineP.children.0.infraRsSpAccPortP.attributes.state == "formed" + + # DELETE BINDING BETWEEN SPINE INTERFACE AND SWITCH PROFILES + - name: Remove Binding between Spine Interface and Switch Profiles (check_mode) + cisco.aci.aci_access_spine_interface_profile_to_spine_switch_profile: &aci_access_spine_interface_profile_to_spine_switch_profile_absent + <<: *aci_access_spine_interface_profile_to_spine_switch_profile_present + state: absent + check_mode: true + register: cm_remove_binding_spine_interface_to_switch + + - name: Remove Binding between Spine Interface and Switch Profiles (normal_mode) + cisco.aci.aci_access_spine_interface_profile_to_spine_switch_profile: + <<: *aci_access_spine_interface_profile_to_spine_switch_profile_absent + register: nm_remove_binding_spine_interface_to_switch + + - name: Remove Binding between Spine Interface and Switch Profiles - testing idempotency + cisco.aci.aci_access_spine_interface_profile_to_spine_switch_profile: + <<: *aci_access_spine_interface_profile_to_spine_switch_profile_absent + register: nm_remove_binding_spine_interface_to_switch_idempotency + + - name: Asserts deletion tasks + ansible.builtin.assert: + that: + - cm_remove_binding_spine_interface_to_switch is changed + - cm_remove_binding_spine_interface_to_switch.current == cm_remove_binding_spine_interface_to_switch.previous + - cm_remove_binding_spine_interface_to_switch.proposed == {} + - nm_remove_binding_spine_interface_to_switch is changed + - nm_remove_binding_spine_interface_to_switch.previous != [] + - nm_remove_binding_spine_interface_to_switch.proposed == {} + - nm_remove_binding_spine_interface_to_switch.current == [] + - nm_remove_binding_spine_interface_to_switch_idempotency is not changed + - nm_remove_binding_spine_interface_to_switch_idempotency.previous == [] + - nm_remove_binding_spine_interface_to_switch_idempotency.current == [] + + # CLEAN ENVIRONMENT BEFORE ENDING TESTS + - name: Remove Access Spine Switch profile - cleanup before ending tests + cisco.aci.aci_access_spine_interface_profile: + <<: *aci_access_spine_interface_profile_all_absent + loop: + - ansible_access_spine_interface_profile_1 + - ansible_access_spine_interface_profile_2 + + - name: Remove all Access Spine Interface Profiles - cleanup before ending tests + cisco.aci.aci_access_spine_switch_profile: + <<: *aci_access_spine_switch_profile_absent diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_access_spine_interface_selector/aliases b/ansible_collections/cisco/aci/tests/integration/targets/aci_access_spine_interface_selector/aliases new file mode 100644 index 000000000..209b793f9 --- /dev/null +++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_access_spine_interface_selector/aliases @@ -0,0 +1,2 @@ +# No ACI simulator yet, so not enabled +# unsupported diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_access_spine_interface_selector/tasks/main.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_access_spine_interface_selector/tasks/main.yml new file mode 100644 index 000000000..255357168 --- /dev/null +++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_access_spine_interface_selector/tasks/main.yml @@ -0,0 +1,204 @@ +# Test code for the ACI modules +# Copyright: (c) 2024, Gaspard Micol (@gmicol) + +# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) + +- name: Test that we have an ACI APIC host, ACI username and ACI password + ansible.builtin.fail: + msg: 'Please define the following variables: aci_hostname, aci_username and aci_password.' + when: aci_hostname is not defined or aci_username is not defined or aci_password is not defined + +- name: Set vars + ansible.builtin.set_fact: + aci_info: &aci_info + host: "{{ aci_hostname }}" + username: "{{ aci_username }}" + password: "{{ aci_password }}" + validate_certs: '{{ aci_validate_certs | default(false) }}' + use_ssl: '{{ aci_use_ssl | default(true) }}' + use_proxy: '{{ aci_use_proxy | default(true) }}' + output_level: '{{ aci_output_level | default("info") }}' + +- name: Verify Cloud and Non-Cloud Sites in use. + ansible.builtin.include_tasks: ../../../../../../integration/targets/aci_cloud_provider/tasks/main.yml + +- name: Execute tasks only for non-cloud sites + when: query_cloud.current == [] # This condition will execute only non-cloud sites + block: # block specifies execution of tasks within, based on conditions + # CLEAN ENVIRONMENT + - name: Remove the ansible_access_spine_interface_profile + cisco.aci.aci_access_spine_interface_profile: &aci_access_spine_interface_profile_absent + <<: *aci_info + spine_interface_profile: ansible_access_spine_interface_profile + description: Ansible Access Spine Interface Profile + state: absent + + - name: Add a new Access Spine Interface profile + cisco.aci.aci_access_spine_interface_profile: &aci_access_spine_interface_profile_present + <<: *aci_access_spine_interface_profile_absent + state: present + + # CREATE ACCESS SPINE INTERFACE SELECTOR + - name: Add a new Access Spine Interface Selector (check_mode) + cisco.aci.aci_access_spine_interface_selector: &aci_access_spine_interface_selector_present + <<: *aci_info + spine_interface_profile: ansible_access_spine_interface_profile + spine_interface_selector: ansible_access_spine_interface_selector_1 + description: Access Spine Interface Selector 1 + selector_type: range + state: present + check_mode: true + register: cm_add_spine_interface_selector + + - name: Add a new Access Spine Interface Selector (normal_mode) + cisco.aci.aci_access_spine_interface_selector: + <<: *aci_access_spine_interface_selector_present + register: nm_add_spine_interface_selector + + - name: Add the first Access Spine Interface Selector again - testing idempotency + cisco.aci.aci_access_spine_interface_selector: + <<: *aci_access_spine_interface_selector_present + register: nm_add_spine_interface_selector_idempotency + + - name: Add a second Access Spine Interface Selector (normal_mode) + cisco.aci.aci_access_spine_interface_selector: &aci_access_spine_interface_selector_2_present + <<: *aci_info + spine_interface_profile: ansible_access_spine_interface_profile + spine_interface_selector: ansible_access_spine_interface_selector_2 + description: Access Spine Interface Selector 2 + selector_type: range + state: present + register: nm_add_spine_interface_selector_2 + + - name: Asserts for Access Spine Interface Selector creation tasks + ansible.builtin.assert: + that: + - cm_add_spine_interface_selector is changed + - cm_add_spine_interface_selector.previous == [] + - cm_add_spine_interface_selector.current == [] + - cm_add_spine_interface_selector.proposed.infraSHPortS.attributes.name == "ansible_access_spine_interface_selector_1" + - cm_add_spine_interface_selector.proposed.infraSHPortS.attributes.descr == "Access Spine Interface Selector 1" + - cm_add_spine_interface_selector.proposed.infraSHPortS.attributes.type == "range" + - nm_add_spine_interface_selector is changed + - nm_add_spine_interface_selector.previous == [] + - nm_add_spine_interface_selector.current.0.infraSHPortS.attributes.name == "ansible_access_spine_interface_selector_1" + - nm_add_spine_interface_selector.current.0.infraSHPortS.attributes.descr == "Access Spine Interface Selector 1" + - nm_add_spine_interface_selector.current.0.infraSHPortS.attributes.type == "range" + - nm_add_spine_interface_selector_idempotency is not changed + - nm_add_spine_interface_selector_idempotency.current.0.infraSHPortS.attributes.name == "ansible_access_spine_interface_selector_1" + - nm_add_spine_interface_selector_idempotency.current.0.infraSHPortS.attributes.descr == "Access Spine Interface Selector 1" + - nm_add_spine_interface_selector_idempotency.current.0.infraSHPortS.attributes.type == "range" + - nm_add_spine_interface_selector_2 is changed + - nm_add_spine_interface_selector_2.previous == [] + - nm_add_spine_interface_selector_2.current.0.infraSHPortS.attributes.name == "ansible_access_spine_interface_selector_2" + - nm_add_spine_interface_selector_2.current.0.infraSHPortS.attributes.descr == "Access Spine Interface Selector 2" + - nm_add_spine_interface_selector_2.current.0.infraSHPortS.attributes.type == "range" + + # QUERY ACCESS SPINE INTERFACE SELECTOR + - name: Query all Access Spine Interface Selectors + cisco.aci.aci_access_spine_interface_selector: + <<: *aci_info + state: query + register: query_all_spine_interface_selector + + - name: Query ansible_access_spine_interface_selector_1 + cisco.aci.aci_access_spine_interface_selector: + <<: *aci_access_spine_interface_selector_present + state: query + register: query_ansible_access_spine_interface_selector_1 + + - name: Asserts query tasks + ansible.builtin.assert: + that: + - query_all_spine_interface_selector is not changed + - query_all_spine_interface_selector.current|length >= 2 + - query_ansible_access_spine_interface_selector_1 is not changed + - query_ansible_access_spine_interface_selector_1.current|length == 1 + - query_ansible_access_spine_interface_selector_1.current.0.infraSpAccPortP.children.0.infraSHPortS.attributes.name == "ansible_access_spine_interface_selector_1" + - query_ansible_access_spine_interface_selector_1.current.0.infraSpAccPortP.children.0.infraSHPortS.attributes.descr == "Access Spine Interface Selector 1" + - query_ansible_access_spine_interface_selector_1.current.0.infraSpAccPortP.children.0.infraSHPortS.attributes.type == "range" + + # UPDATE ACCESS SPINE INTERFACE SELECTOR + - name: Add a new Access Spine Interface policy Group + cisco.aci.aci_interface_policy_spine_policy_group: &aci_interface_policy_spine_policy_group_present + <<: *aci_info + policy_group: ansible_access_spine_interface_policy_group + description: Ansible Access Spine Interface Policy Group + state: present + + - name: Update first Access Spine Interface Selector by adding a Policy Group (check_mode) + cisco.aci.aci_access_spine_interface_selector: &aci_access_spine_interface_selector_update + <<: *aci_access_spine_interface_selector_present + description: Updated description for first ansible Access Spine Interface Selector + policy_group: ansible_access_spine_interface_policy_group + check_mode: true + register: cm_update_spine_interface_selector + + - name: Update first Access Spine Interface Selector by adding a Policy Group (normal_mode) + cisco.aci.aci_access_spine_interface_selector: + <<: *aci_access_spine_interface_selector_update + register: nm_update_spine_interface_selector + + - name: Update first Access Spine Interface Selector by adding a Policy Group again - testing idempotency + cisco.aci.aci_access_spine_interface_selector: + <<: *aci_access_spine_interface_selector_update + register: nm_udpate_spine_interface_selector_idempotency + + - name: Asserts for Access Spine Interface Selector update tasks + ansible.builtin.assert: + that: + - cm_update_spine_interface_selector is changed + - cm_update_spine_interface_selector.previous == cm_update_spine_interface_selector.current + - cm_update_spine_interface_selector.proposed.infraSHPortS.attributes.descr == "Updated description for first ansible Access Spine Interface Selector" + - cm_update_spine_interface_selector.proposed.infraSHPortS.children.0.infraRsSpAccGrp.attributes.tDn == "uni/infra/funcprof/spaccportgrp-ansible_access_spine_interface_policy_group" + - nm_update_spine_interface_selector is changed + - nm_update_spine_interface_selector.current.0.infraSHPortS.attributes.name == "ansible_access_spine_interface_selector_1" + - nm_update_spine_interface_selector.current.0.infraSHPortS.attributes.descr == "Updated description for first ansible Access Spine Interface Selector" + - nm_update_spine_interface_selector.current.0.infraSHPortS.children.0.infraRsSpAccGrp.attributes.tDn == "uni/infra/funcprof/spaccportgrp-ansible_access_spine_interface_policy_group" + - nm_udpate_spine_interface_selector_idempotency is not changed + - nm_udpate_spine_interface_selector_idempotency.current.0.infraSHPortS.attributes.name == "ansible_access_spine_interface_selector_1" + - nm_udpate_spine_interface_selector_idempotency.current.0.infraSHPortS.attributes.descr == "Updated description for first ansible Access Spine Interface Selector" + - nm_udpate_spine_interface_selector_idempotency.current.0.infraSHPortS.children.0.infraRsSpAccGrp.attributes.tDn == "uni/infra/funcprof/spaccportgrp-ansible_access_spine_interface_policy_group" + + # DELETE ACCESS SPINE INTERFACE SELECTOR + - name: Remove Access Spine Interface Selector (check_mode) + cisco.aci.aci_access_spine_interface_selector: &spine_interface_selector_absent + <<: *aci_access_spine_interface_selector_update + state: absent + check_mode: true + register: cm_remove_spine_interface_selector + + - name: Remove Access Spine Interface Selector (normal_mode) + cisco.aci.aci_access_spine_interface_selector: + <<: *spine_interface_selector_absent + register: nm_remove_spine_interface_selector + + - name: Remove Access Spine Interface Selector - testing idempotency + cisco.aci.aci_access_spine_interface_selector: + <<: *spine_interface_selector_absent + register: nm_remove_spine_interface_selector_idempotency + + - name: Asserts deletion tasks + ansible.builtin.assert: + that: + - cm_remove_spine_interface_selector is changed + - cm_remove_spine_interface_selector.current == cm_remove_spine_interface_selector.previous + - cm_remove_spine_interface_selector.proposed == {} + - nm_remove_spine_interface_selector is changed + - nm_remove_spine_interface_selector.previous != [] + - nm_remove_spine_interface_selector.proposed == {} + - nm_remove_spine_interface_selector.current == [] + - nm_remove_spine_interface_selector_idempotency is not changed + - nm_remove_spine_interface_selector_idempotency.previous == [] + - nm_remove_spine_interface_selector_idempotency.current == [] + + # CLEAN ENVIRONMENT BEFORE ENDING TESTS + - name: Remove the Access Spine Interface profile - cleanup before ending tests + cisco.aci.aci_access_spine_interface_profile: + <<: *aci_access_spine_interface_profile_present + state: absent + + - name: Remove the Spine Interface policy Group - cleanup before ending tests + cisco.aci.aci_interface_policy_spine_policy_group: + <<: *aci_interface_policy_spine_policy_group_present + state: absent diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_access_spine_switch_profile/aliases b/ansible_collections/cisco/aci/tests/integration/targets/aci_access_spine_switch_profile/aliases new file mode 100644 index 000000000..209b793f9 --- /dev/null +++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_access_spine_switch_profile/aliases @@ -0,0 +1,2 @@ +# No ACI simulator yet, so not enabled +# unsupported diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_access_spine_switch_profile/tasks/main.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_access_spine_switch_profile/tasks/main.yml new file mode 100644 index 000000000..cf940fcbb --- /dev/null +++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_access_spine_switch_profile/tasks/main.yml @@ -0,0 +1,183 @@ +# Test code for the ACI modules +# Copyright: (c) 2023, Eric Girard <@netgirard> +# Copyright: (c) 2024, Gaspard Micol (@gmicol) + +# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) + +- name: Test that we have an ACI APIC host, ACI username and ACI password + ansible.builtin.fail: + msg: 'Please define the following variables: aci_hostname, aci_username and aci_password.' + when: aci_hostname is not defined or aci_username is not defined or aci_password is not defined + +- name: Set vars + ansible.builtin.set_fact: + aci_info: &aci_info + host: "{{ aci_hostname }}" + username: "{{ aci_username }}" + password: "{{ aci_password }}" + validate_certs: '{{ aci_validate_certs | default(false) }}' + use_ssl: '{{ aci_use_ssl | default(true) }}' + use_proxy: '{{ aci_use_proxy | default(true) }}' + output_level: '{{ aci_output_level | default("info") }}' + +- name: Verify Cloud and Non-Cloud Sites in use. + ansible.builtin.include_tasks: ../../../../../../integration/targets/aci_cloud_provider/tasks/main.yml + +- name: Execute tasks only for non-cloud sites + when: query_cloud.current == [] # This condition will execute only non-cloud sites + block: # block specifies execution of tasks within, based on conditions + # CLEAN ENVIRONMENT + - name: Remove all Access Spine Switch profiles + cisco.aci.aci_access_spine_switch_profile: &aci_access_spine_switch_profile_all_absent + <<: *aci_info + spine_switch_profile: "{{ item }}" + state: absent + loop: + - ansible_access_spine_switch_profile_1 + - ansible_access_spine_switch_profile_2 + + # CREATE ACCESS SPINE SWITCH PROFILE + - name: Add a new Access Spine Switch Profile (check_mode) + cisco.aci.aci_access_spine_switch_profile: &aci_access_spine_switch_profile_present + <<: *aci_info + spine_switch_profile: ansible_access_spine_switch_profile_1 + description: Access Spine Switch Profile 1 + state: present + check_mode: true + register: cm_add_spine_switch_profile + + - name: Add a new Access Spine Switch Profile (normal_mode) + cisco.aci.aci_access_spine_switch_profile: + <<: *aci_access_spine_switch_profile_present + register: nm_add_spine_switch_profile + + - name: Add the first Access Spine Switch Profile again - testing idempotency + cisco.aci.aci_access_spine_switch_profile: + <<: *aci_access_spine_switch_profile_present + register: nm_add_spine_switch_profile_idempotency + + - name: Add a second Access Spine Switch Profile (normal_mode) + cisco.aci.aci_access_spine_switch_profile: &aci_access_spine_switch_profile_2_present + <<: *aci_info + spine_switch_profile: ansible_access_spine_switch_profile_2 + description: Access Spine Switch Profile 2 + state: present + register: nm_add_spine_switch_profile_2 + + - name: Asserts for Access Spine Switch Profile creation tasks + ansible.builtin.assert: + that: + - cm_add_spine_switch_profile is changed + - cm_add_spine_switch_profile.previous == [] + - cm_add_spine_switch_profile.current == [] + - cm_add_spine_switch_profile.proposed.infraSpineP.attributes.name == "ansible_access_spine_switch_profile_1" + - cm_add_spine_switch_profile.proposed.infraSpineP.attributes.descr == "Access Spine Switch Profile 1" + - nm_add_spine_switch_profile is changed + - nm_add_spine_switch_profile.previous == [] + - nm_add_spine_switch_profile.current.0.infraSpineP.attributes.name == "ansible_access_spine_switch_profile_1" + - nm_add_spine_switch_profile.current.0.infraSpineP.attributes.descr == "Access Spine Switch Profile 1" + - nm_add_spine_switch_profile.current.0.infraSpineP.attributes.dn == "uni/infra/spprof-ansible_access_spine_switch_profile_1" + - nm_add_spine_switch_profile_idempotency is not changed + - nm_add_spine_switch_profile_idempotency.current.0.infraSpineP.attributes.name == "ansible_access_spine_switch_profile_1" + - nm_add_spine_switch_profile_idempotency.current.0.infraSpineP.attributes.descr == "Access Spine Switch Profile 1" + - nm_add_spine_switch_profile_idempotency.current.0.infraSpineP.attributes.dn == "uni/infra/spprof-ansible_access_spine_switch_profile_1" + - nm_add_spine_switch_profile_2 is changed + - nm_add_spine_switch_profile_2.previous == [] + - nm_add_spine_switch_profile_2.current.0.infraSpineP.attributes.name == "ansible_access_spine_switch_profile_2" + - nm_add_spine_switch_profile_2.current.0.infraSpineP.attributes.descr == "Access Spine Switch Profile 2" + - nm_add_spine_switch_profile_2.current.0.infraSpineP.attributes.dn == "uni/infra/spprof-ansible_access_spine_switch_profile_2" + + # QUERY ACCESS SPINE SWITCH PROFILE + - name: Query all Access Spine Switch Profiles + cisco.aci.aci_access_spine_switch_profile: + <<: *aci_info + state: query + register: query_all_spine_switch_profile + + - name: Query ansible_access_spine_switch_profile_1 + cisco.aci.aci_access_spine_switch_profile: + <<: *aci_access_spine_switch_profile_present + state: query + register: query_ansible_access_spine_switch_profile_1 + + - name: Asserts query tasks + ansible.builtin.assert: + that: + - query_all_spine_switch_profile is not changed + - query_all_spine_switch_profile.current|length >= 2 + - query_ansible_access_spine_switch_profile_1 is not changed + - query_ansible_access_spine_switch_profile_1.current|length == 1 + - query_ansible_access_spine_switch_profile_1.current.0.infraSpineP.attributes.name == "ansible_access_spine_switch_profile_1" + - query_ansible_access_spine_switch_profile_1.current.0.infraSpineP.attributes.descr == "Access Spine Switch Profile 1" + - query_ansible_access_spine_switch_profile_1.current.0.infraSpineP.attributes.dn == "uni/infra/spprof-ansible_access_spine_switch_profile_1" + + # UPDATE ACCESS SPINE SWITCH PROFILE + - name: Update first Access Spine Switch Profile (check_mode) + cisco.aci.aci_access_spine_switch_profile: &aci_access_spine_switch_profile_update + <<: *aci_access_spine_switch_profile_present + description: Updated description for first ansible Access Spine Switch Profile + check_mode: true + register: cm_update_spine_switch_profile + + - name: Update first Access Spine Switch Profile (normal_mode) + cisco.aci.aci_access_spine_switch_profile: + <<: *aci_access_spine_switch_profile_update + register: nm_update_spine_switch_profile + + - name: Update first Access Spine Switch Profile again - testing idempotency + cisco.aci.aci_access_spine_switch_profile: + <<: *aci_access_spine_switch_profile_update + register: nm_udpate_spine_switch_profile_idempotency + + - name: Asserts for Access Spine Switch Profile update tasks + ansible.builtin.assert: + that: + - cm_update_spine_switch_profile is changed + - cm_update_spine_switch_profile.previous == cm_update_spine_switch_profile.current + - cm_update_spine_switch_profile.proposed.infraSpineP.attributes.descr == "Updated description for first ansible Access Spine Switch Profile" + - nm_update_spine_switch_profile is changed + - nm_update_spine_switch_profile.current.0.infraSpineP.attributes.name == "ansible_access_spine_switch_profile_1" + - nm_update_spine_switch_profile.current.0.infraSpineP.attributes.descr == "Updated description for first ansible Access Spine Switch Profile" + - nm_udpate_spine_switch_profile_idempotency is not changed + - nm_udpate_spine_switch_profile_idempotency.current.0.infraSpineP.attributes.name == "ansible_access_spine_switch_profile_1" + - nm_udpate_spine_switch_profile_idempotency.current.0.infraSpineP.attributes.descr == "Updated description for first ansible Access Spine Switch Profile" + + # DELETE ACCESS SPINE SWITCH PROFILE + - name: Remove Access Spine Switch Profile (check_mode) + cisco.aci.aci_access_spine_switch_profile: &aci_access_spine_switch_profile_absent + <<: *aci_access_spine_switch_profile_update + state: absent + check_mode: true + register: cm_remove_spine_switch_profile + + - name: Remove Access Spine Switch Profile (normal_mode) + cisco.aci.aci_access_spine_switch_profile: + <<: *aci_access_spine_switch_profile_absent + register: nm_remove_spine_switch_profile + + - name: Remove Access Spine Switch Profile - testing idempotency + cisco.aci.aci_access_spine_switch_profile: + <<: *aci_access_spine_switch_profile_absent + register: nm_remove_spine_switch_profile_idempotency + + - name: Asserts deletion tasks + ansible.builtin.assert: + that: + - cm_remove_spine_switch_profile is changed + - cm_remove_spine_switch_profile.current == cm_remove_spine_switch_profile.previous + - cm_remove_spine_switch_profile.proposed == {} + - nm_remove_spine_switch_profile is changed + - nm_remove_spine_switch_profile.previous != [] + - nm_remove_spine_switch_profile.proposed == {} + - nm_remove_spine_switch_profile.current == [] + - nm_remove_spine_switch_profile_idempotency is not changed + - nm_remove_spine_switch_profile_idempotency.previous == [] + - nm_remove_spine_switch_profile_idempotency.current == [] + + # CLEAN ENVIRONMENT BEFORE ENDING TESTS + - name: Remove all Access Spine Switch profiles - cleanup before ending tests + cisco.aci.aci_access_spine_switch_profile: + <<: *aci_access_spine_switch_profile_all_absent + loop: + - ansible_access_spine_switch_profile_1 + - ansible_access_spine_switch_profile_2 diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_access_spine_switch_selector/aliases b/ansible_collections/cisco/aci/tests/integration/targets/aci_access_spine_switch_selector/aliases new file mode 100644 index 000000000..209b793f9 --- /dev/null +++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_access_spine_switch_selector/aliases @@ -0,0 +1,2 @@ +# No ACI simulator yet, so not enabled +# unsupported diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_access_spine_switch_selector/tasks/main.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_access_spine_switch_selector/tasks/main.yml new file mode 100644 index 000000000..1d314ec0e --- /dev/null +++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_access_spine_switch_selector/tasks/main.yml @@ -0,0 +1,193 @@ +# Test code for the ACI modules +# Copyright: (c) 2023, Eric Girard <@netgirard> +# Copyright: (c) 2024, Gaspard Micol (@gmicol) + +# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) + +- name: Test that we have an ACI APIC host, ACI username and ACI password + ansible.builtin.fail: + msg: 'Please define the following variables: aci_hostname, aci_username and aci_password.' + when: aci_hostname is not defined or aci_username is not defined or aci_password is not defined + +- name: Set vars + ansible.builtin.set_fact: + aci_info: &aci_info + host: "{{ aci_hostname }}" + username: "{{ aci_username }}" + password: "{{ aci_password }}" + validate_certs: '{{ aci_validate_certs | default(false) }}' + use_ssl: '{{ aci_use_ssl | default(true) }}' + use_proxy: '{{ aci_use_proxy | default(true) }}' + output_level: '{{ aci_output_level | default("info") }}' + +- name: Verify Cloud and Non-Cloud Sites in use. + ansible.builtin.include_tasks: ../../../../../../integration/targets/aci_cloud_provider/tasks/main.yml + +- name: Execute tasks only for non-cloud sites + when: query_cloud.current == [] # This condition will execute only non-cloud sites + block: # block specifies execution of tasks within, based on conditions + # CLEAN ENVIRONMENT + - name: Remove the ansible_access_spine_switch_profile + cisco.aci.aci_access_spine_switch_profile: &aci_access_spine_switch_profile_absent + <<: *aci_info + spine_switch_profile: ansible_access_spine_switch_profile + description: Ansible Access Spine Switch Profile + state: absent + + - name: Add a new Access Spine Switch profile + cisco.aci.aci_access_spine_switch_profile: &aci_access_spine_switch_profile_present + <<: *aci_access_spine_switch_profile_absent + state: present + + # CREATE ACCESS SPINE SWITCH SELECTOR + - name: Add a new Access Spine Switch Selector (check_mode) + cisco.aci.aci_access_spine_switch_selector: &aci_access_spine_switch_selector_present + <<: *aci_info + spine_switch_profile: ansible_access_spine_switch_profile + spine_switch_selector: ansible_access_spine_switch_selector_1 + description: Access Spine Switch Selector 1 + selector_type: range + state: present + check_mode: true + register: cm_add_spine_switch_selector + + - name: Add a new Access Spine Switch Selector (normal_mode) + cisco.aci.aci_access_spine_switch_selector: + <<: *aci_access_spine_switch_selector_present + register: nm_add_spine_switch_selector + + - name: Add the first Access Spine Switch Selector again - testing idempotency + cisco.aci.aci_access_spine_switch_selector: + <<: *aci_access_spine_switch_selector_present + register: nm_add_spine_switch_selector_idempotency + + - name: Add a second Access Spine Switch Selector (normal_mode) + cisco.aci.aci_access_spine_switch_selector: &aci_access_spine_switch_selector_2_present + <<: *aci_info + spine_switch_profile: ansible_access_spine_switch_profile + spine_switch_selector: ansible_access_spine_switch_selector_2 + description: Access Spine Switch Selector 2 + selector_type: range + state: present + register: nm_add_spine_switch_selector_2 + + - name: Asserts for Access Spine Switch Selector creation tasks + ansible.builtin.assert: + that: + - cm_add_spine_switch_selector is changed + - cm_add_spine_switch_selector.previous == [] + - cm_add_spine_switch_selector.current == [] + - cm_add_spine_switch_selector.proposed.infraSpineS.attributes.name == "ansible_access_spine_switch_selector_1" + - cm_add_spine_switch_selector.proposed.infraSpineS.attributes.descr == "Access Spine Switch Selector 1" + - cm_add_spine_switch_selector.proposed.infraSpineS.attributes.type == "range" + - nm_add_spine_switch_selector is changed + - nm_add_spine_switch_selector.previous == [] + - nm_add_spine_switch_selector.current.0.infraSpineS.attributes.name == "ansible_access_spine_switch_selector_1" + - nm_add_spine_switch_selector.current.0.infraSpineS.attributes.descr == "Access Spine Switch Selector 1" + - nm_add_spine_switch_selector.current.0.infraSpineS.attributes.type == "range" + - nm_add_spine_switch_selector_idempotency is not changed + - nm_add_spine_switch_selector_idempotency.current.0.infraSpineS.attributes.name == "ansible_access_spine_switch_selector_1" + - nm_add_spine_switch_selector_idempotency.current.0.infraSpineS.attributes.descr == "Access Spine Switch Selector 1" + - nm_add_spine_switch_selector_idempotency.current.0.infraSpineS.attributes.type == "range" + - nm_add_spine_switch_selector_2 is changed + - nm_add_spine_switch_selector_2.previous == [] + - nm_add_spine_switch_selector_2.current.0.infraSpineS.attributes.name == "ansible_access_spine_switch_selector_2" + - nm_add_spine_switch_selector_2.current.0.infraSpineS.attributes.descr == "Access Spine Switch Selector 2" + - nm_add_spine_switch_selector_2.current.0.infraSpineS.attributes.type == "range" + + # QUERY ACCESS SPINE SWITCH SELECTOR + - name: Query all Access Spine Switch Selectors + cisco.aci.aci_access_spine_switch_selector: + <<: *aci_info + state: query + register: query_all_spine_switch_selector + + - name: Query ansible_access_spine_switch_selector_1 + cisco.aci.aci_access_spine_switch_selector: + <<: *aci_access_spine_switch_selector_present + state: query + register: query_ansible_access_spine_switch_selector_1 + + - name: Asserts query tasks + ansible.builtin.assert: + that: + - query_all_spine_switch_selector is not changed + - query_all_spine_switch_selector.current|length >= 2 + - query_ansible_access_spine_switch_selector_1 is not changed + - query_ansible_access_spine_switch_selector_1.current|length == 1 + - query_ansible_access_spine_switch_selector_1.current.0.infraSpineP.children.0.infraSpineS.attributes.name == "ansible_access_spine_switch_selector_1" + - query_ansible_access_spine_switch_selector_1.current.0.infraSpineP.children.0.infraSpineS.attributes.descr == "Access Spine Switch Selector 1" + - query_ansible_access_spine_switch_selector_1.current.0.infraSpineP.children.0.infraSpineS.attributes.type == "range" + + # UPDATE ACCESS SPINE SWITCH SELECTOR + - name: Update first Access Spine Switch Selector by adding a Policy Group (check_mode) + cisco.aci.aci_access_spine_switch_selector: &aci_access_spine_switch_selector_update + <<: *aci_access_spine_switch_selector_present + description: Updated description for first ansible Access Spine Switch Selector + policy_group: ansible_access_spine_switch_policy_group + check_mode: true + register: cm_update_spine_switch_selector + + - name: Update first Access Spine Switch Selector by adding a Policy Group (normal_mode) + cisco.aci.aci_access_spine_switch_selector: + <<: *aci_access_spine_switch_selector_update + register: nm_update_spine_switch_selector + + - name: Update first Access Spine Switch Selector by adding a Policy Group again - testing idempotency + cisco.aci.aci_access_spine_switch_selector: + <<: *aci_access_spine_switch_selector_update + register: nm_udpate_spine_switch_selector_idempotency + + - name: Asserts for Access Spine Switch Selector update tasks + ansible.builtin.assert: + that: + - cm_update_spine_switch_selector is changed + - cm_update_spine_switch_selector.previous == cm_update_spine_switch_selector.current + - cm_update_spine_switch_selector.proposed.infraSpineS.attributes.descr == "Updated description for first ansible Access Spine Switch Selector" + - cm_update_spine_switch_selector.proposed.infraSpineS.children.0.infraRsSpineAccNodePGrp.attributes.tDn == "uni/infra/funcprof/spaccnodepgrp-ansible_access_spine_switch_policy_group" + - nm_update_spine_switch_selector is changed + - nm_update_spine_switch_selector.current.0.infraSpineS.attributes.name == "ansible_access_spine_switch_selector_1" + - nm_update_spine_switch_selector.current.0.infraSpineS.attributes.descr == "Updated description for first ansible Access Spine Switch Selector" + - nm_update_spine_switch_selector.current.0.infraSpineS.children.0.infraRsSpineAccNodePGrp.attributes.tDn == "uni/infra/funcprof/spaccnodepgrp-ansible_access_spine_switch_policy_group" + - nm_udpate_spine_switch_selector_idempotency is not changed + - nm_udpate_spine_switch_selector_idempotency.current.0.infraSpineS.attributes.name == "ansible_access_spine_switch_selector_1" + - nm_udpate_spine_switch_selector_idempotency.current.0.infraSpineS.attributes.descr == "Updated description for first ansible Access Spine Switch Selector" + - nm_udpate_spine_switch_selector_idempotency.current.0.infraSpineS.children.0.infraRsSpineAccNodePGrp.attributes.tDn == "uni/infra/funcprof/spaccnodepgrp-ansible_access_spine_switch_policy_group" + + # DELETE ACCESS SPINE SWITCH SELECTOR + - name: Remove Access Spine Switch Selector (check_mode) + cisco.aci.aci_access_spine_switch_selector: &spine_switch_selector_absent + <<: *aci_access_spine_switch_selector_update + state: absent + check_mode: true + register: cm_remove_spine_switch_selector + + - name: Remove Access Spine Switch Selector (normal_mode) + cisco.aci.aci_access_spine_switch_selector: + <<: *spine_switch_selector_absent + register: nm_remove_spine_switch_selector + + - name: Remove Access Spine Switch Selector - testing idempotency + cisco.aci.aci_access_spine_switch_selector: + <<: *spine_switch_selector_absent + register: nm_remove_spine_switch_selector_idempotency + + - name: Asserts deletion tasks + ansible.builtin.assert: + that: + - cm_remove_spine_switch_selector is changed + - cm_remove_spine_switch_selector.current == cm_remove_spine_switch_selector.previous + - cm_remove_spine_switch_selector.proposed == {} + - nm_remove_spine_switch_selector is changed + - nm_remove_spine_switch_selector.previous != [] + - nm_remove_spine_switch_selector.proposed == {} + - nm_remove_spine_switch_selector.current == [] + - nm_remove_spine_switch_selector_idempotency is not changed + - nm_remove_spine_switch_selector_idempotency.previous == [] + - nm_remove_spine_switch_selector_idempotency.current == [] + + # CLEAN ENVIRONMENT BEFORE ENDING TESTS + - name: Remove the Access Spine Switch profile - cleanup before ending tests + cisco.aci.aci_access_spine_switch_profile: + <<: *aci_access_spine_switch_profile_present + state: absent diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_access_sub_port_block_to_access_port/tasks/main.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_access_sub_port_block_to_access_port/tasks/main.yml index b986f5762..69326320a 100644 --- a/ansible_collections/cisco/aci/tests/integration/targets/aci_access_sub_port_block_to_access_port/tasks/main.yml +++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_access_sub_port_block_to_access_port/tasks/main.yml @@ -4,12 +4,12 @@ # GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) - name: Test that we have an ACI APIC host, ACI username and ACI password - fail: + ansible.builtin.fail: msg: 'Please define the following variables: aci_hostname, aci_username and aci_password.' when: aci_hostname is not defined or aci_username is not defined or aci_password is not defined - name: Verify Cloud and Non-Cloud Sites in use. - include_tasks: ../../../../../../integration/targets/aci_cloud_provider/tasks/main.yml + ansible.builtin.include_tasks: ../../../../../../integration/targets/aci_cloud_provider/tasks/main.yml - name: Execute tasks only for non-cloud sites when: query_cloud.current == [] # This condition will execute only non-cloud sites @@ -64,7 +64,7 @@ # TODO: also test for errors - name: present assertions - assert: + ansible.builtin.assert: that: - accesssubportblock_to_accessport_check_mode_present is changed - accesssubportblock_to_accessport_present is changed @@ -88,7 +88,7 @@ register: binding_query - name: present assertions - assert: + ansible.builtin.assert: that: - binding_query is not changed - binding_query.current | length >= 1 @@ -120,7 +120,7 @@ register: accesssubportblock_to_accessport_absent_missing_param - name: absent assertions - assert: + ansible.builtin.assert: that: - accesssubportblock_to_accessport_check_mode_absent is changed - accesssubportblock_to_accessport_check_mode_absent.previous != [] diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_access_switch_policy_group/aliases b/ansible_collections/cisco/aci/tests/integration/targets/aci_access_switch_policy_group/aliases new file mode 100644 index 000000000..209b793f9 --- /dev/null +++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_access_switch_policy_group/aliases @@ -0,0 +1,2 @@ +# No ACI simulator yet, so not enabled +# unsupported diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_access_switch_policy_group/tasks/main.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_access_switch_policy_group/tasks/main.yml new file mode 100644 index 000000000..70a144a8e --- /dev/null +++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_access_switch_policy_group/tasks/main.yml @@ -0,0 +1,1122 @@ +# Test code for the ACI modules +# Copyright: (c) 2023, Tim Cragg (@timcragg) +# Copyright: (c) 2023, Akini Ross (@akinross) + +# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) + +- name: Test that we have an ACI APIC host, ACI username and ACI password + ansible.builtin.fail: + msg: 'Please define the following variables: aci_hostname, aci_username and aci_password.' + when: aci_hostname is not defined or aci_username is not defined or aci_password is not defined + +- name: Set vars + ansible.builtin.set_fact: + aci_info: &aci_info + host: "{{ aci_hostname }}" + port: "{{ aci_port | default(omit) }}" + username: "{{ aci_username }}" + password: "{{ aci_password }}" + validate_certs: '{{ aci_validate_certs | default(false) }}' + use_ssl: '{{ aci_use_ssl | default(true) }}' + use_proxy: '{{ aci_use_proxy | default(true) }}' + output_level: '{{ aci_output_level | default("info") }}' + +- name: Query system information + cisco.aci.aci_system: + <<: *aci_info + id: 1 + state: query + register: version + +- name: Verify Cloud and Non-Cloud Sites in use. + ansible.builtin.include_tasks: ../../../../../../integration/targets/aci_cloud_provider/tasks/main.yml + +- name: Execute tasks only for non-cloud sites + when: query_cloud.current == [] + block: # block specifies execution of tasks within, based on conditions + + # CLEAN ENVIRONMENT + - name: Remove the ansible access switch policy groups + cisco.aci.aci_access_switch_policy_group: + <<: *aci_info + switch_type: "{{ item.type }}" + name: "{{ item.name }}" + state: absent + loop: + - {name: ansible_access_switch_leaf_pol_grp, type: leaf} + - {name: ansible_access_switch_leaf_pol_grp_2, type: leaf} + - {name: ansible_access_switch_spine_pol_grp, type: spine} + - {name: ansible_access_switch_spine_pol_grp_2, type: spine} + + # ACCESS SWITCH LEAF POLICY GROUP + - name: Create the ansible access switch leaf policy group (check mode) + cisco.aci.aci_access_switch_policy_group: &aci_create_leaf_policy_group + <<: *aci_info + switch_type: leaf + name: ansible_access_switch_leaf_pol_grp + state: present + check_mode: yes + register: cm_create_leaf_policy_group + + - name: Create the ansible access switch leaf policy group + cisco.aci.aci_access_switch_policy_group: + <<: *aci_create_leaf_policy_group + register: nm_create_leaf_policy_group + + - name: Create the ansible access switch leaf policy group again + cisco.aci.aci_access_switch_policy_group: + <<: *aci_create_leaf_policy_group + register: nm_create_leaf_policy_group_again + + # TODO investigate simplify test assertion because apic returns order that deviates for each version + # Possibly by leveraging https://docs.ansible.com/ansible/latest/collections/community/general/docsite/filter_guide_selecting_json_data.html + - name: Verify creation of access switch leaf policy group for version 4.2(7s) + ansible.builtin.assert: + that: + - cm_create_leaf_policy_group is changed + - cm_create_leaf_policy_group.previous == [] + - cm_create_leaf_policy_group.current == [] + - cm_create_leaf_policy_group.proposed.infraAccNodePGrp.attributes.annotation == "orchestrator:ansible" + - cm_create_leaf_policy_group.proposed.infraAccNodePGrp.attributes.dn == "uni/infra/funcprof/accnodepgrp-ansible_access_switch_leaf_pol_grp" + - nm_create_leaf_policy_group is changed + - nm_create_leaf_policy_group.previous == [] + - nm_create_leaf_policy_group.current.0.infraAccNodePGrp.children.0.infraRsTopoctrlFwdScaleProfPol.attributes.tnTopoctrlFwdScaleProfilePolName == "" + - nm_create_leaf_policy_group.current.0.infraAccNodePGrp.children.1.infraRsPoeInstPol.attributes.tnPoeInstPolName == "" + - nm_create_leaf_policy_group.current.0.infraAccNodePGrp.children.2.infraRsBfdIpv6InstPol.attributes.tnBfdIpv6InstPolName == "" + - nm_create_leaf_policy_group.current.0.infraAccNodePGrp.children.3.infraRsEquipmentFlashConfigPol.attributes.tnEquipmentFlashConfigPolName == "" + - nm_create_leaf_policy_group.current.0.infraAccNodePGrp.children.4.infraRsMonNodeInfraPol.attributes.tnMonInfraPolName == "" + - nm_create_leaf_policy_group.current.0.infraAccNodePGrp.children.5.infraRsFcInstPol.attributes.tnFcInstPolName == "" + - nm_create_leaf_policy_group.current.0.infraAccNodePGrp.children.6.infraRsBfdIpv4InstPol.attributes.tnBfdIpv4InstPolName == "" + - nm_create_leaf_policy_group.current.0.infraAccNodePGrp.children.7.infraRsL2NodeAuthPol.attributes.tnL2NodeAuthPolName == "" + - nm_create_leaf_policy_group.current.0.infraAccNodePGrp.children.8.infraRsTopoctrlFastLinkFailoverInstPol.attributes.tnTopoctrlFastLinkFailoverInstPolName == "" + - nm_create_leaf_policy_group.current.0.infraAccNodePGrp.children.9.infraRsMstInstPol.attributes.tnStpInstPolName == "" + - nm_create_leaf_policy_group.current.0.infraAccNodePGrp.children.10.infraRsFcFabricPol.attributes.tnFcFabricPolName == "" + - nm_create_leaf_policy_group.current.0.infraAccNodePGrp.children.11.infraRsIaclLeafProfile.attributes.tnIaclLeafProfileName == "" + - nm_create_leaf_policy_group.current.0.infraAccNodePGrp.children.12.infraRsLeafCoppProfile.attributes.tnCoppLeafProfileName == "" + - nm_create_leaf_policy_group.current.0.infraAccNodePGrp.children.13.infraRsLeafPGrpToCdpIfPol.attributes.tnCdpIfPolName == "" + - nm_create_leaf_policy_group.current.0.infraAccNodePGrp.children.14.infraRsLeafPGrpToLldpIfPol.attributes.tnLldpIfPolName == "" + - nm_create_leaf_policy_group_again is not changed + - nm_create_leaf_policy_group_again.current.0.infraAccNodePGrp.children.0.infraRsTopoctrlFwdScaleProfPol.attributes.tnTopoctrlFwdScaleProfilePolName == "" + - nm_create_leaf_policy_group_again.current.0.infraAccNodePGrp.children.1.infraRsPoeInstPol.attributes.tnPoeInstPolName == "" + - nm_create_leaf_policy_group_again.current.0.infraAccNodePGrp.children.2.infraRsBfdIpv6InstPol.attributes.tnBfdIpv6InstPolName == "" + - nm_create_leaf_policy_group_again.current.0.infraAccNodePGrp.children.3.infraRsEquipmentFlashConfigPol.attributes.tnEquipmentFlashConfigPolName == "" + - nm_create_leaf_policy_group_again.current.0.infraAccNodePGrp.children.4.infraRsMonNodeInfraPol.attributes.tnMonInfraPolName == "" + - nm_create_leaf_policy_group_again.current.0.infraAccNodePGrp.children.5.infraRsFcInstPol.attributes.tnFcInstPolName == "" + - nm_create_leaf_policy_group_again.current.0.infraAccNodePGrp.children.6.infraRsBfdIpv4InstPol.attributes.tnBfdIpv4InstPolName == "" + - nm_create_leaf_policy_group_again.current.0.infraAccNodePGrp.children.7.infraRsL2NodeAuthPol.attributes.tnL2NodeAuthPolName == "" + - nm_create_leaf_policy_group_again.current.0.infraAccNodePGrp.children.8.infraRsTopoctrlFastLinkFailoverInstPol.attributes.tnTopoctrlFastLinkFailoverInstPolName == "" + - nm_create_leaf_policy_group_again.current.0.infraAccNodePGrp.children.9.infraRsMstInstPol.attributes.tnStpInstPolName == "" + - nm_create_leaf_policy_group_again.current.0.infraAccNodePGrp.children.10.infraRsFcFabricPol.attributes.tnFcFabricPolName == "" + - nm_create_leaf_policy_group_again.current.0.infraAccNodePGrp.children.11.infraRsIaclLeafProfile.attributes.tnIaclLeafProfileName == "" + - nm_create_leaf_policy_group_again.current.0.infraAccNodePGrp.children.12.infraRsLeafCoppProfile.attributes.tnCoppLeafProfileName == "" + - nm_create_leaf_policy_group_again.current.0.infraAccNodePGrp.children.13.infraRsLeafPGrpToCdpIfPol.attributes.tnCdpIfPolName == "" + - nm_create_leaf_policy_group_again.current.0.infraAccNodePGrp.children.14.infraRsLeafPGrpToLldpIfPol.attributes.tnLldpIfPolName == "" + - nm_create_leaf_policy_group_again.previous.0.infraAccNodePGrp.children.0.infraRsTopoctrlFwdScaleProfPol.attributes.tnTopoctrlFwdScaleProfilePolName == "" + - nm_create_leaf_policy_group_again.previous.0.infraAccNodePGrp.children.1.infraRsPoeInstPol.attributes.tnPoeInstPolName == "" + - nm_create_leaf_policy_group_again.previous.0.infraAccNodePGrp.children.2.infraRsBfdIpv6InstPol.attributes.tnBfdIpv6InstPolName == "" + - nm_create_leaf_policy_group_again.previous.0.infraAccNodePGrp.children.3.infraRsEquipmentFlashConfigPol.attributes.tnEquipmentFlashConfigPolName == "" + - nm_create_leaf_policy_group_again.previous.0.infraAccNodePGrp.children.4.infraRsMonNodeInfraPol.attributes.tnMonInfraPolName == "" + - nm_create_leaf_policy_group_again.previous.0.infraAccNodePGrp.children.5.infraRsFcInstPol.attributes.tnFcInstPolName == "" + - nm_create_leaf_policy_group_again.previous.0.infraAccNodePGrp.children.6.infraRsBfdIpv4InstPol.attributes.tnBfdIpv4InstPolName == "" + - nm_create_leaf_policy_group_again.previous.0.infraAccNodePGrp.children.7.infraRsL2NodeAuthPol.attributes.tnL2NodeAuthPolName == "" + - nm_create_leaf_policy_group_again.previous.0.infraAccNodePGrp.children.8.infraRsTopoctrlFastLinkFailoverInstPol.attributes.tnTopoctrlFastLinkFailoverInstPolName == "" + - nm_create_leaf_policy_group_again.previous.0.infraAccNodePGrp.children.9.infraRsMstInstPol.attributes.tnStpInstPolName == "" + - nm_create_leaf_policy_group_again.previous.0.infraAccNodePGrp.children.10.infraRsFcFabricPol.attributes.tnFcFabricPolName == "" + - nm_create_leaf_policy_group_again.previous.0.infraAccNodePGrp.children.11.infraRsIaclLeafProfile.attributes.tnIaclLeafProfileName == "" + - nm_create_leaf_policy_group_again.previous.0.infraAccNodePGrp.children.12.infraRsLeafCoppProfile.attributes.tnCoppLeafProfileName == "" + - nm_create_leaf_policy_group_again.previous.0.infraAccNodePGrp.children.13.infraRsLeafPGrpToCdpIfPol.attributes.tnCdpIfPolName == "" + - nm_create_leaf_policy_group_again.previous.0.infraAccNodePGrp.children.14.infraRsLeafPGrpToLldpIfPol.attributes.tnLldpIfPolName == "" + when: version.current.0.topSystem.attributes.version == "4.2(7s)" + + - name: Verify creation of access switch leaf policy group for version 5.2(5c) + ansible.builtin.assert: + that: + - cm_create_leaf_policy_group is changed + - cm_create_leaf_policy_group.previous == [] + - cm_create_leaf_policy_group.current == [] + - cm_create_leaf_policy_group.proposed.infraAccNodePGrp.attributes.annotation == "orchestrator:ansible" + - cm_create_leaf_policy_group.proposed.infraAccNodePGrp.attributes.dn == "uni/infra/funcprof/accnodepgrp-ansible_access_switch_leaf_pol_grp" + - nm_create_leaf_policy_group is changed + - nm_create_leaf_policy_group.previous == [] + - nm_create_leaf_policy_group.current.0.infraAccNodePGrp.children.0.infraRsTopoctrlFwdScaleProfPol.attributes.tnTopoctrlFwdScaleProfilePolName == "" + - nm_create_leaf_policy_group.current.0.infraAccNodePGrp.children.1.infraRsLeafTopoctrlUsbConfigProfilePol.attributes.tnTopoctrlUsbConfigProfilePolName == "" + - nm_create_leaf_policy_group.current.0.infraAccNodePGrp.children.2.infraRsLeafPGrpToLldpIfPol.attributes.tnLldpIfPolName == "" + - nm_create_leaf_policy_group.current.0.infraAccNodePGrp.children.3.infraRsLeafPGrpToCdpIfPol.attributes.tnCdpIfPolName == "" + - nm_create_leaf_policy_group.current.0.infraAccNodePGrp.children.4.infraRsBfdIpv6InstPol.attributes.tnBfdIpv6InstPolName == "" + - nm_create_leaf_policy_group.current.0.infraAccNodePGrp.children.5.infraRsSynceInstPol.attributes.tnSynceInstPolName == "" + - nm_create_leaf_policy_group.current.0.infraAccNodePGrp.children.6.infraRsPoeInstPol.attributes.tnPoeInstPolName == "" + - nm_create_leaf_policy_group.current.0.infraAccNodePGrp.children.7.infraRsBfdMhIpv4InstPol.attributes.tnBfdMhIpv4InstPolName == "" + - nm_create_leaf_policy_group.current.0.infraAccNodePGrp.children.8.infraRsBfdMhIpv6InstPol.attributes.tnBfdMhIpv6InstPolName == "" + - nm_create_leaf_policy_group.current.0.infraAccNodePGrp.children.9.infraRsEquipmentFlashConfigPol.attributes.tnEquipmentFlashConfigPolName == "" + - nm_create_leaf_policy_group.current.0.infraAccNodePGrp.children.10.infraRsMonNodeInfraPol.attributes.tnMonInfraPolName == "" + - nm_create_leaf_policy_group.current.0.infraAccNodePGrp.children.11.infraRsFcInstPol.attributes.tnFcInstPolName == "" + - nm_create_leaf_policy_group.current.0.infraAccNodePGrp.children.12.infraRsTopoctrlFastLinkFailoverInstPol.attributes.tnTopoctrlFastLinkFailoverInstPolName == "" + - nm_create_leaf_policy_group.current.0.infraAccNodePGrp.children.13.infraRsMstInstPol.attributes.tnStpInstPolName == "" + - nm_create_leaf_policy_group.current.0.infraAccNodePGrp.children.14.infraRsFcFabricPol.attributes.tnFcFabricPolName == "" + - nm_create_leaf_policy_group.current.0.infraAccNodePGrp.children.15.infraRsLeafCoppProfile.attributes.tnCoppLeafProfileName == "" + - nm_create_leaf_policy_group.current.0.infraAccNodePGrp.children.16.infraRsIaclLeafProfile.attributes.tnIaclLeafProfileName == "" + - nm_create_leaf_policy_group.current.0.infraAccNodePGrp.children.17.infraRsBfdIpv4InstPol.attributes.tnBfdIpv4InstPolName == "" + - nm_create_leaf_policy_group.current.0.infraAccNodePGrp.children.18.infraRsL2NodeAuthPol.attributes.tnL2NodeAuthPolName == "" + - nm_create_leaf_policy_group_again is not changed + - nm_create_leaf_policy_group_again.current.0.infraAccNodePGrp.children.0.infraRsTopoctrlFwdScaleProfPol.attributes.tnTopoctrlFwdScaleProfilePolName == "" + - nm_create_leaf_policy_group_again.current.0.infraAccNodePGrp.children.1.infraRsLeafTopoctrlUsbConfigProfilePol.attributes.tnTopoctrlUsbConfigProfilePolName == "" + - nm_create_leaf_policy_group_again.current.0.infraAccNodePGrp.children.2.infraRsLeafPGrpToLldpIfPol.attributes.tnLldpIfPolName == "" + - nm_create_leaf_policy_group_again.current.0.infraAccNodePGrp.children.3.infraRsLeafPGrpToCdpIfPol.attributes.tnCdpIfPolName == "" + - nm_create_leaf_policy_group_again.current.0.infraAccNodePGrp.children.4.infraRsBfdIpv6InstPol.attributes.tnBfdIpv6InstPolName == "" + - nm_create_leaf_policy_group_again.current.0.infraAccNodePGrp.children.5.infraRsSynceInstPol.attributes.tnSynceInstPolName == "" + - nm_create_leaf_policy_group_again.current.0.infraAccNodePGrp.children.6.infraRsPoeInstPol.attributes.tnPoeInstPolName == "" + - nm_create_leaf_policy_group_again.current.0.infraAccNodePGrp.children.7.infraRsBfdMhIpv4InstPol.attributes.tnBfdMhIpv4InstPolName == "" + - nm_create_leaf_policy_group_again.current.0.infraAccNodePGrp.children.8.infraRsBfdMhIpv6InstPol.attributes.tnBfdMhIpv6InstPolName == "" + - nm_create_leaf_policy_group_again.current.0.infraAccNodePGrp.children.9.infraRsEquipmentFlashConfigPol.attributes.tnEquipmentFlashConfigPolName == "" + - nm_create_leaf_policy_group_again.current.0.infraAccNodePGrp.children.10.infraRsMonNodeInfraPol.attributes.tnMonInfraPolName == "" + - nm_create_leaf_policy_group_again.current.0.infraAccNodePGrp.children.11.infraRsFcInstPol.attributes.tnFcInstPolName == "" + - nm_create_leaf_policy_group_again.current.0.infraAccNodePGrp.children.12.infraRsTopoctrlFastLinkFailoverInstPol.attributes.tnTopoctrlFastLinkFailoverInstPolName == "" + - nm_create_leaf_policy_group_again.current.0.infraAccNodePGrp.children.13.infraRsMstInstPol.attributes.tnStpInstPolName == "" + - nm_create_leaf_policy_group_again.current.0.infraAccNodePGrp.children.14.infraRsFcFabricPol.attributes.tnFcFabricPolName == "" + - nm_create_leaf_policy_group_again.current.0.infraAccNodePGrp.children.15.infraRsLeafCoppProfile.attributes.tnCoppLeafProfileName == "" + - nm_create_leaf_policy_group_again.current.0.infraAccNodePGrp.children.16.infraRsIaclLeafProfile.attributes.tnIaclLeafProfileName == "" + - nm_create_leaf_policy_group_again.current.0.infraAccNodePGrp.children.17.infraRsBfdIpv4InstPol.attributes.tnBfdIpv4InstPolName == "" + - nm_create_leaf_policy_group_again.current.0.infraAccNodePGrp.children.18.infraRsL2NodeAuthPol.attributes.tnL2NodeAuthPolName == "" + - nm_create_leaf_policy_group_again.previous.0.infraAccNodePGrp.children.0.infraRsTopoctrlFwdScaleProfPol.attributes.tnTopoctrlFwdScaleProfilePolName == "" + - nm_create_leaf_policy_group_again.previous.0.infraAccNodePGrp.children.1.infraRsLeafTopoctrlUsbConfigProfilePol.attributes.tnTopoctrlUsbConfigProfilePolName == "" + - nm_create_leaf_policy_group_again.previous.0.infraAccNodePGrp.children.2.infraRsLeafPGrpToLldpIfPol.attributes.tnLldpIfPolName == "" + - nm_create_leaf_policy_group_again.previous.0.infraAccNodePGrp.children.3.infraRsLeafPGrpToCdpIfPol.attributes.tnCdpIfPolName == "" + - nm_create_leaf_policy_group_again.previous.0.infraAccNodePGrp.children.4.infraRsBfdIpv6InstPol.attributes.tnBfdIpv6InstPolName == "" + - nm_create_leaf_policy_group_again.previous.0.infraAccNodePGrp.children.5.infraRsSynceInstPol.attributes.tnSynceInstPolName == "" + - nm_create_leaf_policy_group_again.previous.0.infraAccNodePGrp.children.6.infraRsPoeInstPol.attributes.tnPoeInstPolName == "" + - nm_create_leaf_policy_group_again.previous.0.infraAccNodePGrp.children.7.infraRsBfdMhIpv4InstPol.attributes.tnBfdMhIpv4InstPolName == "" + - nm_create_leaf_policy_group_again.previous.0.infraAccNodePGrp.children.8.infraRsBfdMhIpv6InstPol.attributes.tnBfdMhIpv6InstPolName == "" + - nm_create_leaf_policy_group_again.previous.0.infraAccNodePGrp.children.9.infraRsEquipmentFlashConfigPol.attributes.tnEquipmentFlashConfigPolName == "" + - nm_create_leaf_policy_group_again.previous.0.infraAccNodePGrp.children.10.infraRsMonNodeInfraPol.attributes.tnMonInfraPolName == "" + - nm_create_leaf_policy_group_again.previous.0.infraAccNodePGrp.children.11.infraRsFcInstPol.attributes.tnFcInstPolName == "" + - nm_create_leaf_policy_group_again.previous.0.infraAccNodePGrp.children.12.infraRsTopoctrlFastLinkFailoverInstPol.attributes.tnTopoctrlFastLinkFailoverInstPolName == "" + - nm_create_leaf_policy_group_again.previous.0.infraAccNodePGrp.children.13.infraRsMstInstPol.attributes.tnStpInstPolName == "" + - nm_create_leaf_policy_group_again.previous.0.infraAccNodePGrp.children.14.infraRsFcFabricPol.attributes.tnFcFabricPolName == "" + - nm_create_leaf_policy_group_again.previous.0.infraAccNodePGrp.children.15.infraRsLeafCoppProfile.attributes.tnCoppLeafProfileName == "" + - nm_create_leaf_policy_group_again.previous.0.infraAccNodePGrp.children.16.infraRsIaclLeafProfile.attributes.tnIaclLeafProfileName == "" + - nm_create_leaf_policy_group_again.previous.0.infraAccNodePGrp.children.17.infraRsBfdIpv4InstPol.attributes.tnBfdIpv4InstPolName == "" + - nm_create_leaf_policy_group_again.previous.0.infraAccNodePGrp.children.18.infraRsL2NodeAuthPol.attributes.tnL2NodeAuthPolName == "" + when: version.current.0.topSystem.attributes.version == "5.2(5c)" + + - name: Verify creation of access switch leaf policy group for version 6.0(2h) + ansible.builtin.assert: + that: + - cm_create_leaf_policy_group is changed + - cm_create_leaf_policy_group.previous == [] + - cm_create_leaf_policy_group.current == [] + - cm_create_leaf_policy_group.proposed.infraAccNodePGrp.attributes.annotation == "orchestrator:ansible" + - cm_create_leaf_policy_group.proposed.infraAccNodePGrp.attributes.dn == "uni/infra/funcprof/accnodepgrp-ansible_access_switch_leaf_pol_grp" + - nm_create_leaf_policy_group is changed + - nm_create_leaf_policy_group.previous == [] + - nm_create_leaf_policy_group.current.0.infraAccNodePGrp.children.0.infraRsTopoctrlFwdScaleProfPol.attributes.tnTopoctrlFwdScaleProfilePolName == "" + - nm_create_leaf_policy_group.current.0.infraAccNodePGrp.children.1.infraRsLeafTopoctrlUsbConfigProfilePol.attributes.tnTopoctrlUsbConfigProfilePolName == "" + - nm_create_leaf_policy_group.current.0.infraAccNodePGrp.children.2.infraRsLeafPGrpToLldpIfPol.attributes.tnLldpIfPolName == "" + - nm_create_leaf_policy_group.current.0.infraAccNodePGrp.children.3.infraRsBfdIpv6InstPol.attributes.tnBfdIpv6InstPolName == "" + - nm_create_leaf_policy_group.current.0.infraAccNodePGrp.children.4.infraRsSynceInstPol.attributes.tnSynceInstPolName == "" + - nm_create_leaf_policy_group.current.0.infraAccNodePGrp.children.5.infraRsPoeInstPol.attributes.tnPoeInstPolName == "" + - nm_create_leaf_policy_group.current.0.infraAccNodePGrp.children.6.infraRsBfdMhIpv4InstPol.attributes.tnBfdMhIpv4InstPolName == "" + - nm_create_leaf_policy_group.current.0.infraAccNodePGrp.children.7.infraRsBfdMhIpv6InstPol.attributes.tnBfdMhIpv6InstPolName == "" + - nm_create_leaf_policy_group.current.0.infraAccNodePGrp.children.8.infraRsEquipmentFlashConfigPol.attributes.tnEquipmentFlashConfigPolName == "" + - nm_create_leaf_policy_group.current.0.infraAccNodePGrp.children.9.infraRsMonNodeInfraPol.attributes.tnMonInfraPolName == "" + - nm_create_leaf_policy_group.current.0.infraAccNodePGrp.children.10.infraRsFcInstPol.attributes.tnFcInstPolName == "" + - nm_create_leaf_policy_group.current.0.infraAccNodePGrp.children.11.infraRsTopoctrlFastLinkFailoverInstPol.attributes.tnTopoctrlFastLinkFailoverInstPolName == "" + - nm_create_leaf_policy_group.current.0.infraAccNodePGrp.children.12.infraRsMstInstPol.attributes.tnStpInstPolName == "" + - nm_create_leaf_policy_group.current.0.infraAccNodePGrp.children.13.infraRsFcFabricPol.attributes.tnFcFabricPolName == "" + - nm_create_leaf_policy_group.current.0.infraAccNodePGrp.children.14.infraRsLeafCoppProfile.attributes.tnCoppLeafProfileName == "" + - nm_create_leaf_policy_group.current.0.infraAccNodePGrp.children.15.infraRsIaclLeafProfile.attributes.tnIaclLeafProfileName == "" + - nm_create_leaf_policy_group.current.0.infraAccNodePGrp.children.16.infraRsBfdIpv4InstPol.attributes.tnBfdIpv4InstPolName == "" + - nm_create_leaf_policy_group.current.0.infraAccNodePGrp.children.17.infraRsL2NodeAuthPol.attributes.tnL2NodeAuthPolName == "" + - nm_create_leaf_policy_group.current.0.infraAccNodePGrp.children.18.infraRsLeafPGrpToCdpIfPol.attributes.tnCdpIfPolName == "" + - nm_create_leaf_policy_group_again is not changed + - nm_create_leaf_policy_group_again.current.0.infraAccNodePGrp.children.0.infraRsTopoctrlFwdScaleProfPol.attributes.tnTopoctrlFwdScaleProfilePolName == "" + - nm_create_leaf_policy_group_again.current.0.infraAccNodePGrp.children.1.infraRsLeafTopoctrlUsbConfigProfilePol.attributes.tnTopoctrlUsbConfigProfilePolName == "" + - nm_create_leaf_policy_group_again.current.0.infraAccNodePGrp.children.2.infraRsLeafPGrpToLldpIfPol.attributes.tnLldpIfPolName == "" + - nm_create_leaf_policy_group_again.current.0.infraAccNodePGrp.children.3.infraRsBfdIpv6InstPol.attributes.tnBfdIpv6InstPolName == "" + - nm_create_leaf_policy_group_again.current.0.infraAccNodePGrp.children.4.infraRsSynceInstPol.attributes.tnSynceInstPolName == "" + - nm_create_leaf_policy_group_again.current.0.infraAccNodePGrp.children.5.infraRsPoeInstPol.attributes.tnPoeInstPolName == "" + - nm_create_leaf_policy_group_again.current.0.infraAccNodePGrp.children.6.infraRsBfdMhIpv4InstPol.attributes.tnBfdMhIpv4InstPolName == "" + - nm_create_leaf_policy_group_again.current.0.infraAccNodePGrp.children.7.infraRsBfdMhIpv6InstPol.attributes.tnBfdMhIpv6InstPolName == "" + - nm_create_leaf_policy_group_again.current.0.infraAccNodePGrp.children.8.infraRsEquipmentFlashConfigPol.attributes.tnEquipmentFlashConfigPolName == "" + - nm_create_leaf_policy_group_again.current.0.infraAccNodePGrp.children.9.infraRsMonNodeInfraPol.attributes.tnMonInfraPolName == "" + - nm_create_leaf_policy_group_again.current.0.infraAccNodePGrp.children.10.infraRsFcInstPol.attributes.tnFcInstPolName == "" + - nm_create_leaf_policy_group_again.current.0.infraAccNodePGrp.children.11.infraRsTopoctrlFastLinkFailoverInstPol.attributes.tnTopoctrlFastLinkFailoverInstPolName == "" + - nm_create_leaf_policy_group_again.current.0.infraAccNodePGrp.children.12.infraRsMstInstPol.attributes.tnStpInstPolName == "" + - nm_create_leaf_policy_group_again.current.0.infraAccNodePGrp.children.13.infraRsFcFabricPol.attributes.tnFcFabricPolName == "" + - nm_create_leaf_policy_group_again.current.0.infraAccNodePGrp.children.14.infraRsLeafCoppProfile.attributes.tnCoppLeafProfileName == "" + - nm_create_leaf_policy_group_again.current.0.infraAccNodePGrp.children.15.infraRsIaclLeafProfile.attributes.tnIaclLeafProfileName == "" + - nm_create_leaf_policy_group_again.current.0.infraAccNodePGrp.children.16.infraRsBfdIpv4InstPol.attributes.tnBfdIpv4InstPolName == "" + - nm_create_leaf_policy_group_again.current.0.infraAccNodePGrp.children.17.infraRsL2NodeAuthPol.attributes.tnL2NodeAuthPolName == "" + - nm_create_leaf_policy_group_again.current.0.infraAccNodePGrp.children.18.infraRsLeafPGrpToCdpIfPol.attributes.tnCdpIfPolName == "" + - nm_create_leaf_policy_group_again.previous.0.infraAccNodePGrp.children.0.infraRsTopoctrlFwdScaleProfPol.attributes.tnTopoctrlFwdScaleProfilePolName == "" + - nm_create_leaf_policy_group_again.previous.0.infraAccNodePGrp.children.1.infraRsLeafTopoctrlUsbConfigProfilePol.attributes.tnTopoctrlUsbConfigProfilePolName == "" + - nm_create_leaf_policy_group_again.previous.0.infraAccNodePGrp.children.2.infraRsLeafPGrpToLldpIfPol.attributes.tnLldpIfPolName == "" + - nm_create_leaf_policy_group_again.previous.0.infraAccNodePGrp.children.3.infraRsBfdIpv6InstPol.attributes.tnBfdIpv6InstPolName == "" + - nm_create_leaf_policy_group_again.previous.0.infraAccNodePGrp.children.4.infraRsSynceInstPol.attributes.tnSynceInstPolName == "" + - nm_create_leaf_policy_group_again.previous.0.infraAccNodePGrp.children.5.infraRsPoeInstPol.attributes.tnPoeInstPolName == "" + - nm_create_leaf_policy_group_again.previous.0.infraAccNodePGrp.children.6.infraRsBfdMhIpv4InstPol.attributes.tnBfdMhIpv4InstPolName == "" + - nm_create_leaf_policy_group_again.previous.0.infraAccNodePGrp.children.7.infraRsBfdMhIpv6InstPol.attributes.tnBfdMhIpv6InstPolName == "" + - nm_create_leaf_policy_group_again.previous.0.infraAccNodePGrp.children.8.infraRsEquipmentFlashConfigPol.attributes.tnEquipmentFlashConfigPolName == "" + - nm_create_leaf_policy_group_again.previous.0.infraAccNodePGrp.children.9.infraRsMonNodeInfraPol.attributes.tnMonInfraPolName == "" + - nm_create_leaf_policy_group_again.previous.0.infraAccNodePGrp.children.10.infraRsFcInstPol.attributes.tnFcInstPolName == "" + - nm_create_leaf_policy_group_again.previous.0.infraAccNodePGrp.children.11.infraRsTopoctrlFastLinkFailoverInstPol.attributes.tnTopoctrlFastLinkFailoverInstPolName == "" + - nm_create_leaf_policy_group_again.previous.0.infraAccNodePGrp.children.12.infraRsMstInstPol.attributes.tnStpInstPolName == "" + - nm_create_leaf_policy_group_again.previous.0.infraAccNodePGrp.children.13.infraRsFcFabricPol.attributes.tnFcFabricPolName == "" + - nm_create_leaf_policy_group_again.previous.0.infraAccNodePGrp.children.14.infraRsLeafCoppProfile.attributes.tnCoppLeafProfileName == "" + - nm_create_leaf_policy_group_again.previous.0.infraAccNodePGrp.children.15.infraRsIaclLeafProfile.attributes.tnIaclLeafProfileName == "" + - nm_create_leaf_policy_group_again.previous.0.infraAccNodePGrp.children.16.infraRsBfdIpv4InstPol.attributes.tnBfdIpv4InstPolName == "" + - nm_create_leaf_policy_group_again.previous.0.infraAccNodePGrp.children.17.infraRsL2NodeAuthPol.attributes.tnL2NodeAuthPolName == "" + - nm_create_leaf_policy_group_again.previous.0.infraAccNodePGrp.children.18.infraRsLeafPGrpToCdpIfPol.attributes.tnCdpIfPolName == "" + when: version.current.0.topSystem.attributes.version == "6.0(2h)" + + - name: Verify creation of access switch leaf policy group for 6.0(1g) + ansible.builtin.assert: + that: + - cm_create_leaf_policy_group is changed + - cm_create_leaf_policy_group.previous == [] + - cm_create_leaf_policy_group.current == [] + - cm_create_leaf_policy_group.proposed.infraAccNodePGrp.attributes.annotation == "orchestrator:ansible" + - cm_create_leaf_policy_group.proposed.infraAccNodePGrp.attributes.dn == "uni/infra/funcprof/accnodepgrp-ansible_access_switch_leaf_pol_grp" + - nm_create_leaf_policy_group is changed + - nm_create_leaf_policy_group.previous == [] + - nm_create_leaf_policy_group.current.0.infraAccNodePGrp.children.0.infraRsTopoctrlFwdScaleProfPol.attributes.tnTopoctrlFwdScaleProfilePolName == "" + - nm_create_leaf_policy_group.current.0.infraAccNodePGrp.children.1.infraRsLeafTopoctrlUsbConfigProfilePol.attributes.tnTopoctrlUsbConfigProfilePolName == "" + - nm_create_leaf_policy_group.current.0.infraAccNodePGrp.children.2.infraRsLeafPGrpToLldpIfPol.attributes.tnLldpIfPolName == "" + - nm_create_leaf_policy_group.current.0.infraAccNodePGrp.children.3.infraRsLeafPGrpToCdpIfPol.attributes.tnCdpIfPolName == "" + - nm_create_leaf_policy_group.current.0.infraAccNodePGrp.children.4.infraRsBfdIpv6InstPol.attributes.tnBfdIpv6InstPolName == "" + - nm_create_leaf_policy_group.current.0.infraAccNodePGrp.children.5.infraRsSynceInstPol.attributes.tnSynceInstPolName == "" + - nm_create_leaf_policy_group.current.0.infraAccNodePGrp.children.6.infraRsPoeInstPol.attributes.tnPoeInstPolName == "" + - nm_create_leaf_policy_group.current.0.infraAccNodePGrp.children.7.infraRsBfdMhIpv4InstPol.attributes.tnBfdMhIpv4InstPolName == "" + - nm_create_leaf_policy_group.current.0.infraAccNodePGrp.children.8.infraRsBfdMhIpv6InstPol.attributes.tnBfdMhIpv6InstPolName == "" + - nm_create_leaf_policy_group.current.0.infraAccNodePGrp.children.9.infraRsEquipmentFlashConfigPol.attributes.tnEquipmentFlashConfigPolName == "" + - nm_create_leaf_policy_group.current.0.infraAccNodePGrp.children.10.infraRsMonNodeInfraPol.attributes.tnMonInfraPolName == "" + - nm_create_leaf_policy_group.current.0.infraAccNodePGrp.children.11.infraRsFcInstPol.attributes.tnFcInstPolName == "" + - nm_create_leaf_policy_group.current.0.infraAccNodePGrp.children.12.infraRsTopoctrlFastLinkFailoverInstPol.attributes.tnTopoctrlFastLinkFailoverInstPolName == "" + - nm_create_leaf_policy_group.current.0.infraAccNodePGrp.children.13.infraRsMstInstPol.attributes.tnStpInstPolName == "" + - nm_create_leaf_policy_group.current.0.infraAccNodePGrp.children.14.infraRsFcFabricPol.attributes.tnFcFabricPolName == "" + - nm_create_leaf_policy_group.current.0.infraAccNodePGrp.children.15.infraRsLeafCoppProfile.attributes.tnCoppLeafProfileName == "" + - nm_create_leaf_policy_group.current.0.infraAccNodePGrp.children.16.infraRsIaclLeafProfile.attributes.tnIaclLeafProfileName == "" + - nm_create_leaf_policy_group.current.0.infraAccNodePGrp.children.17.infraRsBfdIpv4InstPol.attributes.tnBfdIpv4InstPolName == "" + - nm_create_leaf_policy_group.current.0.infraAccNodePGrp.children.18.infraRsL2NodeAuthPol.attributes.tnL2NodeAuthPolName == "" + - nm_create_leaf_policy_group_again is not changed + - nm_create_leaf_policy_group_again.current.0.infraAccNodePGrp.children.0.infraRsTopoctrlFwdScaleProfPol.attributes.tnTopoctrlFwdScaleProfilePolName == "" + - nm_create_leaf_policy_group_again.current.0.infraAccNodePGrp.children.1.infraRsLeafTopoctrlUsbConfigProfilePol.attributes.tnTopoctrlUsbConfigProfilePolName == "" + - nm_create_leaf_policy_group_again.current.0.infraAccNodePGrp.children.2.infraRsLeafPGrpToLldpIfPol.attributes.tnLldpIfPolName == "" + - nm_create_leaf_policy_group_again.current.0.infraAccNodePGrp.children.3.infraRsLeafPGrpToCdpIfPol.attributes.tnCdpIfPolName == "" + - nm_create_leaf_policy_group_again.current.0.infraAccNodePGrp.children.4.infraRsBfdIpv6InstPol.attributes.tnBfdIpv6InstPolName == "" + - nm_create_leaf_policy_group_again.current.0.infraAccNodePGrp.children.5.infraRsSynceInstPol.attributes.tnSynceInstPolName == "" + - nm_create_leaf_policy_group_again.current.0.infraAccNodePGrp.children.6.infraRsPoeInstPol.attributes.tnPoeInstPolName == "" + - nm_create_leaf_policy_group_again.current.0.infraAccNodePGrp.children.7.infraRsBfdMhIpv4InstPol.attributes.tnBfdMhIpv4InstPolName == "" + - nm_create_leaf_policy_group_again.current.0.infraAccNodePGrp.children.8.infraRsBfdMhIpv6InstPol.attributes.tnBfdMhIpv6InstPolName == "" + - nm_create_leaf_policy_group_again.current.0.infraAccNodePGrp.children.9.infraRsEquipmentFlashConfigPol.attributes.tnEquipmentFlashConfigPolName == "" + - nm_create_leaf_policy_group_again.current.0.infraAccNodePGrp.children.10.infraRsMonNodeInfraPol.attributes.tnMonInfraPolName == "" + - nm_create_leaf_policy_group_again.current.0.infraAccNodePGrp.children.11.infraRsFcInstPol.attributes.tnFcInstPolName == "" + - nm_create_leaf_policy_group_again.current.0.infraAccNodePGrp.children.12.infraRsTopoctrlFastLinkFailoverInstPol.attributes.tnTopoctrlFastLinkFailoverInstPolName == "" + - nm_create_leaf_policy_group_again.current.0.infraAccNodePGrp.children.13.infraRsMstInstPol.attributes.tnStpInstPolName == "" + - nm_create_leaf_policy_group_again.current.0.infraAccNodePGrp.children.14.infraRsFcFabricPol.attributes.tnFcFabricPolName == "" + - nm_create_leaf_policy_group_again.current.0.infraAccNodePGrp.children.15.infraRsLeafCoppProfile.attributes.tnCoppLeafProfileName == "" + - nm_create_leaf_policy_group_again.current.0.infraAccNodePGrp.children.16.infraRsIaclLeafProfile.attributes.tnIaclLeafProfileName == "" + - nm_create_leaf_policy_group_again.current.0.infraAccNodePGrp.children.17.infraRsBfdIpv4InstPol.attributes.tnBfdIpv4InstPolName == "" + - nm_create_leaf_policy_group_again.current.0.infraAccNodePGrp.children.18.infraRsL2NodeAuthPol.attributes.tnL2NodeAuthPolName == "" + - nm_create_leaf_policy_group_again.previous.0.infraAccNodePGrp.children.0.infraRsTopoctrlFwdScaleProfPol.attributes.tnTopoctrlFwdScaleProfilePolName == "" + - nm_create_leaf_policy_group_again.previous.0.infraAccNodePGrp.children.1.infraRsLeafTopoctrlUsbConfigProfilePol.attributes.tnTopoctrlUsbConfigProfilePolName == "" + - nm_create_leaf_policy_group_again.previous.0.infraAccNodePGrp.children.2.infraRsLeafPGrpToLldpIfPol.attributes.tnLldpIfPolName == "" + - nm_create_leaf_policy_group_again.previous.0.infraAccNodePGrp.children.3.infraRsLeafPGrpToCdpIfPol.attributes.tnCdpIfPolName == "" + - nm_create_leaf_policy_group_again.previous.0.infraAccNodePGrp.children.4.infraRsBfdIpv6InstPol.attributes.tnBfdIpv6InstPolName == "" + - nm_create_leaf_policy_group_again.previous.0.infraAccNodePGrp.children.5.infraRsSynceInstPol.attributes.tnSynceInstPolName == "" + - nm_create_leaf_policy_group_again.previous.0.infraAccNodePGrp.children.6.infraRsPoeInstPol.attributes.tnPoeInstPolName == "" + - nm_create_leaf_policy_group_again.previous.0.infraAccNodePGrp.children.7.infraRsBfdMhIpv4InstPol.attributes.tnBfdMhIpv4InstPolName == "" + - nm_create_leaf_policy_group_again.previous.0.infraAccNodePGrp.children.8.infraRsBfdMhIpv6InstPol.attributes.tnBfdMhIpv6InstPolName == "" + - nm_create_leaf_policy_group_again.previous.0.infraAccNodePGrp.children.9.infraRsEquipmentFlashConfigPol.attributes.tnEquipmentFlashConfigPolName == "" + - nm_create_leaf_policy_group_again.previous.0.infraAccNodePGrp.children.10.infraRsMonNodeInfraPol.attributes.tnMonInfraPolName == "" + - nm_create_leaf_policy_group_again.previous.0.infraAccNodePGrp.children.11.infraRsFcInstPol.attributes.tnFcInstPolName == "" + - nm_create_leaf_policy_group_again.previous.0.infraAccNodePGrp.children.12.infraRsTopoctrlFastLinkFailoverInstPol.attributes.tnTopoctrlFastLinkFailoverInstPolName == "" + - nm_create_leaf_policy_group_again.previous.0.infraAccNodePGrp.children.13.infraRsMstInstPol.attributes.tnStpInstPolName == "" + - nm_create_leaf_policy_group_again.previous.0.infraAccNodePGrp.children.14.infraRsFcFabricPol.attributes.tnFcFabricPolName == "" + - nm_create_leaf_policy_group_again.previous.0.infraAccNodePGrp.children.15.infraRsLeafCoppProfile.attributes.tnCoppLeafProfileName == "" + - nm_create_leaf_policy_group_again.previous.0.infraAccNodePGrp.children.16.infraRsIaclLeafProfile.attributes.tnIaclLeafProfileName == "" + - nm_create_leaf_policy_group_again.previous.0.infraAccNodePGrp.children.17.infraRsBfdIpv4InstPol.attributes.tnBfdIpv4InstPolName == "" + - nm_create_leaf_policy_group_again.previous.0.infraAccNodePGrp.children.18.infraRsL2NodeAuthPol.attributes.tnL2NodeAuthPolName == "" + when: version.current.0.topSystem.attributes.version == "6.0(1g)" + + - name: Change the ansible access switch leaf policy group < 5.0 + cisco.aci.aci_access_switch_policy_group: + <<: *aci_create_leaf_policy_group + spanning_tree_policy: changed_spanning_tree_policy + bfd_ipv4_policy: changed_bfd_ipv4_policy + bfd_ipv6_policy: changed_bfd_ipv6_policy + fibre_channel_node_policy: changed_fibre_channel_node_policy + poe_node_policy: changed_poe_node_policy + fibre_channel_san_policy: changed_fibre_channel_san_policy + monitoring_policy: changed_monitoring_policy + copp_policy: changed_copp_policy + forward_scale_profile_policy: changed_forward_scale_profile_policy + fast_link_failover_policy: changed_fast_link_failover_policy + node_802_1x_authentication_policy: changed_node_802_1x_authentication_policy + copp_pre_filter_policy: changed_copp_pre_filter_policy + equipment_flash_policy: changed_equipment_flash_policy + cdp_policy: changed_cdp_policy + lldp_policy: changed_lldp_policy + register: nm_change_leaf_policy_group_5_2 + when: version.current.0.topSystem.attributes.version is version('5.2', '<') + + - name: Change the ansible access switch leaf policy group + cisco.aci.aci_access_switch_policy_group: + <<: *aci_create_leaf_policy_group + spanning_tree_policy: changed_spanning_tree_policy + bfd_ipv4_policy: changed_bfd_ipv4_policy + bfd_ipv6_policy: changed_bfd_ipv6_policy + bfd_multihop_ipv4_policy: changed_bfd_multihop_ipv4_policy + bfd_multihop_ipv6_policy: changed_bfd_multihop_ipv6_policy + fibre_channel_node_policy: changed_fibre_channel_node_policy + poe_node_policy: changed_poe_node_policy + fibre_channel_san_policy: changed_fibre_channel_san_policy + monitoring_policy: changed_monitoring_policy + copp_policy: changed_copp_policy + forward_scale_profile_policy: changed_forward_scale_profile_policy + fast_link_failover_policy: changed_fast_link_failover_policy + node_802_1x_authentication_policy: changed_node_802_1x_authentication_policy + copp_pre_filter_policy: changed_copp_pre_filter_policy + equipment_flash_policy: changed_equipment_flash_policy + cdp_policy: changed_cdp_policy + lldp_policy: changed_lldp_policy + sync_e_node_policy: changed_sync_e_node_policy + usb_configuration_policy: changed_usb_configuration_policy + register: nm_change_leaf_policy_group + when: version.current.0.topSystem.attributes.version is version('5.2', '>=') + + - name: Verify change of access switch leaf policy group for version 4.2(7s) + ansible.builtin.assert: + that: + - nm_change_leaf_policy_group_5_2 is changed + - nm_change_leaf_policy_group_5_2.current.0.infraAccNodePGrp.children.0.infraRsTopoctrlFwdScaleProfPol.attributes.tnTopoctrlFwdScaleProfilePolName == "changed_forward_scale_profile_policy" + - nm_change_leaf_policy_group_5_2.current.0.infraAccNodePGrp.children.1.infraRsPoeInstPol.attributes.tnPoeInstPolName == "changed_poe_node_policy" + - nm_change_leaf_policy_group_5_2.current.0.infraAccNodePGrp.children.2.infraRsBfdIpv6InstPol.attributes.tnBfdIpv6InstPolName == "changed_bfd_ipv6_policy" + - nm_change_leaf_policy_group_5_2.current.0.infraAccNodePGrp.children.3.infraRsEquipmentFlashConfigPol.attributes.tnEquipmentFlashConfigPolName == "changed_equipment_flash_policy" + - nm_change_leaf_policy_group_5_2.current.0.infraAccNodePGrp.children.4.infraRsMonNodeInfraPol.attributes.tnMonInfraPolName == "changed_monitoring_policy" + - nm_change_leaf_policy_group_5_2.current.0.infraAccNodePGrp.children.5.infraRsFcInstPol.attributes.tnFcInstPolName == "changed_fibre_channel_node_policy" + - nm_change_leaf_policy_group_5_2.current.0.infraAccNodePGrp.children.6.infraRsBfdIpv4InstPol.attributes.tnBfdIpv4InstPolName == "changed_bfd_ipv4_policy" + - nm_change_leaf_policy_group_5_2.current.0.infraAccNodePGrp.children.7.infraRsL2NodeAuthPol.attributes.tnL2NodeAuthPolName == "changed_node_802_1x_authentication_policy" + - nm_change_leaf_policy_group_5_2.current.0.infraAccNodePGrp.children.8.infraRsTopoctrlFastLinkFailoverInstPol.attributes.tnTopoctrlFastLinkFailoverInstPolName == "changed_fast_link_failover_policy" + - nm_change_leaf_policy_group_5_2.current.0.infraAccNodePGrp.children.9.infraRsMstInstPol.attributes.tnStpInstPolName == "changed_spanning_tree_policy" + - nm_change_leaf_policy_group_5_2.current.0.infraAccNodePGrp.children.10.infraRsFcFabricPol.attributes.tnFcFabricPolName == "changed_fibre_channel_san_policy" + - nm_change_leaf_policy_group_5_2.current.0.infraAccNodePGrp.children.11.infraRsIaclLeafProfile.attributes.tnIaclLeafProfileName == "changed_copp_pre_filter_policy" + - nm_change_leaf_policy_group_5_2.current.0.infraAccNodePGrp.children.12.infraRsLeafCoppProfile.attributes.tnCoppLeafProfileName == "changed_copp_policy" + - nm_change_leaf_policy_group_5_2.current.0.infraAccNodePGrp.children.13.infraRsLeafPGrpToCdpIfPol.attributes.tnCdpIfPolName == "changed_cdp_policy" + - nm_change_leaf_policy_group_5_2.current.0.infraAccNodePGrp.children.14.infraRsLeafPGrpToLldpIfPol.attributes.tnLldpIfPolName == "changed_lldp_policy" + - nm_change_leaf_policy_group_5_2.previous.0.infraAccNodePGrp.children.0.infraRsTopoctrlFwdScaleProfPol.attributes.tnTopoctrlFwdScaleProfilePolName == "" + - nm_change_leaf_policy_group_5_2.previous.0.infraAccNodePGrp.children.1.infraRsPoeInstPol.attributes.tnPoeInstPolName == "" + - nm_change_leaf_policy_group_5_2.previous.0.infraAccNodePGrp.children.2.infraRsBfdIpv6InstPol.attributes.tnBfdIpv6InstPolName == "" + - nm_change_leaf_policy_group_5_2.previous.0.infraAccNodePGrp.children.3.infraRsEquipmentFlashConfigPol.attributes.tnEquipmentFlashConfigPolName == "" + - nm_change_leaf_policy_group_5_2.previous.0.infraAccNodePGrp.children.4.infraRsMonNodeInfraPol.attributes.tnMonInfraPolName == "" + - nm_change_leaf_policy_group_5_2.previous.0.infraAccNodePGrp.children.5.infraRsFcInstPol.attributes.tnFcInstPolName == "" + - nm_change_leaf_policy_group_5_2.previous.0.infraAccNodePGrp.children.6.infraRsBfdIpv4InstPol.attributes.tnBfdIpv4InstPolName == "" + - nm_change_leaf_policy_group_5_2.previous.0.infraAccNodePGrp.children.7.infraRsL2NodeAuthPol.attributes.tnL2NodeAuthPolName == "" + - nm_change_leaf_policy_group_5_2.previous.0.infraAccNodePGrp.children.8.infraRsTopoctrlFastLinkFailoverInstPol.attributes.tnTopoctrlFastLinkFailoverInstPolName == "" + - nm_change_leaf_policy_group_5_2.previous.0.infraAccNodePGrp.children.9.infraRsMstInstPol.attributes.tnStpInstPolName == "" + - nm_change_leaf_policy_group_5_2.previous.0.infraAccNodePGrp.children.10.infraRsFcFabricPol.attributes.tnFcFabricPolName == "" + - nm_change_leaf_policy_group_5_2.previous.0.infraAccNodePGrp.children.11.infraRsIaclLeafProfile.attributes.tnIaclLeafProfileName == "" + - nm_change_leaf_policy_group_5_2.previous.0.infraAccNodePGrp.children.12.infraRsLeafCoppProfile.attributes.tnCoppLeafProfileName == "" + - nm_change_leaf_policy_group_5_2.previous.0.infraAccNodePGrp.children.13.infraRsLeafPGrpToCdpIfPol.attributes.tnCdpIfPolName == "" + - nm_change_leaf_policy_group_5_2.previous.0.infraAccNodePGrp.children.14.infraRsLeafPGrpToLldpIfPol.attributes.tnLldpIfPolName == "" + when: version.current.0.topSystem.attributes.version == "4.2(7s)" + + - name: Verify change of access switch leaf policy group for version 5.2(5c) + ansible.builtin.assert: + that: + - nm_change_leaf_policy_group is changed + - nm_change_leaf_policy_group.current.0.infraAccNodePGrp.children.0.infraRsTopoctrlFwdScaleProfPol.attributes.tnTopoctrlFwdScaleProfilePolName == "changed_forward_scale_profile_policy" + - nm_change_leaf_policy_group.current.0.infraAccNodePGrp.children.1.infraRsLeafTopoctrlUsbConfigProfilePol.attributes.tnTopoctrlUsbConfigProfilePolName == "changed_usb_configuration_policy" + - nm_change_leaf_policy_group.current.0.infraAccNodePGrp.children.2.infraRsLeafPGrpToLldpIfPol.attributes.tnLldpIfPolName == "changed_lldp_policy" + - nm_change_leaf_policy_group.current.0.infraAccNodePGrp.children.3.infraRsLeafPGrpToCdpIfPol.attributes.tnCdpIfPolName == "changed_cdp_policy" + - nm_change_leaf_policy_group.current.0.infraAccNodePGrp.children.4.infraRsBfdIpv6InstPol.attributes.tnBfdIpv6InstPolName == "changed_bfd_ipv6_policy" + - nm_change_leaf_policy_group.current.0.infraAccNodePGrp.children.5.infraRsSynceInstPol.attributes.tnSynceInstPolName == "changed_sync_e_node_policy" + - nm_change_leaf_policy_group.current.0.infraAccNodePGrp.children.6.infraRsPoeInstPol.attributes.tnPoeInstPolName == "changed_poe_node_policy" + - nm_change_leaf_policy_group.current.0.infraAccNodePGrp.children.7.infraRsBfdMhIpv4InstPol.attributes.tnBfdMhIpv4InstPolName == "changed_bfd_multihop_ipv4_policy" + - nm_change_leaf_policy_group.current.0.infraAccNodePGrp.children.8.infraRsBfdMhIpv6InstPol.attributes.tnBfdMhIpv6InstPolName == "changed_bfd_multihop_ipv6_policy" + - nm_change_leaf_policy_group.current.0.infraAccNodePGrp.children.9.infraRsEquipmentFlashConfigPol.attributes.tnEquipmentFlashConfigPolName == "changed_equipment_flash_policy" + - nm_change_leaf_policy_group.current.0.infraAccNodePGrp.children.10.infraRsMonNodeInfraPol.attributes.tnMonInfraPolName == "changed_monitoring_policy" + - nm_change_leaf_policy_group.current.0.infraAccNodePGrp.children.11.infraRsFcInstPol.attributes.tnFcInstPolName == "changed_fibre_channel_node_policy" + - nm_change_leaf_policy_group.current.0.infraAccNodePGrp.children.12.infraRsTopoctrlFastLinkFailoverInstPol.attributes.tnTopoctrlFastLinkFailoverInstPolName == "changed_fast_link_failover_policy" + - nm_change_leaf_policy_group.current.0.infraAccNodePGrp.children.13.infraRsMstInstPol.attributes.tnStpInstPolName == "changed_spanning_tree_policy" + - nm_change_leaf_policy_group.current.0.infraAccNodePGrp.children.14.infraRsFcFabricPol.attributes.tnFcFabricPolName == "changed_fibre_channel_san_policy" + - nm_change_leaf_policy_group.current.0.infraAccNodePGrp.children.15.infraRsLeafCoppProfile.attributes.tnCoppLeafProfileName == "changed_copp_policy" + - nm_change_leaf_policy_group.current.0.infraAccNodePGrp.children.16.infraRsIaclLeafProfile.attributes.tnIaclLeafProfileName == "changed_copp_pre_filter_policy" + - nm_change_leaf_policy_group.current.0.infraAccNodePGrp.children.17.infraRsBfdIpv4InstPol.attributes.tnBfdIpv4InstPolName == "changed_bfd_ipv4_policy" + - nm_change_leaf_policy_group.current.0.infraAccNodePGrp.children.18.infraRsL2NodeAuthPol.attributes.tnL2NodeAuthPolName == "changed_node_802_1x_authentication_policy" + - nm_change_leaf_policy_group.previous.0.infraAccNodePGrp.children.0.infraRsTopoctrlFwdScaleProfPol.attributes.tnTopoctrlFwdScaleProfilePolName == "" + - nm_change_leaf_policy_group.previous.0.infraAccNodePGrp.children.1.infraRsLeafTopoctrlUsbConfigProfilePol.attributes.tnTopoctrlUsbConfigProfilePolName == "" + - nm_change_leaf_policy_group.previous.0.infraAccNodePGrp.children.2.infraRsLeafPGrpToLldpIfPol.attributes.tnLldpIfPolName == "" + - nm_change_leaf_policy_group.previous.0.infraAccNodePGrp.children.3.infraRsLeafPGrpToCdpIfPol.attributes.tnCdpIfPolName == "" + - nm_change_leaf_policy_group.previous.0.infraAccNodePGrp.children.4.infraRsBfdIpv6InstPol.attributes.tnBfdIpv6InstPolName == "" + - nm_change_leaf_policy_group.previous.0.infraAccNodePGrp.children.5.infraRsSynceInstPol.attributes.tnSynceInstPolName == "" + - nm_change_leaf_policy_group.previous.0.infraAccNodePGrp.children.6.infraRsPoeInstPol.attributes.tnPoeInstPolName == "" + - nm_change_leaf_policy_group.previous.0.infraAccNodePGrp.children.7.infraRsBfdMhIpv4InstPol.attributes.tnBfdMhIpv4InstPolName == "" + - nm_change_leaf_policy_group.previous.0.infraAccNodePGrp.children.8.infraRsBfdMhIpv6InstPol.attributes.tnBfdMhIpv6InstPolName == "" + - nm_change_leaf_policy_group.previous.0.infraAccNodePGrp.children.9.infraRsEquipmentFlashConfigPol.attributes.tnEquipmentFlashConfigPolName == "" + - nm_change_leaf_policy_group.previous.0.infraAccNodePGrp.children.10.infraRsMonNodeInfraPol.attributes.tnMonInfraPolName == "" + - nm_change_leaf_policy_group.previous.0.infraAccNodePGrp.children.11.infraRsFcInstPol.attributes.tnFcInstPolName == "" + - nm_change_leaf_policy_group.previous.0.infraAccNodePGrp.children.12.infraRsTopoctrlFastLinkFailoverInstPol.attributes.tnTopoctrlFastLinkFailoverInstPolName == "" + - nm_change_leaf_policy_group.previous.0.infraAccNodePGrp.children.13.infraRsMstInstPol.attributes.tnStpInstPolName == "" + - nm_change_leaf_policy_group.previous.0.infraAccNodePGrp.children.14.infraRsFcFabricPol.attributes.tnFcFabricPolName == "" + - nm_change_leaf_policy_group.previous.0.infraAccNodePGrp.children.15.infraRsLeafCoppProfile.attributes.tnCoppLeafProfileName == "" + - nm_change_leaf_policy_group.previous.0.infraAccNodePGrp.children.16.infraRsIaclLeafProfile.attributes.tnIaclLeafProfileName == "" + - nm_change_leaf_policy_group.previous.0.infraAccNodePGrp.children.17.infraRsBfdIpv4InstPol.attributes.tnBfdIpv4InstPolName == "" + - nm_change_leaf_policy_group.previous.0.infraAccNodePGrp.children.18.infraRsL2NodeAuthPol.attributes.tnL2NodeAuthPolName == "" + when: version.current.0.topSystem.attributes.version == "5.2(5c)" + + - name: Verify change of access switch leaf policy group for version 6.0(2h) + ansible.builtin.assert: + that: + - nm_change_leaf_policy_group is changed + - nm_change_leaf_policy_group.current.0.infraAccNodePGrp.children.0.infraRsTopoctrlFwdScaleProfPol.attributes.tnTopoctrlFwdScaleProfilePolName == "changed_forward_scale_profile_policy" + - nm_change_leaf_policy_group.current.0.infraAccNodePGrp.children.1.infraRsLeafTopoctrlUsbConfigProfilePol.attributes.tnTopoctrlUsbConfigProfilePolName == "changed_usb_configuration_policy" + - nm_change_leaf_policy_group.current.0.infraAccNodePGrp.children.2.infraRsLeafPGrpToLldpIfPol.attributes.tnLldpIfPolName == "changed_lldp_policy" + - nm_change_leaf_policy_group.current.0.infraAccNodePGrp.children.3.infraRsBfdIpv6InstPol.attributes.tnBfdIpv6InstPolName == "changed_bfd_ipv6_policy" + - nm_change_leaf_policy_group.current.0.infraAccNodePGrp.children.4.infraRsSynceInstPol.attributes.tnSynceInstPolName == "changed_sync_e_node_policy" + - nm_change_leaf_policy_group.current.0.infraAccNodePGrp.children.5.infraRsPoeInstPol.attributes.tnPoeInstPolName == "changed_poe_node_policy" + - nm_change_leaf_policy_group.current.0.infraAccNodePGrp.children.6.infraRsBfdMhIpv4InstPol.attributes.tnBfdMhIpv4InstPolName == "changed_bfd_multihop_ipv4_policy" + - nm_change_leaf_policy_group.current.0.infraAccNodePGrp.children.7.infraRsBfdMhIpv6InstPol.attributes.tnBfdMhIpv6InstPolName == "changed_bfd_multihop_ipv6_policy" + - nm_change_leaf_policy_group.current.0.infraAccNodePGrp.children.8.infraRsEquipmentFlashConfigPol.attributes.tnEquipmentFlashConfigPolName == "changed_equipment_flash_policy" + - nm_change_leaf_policy_group.current.0.infraAccNodePGrp.children.9.infraRsMonNodeInfraPol.attributes.tnMonInfraPolName == "changed_monitoring_policy" + - nm_change_leaf_policy_group.current.0.infraAccNodePGrp.children.10.infraRsFcInstPol.attributes.tnFcInstPolName == "changed_fibre_channel_node_policy" + - nm_change_leaf_policy_group.current.0.infraAccNodePGrp.children.11.infraRsTopoctrlFastLinkFailoverInstPol.attributes.tnTopoctrlFastLinkFailoverInstPolName == "changed_fast_link_failover_policy" + - nm_change_leaf_policy_group.current.0.infraAccNodePGrp.children.12.infraRsMstInstPol.attributes.tnStpInstPolName == "changed_spanning_tree_policy" + - nm_change_leaf_policy_group.current.0.infraAccNodePGrp.children.13.infraRsFcFabricPol.attributes.tnFcFabricPolName == "changed_fibre_channel_san_policy" + - nm_change_leaf_policy_group.current.0.infraAccNodePGrp.children.14.infraRsLeafCoppProfile.attributes.tnCoppLeafProfileName == "changed_copp_policy" + - nm_change_leaf_policy_group.current.0.infraAccNodePGrp.children.15.infraRsIaclLeafProfile.attributes.tnIaclLeafProfileName == "changed_copp_pre_filter_policy" + - nm_change_leaf_policy_group.current.0.infraAccNodePGrp.children.16.infraRsBfdIpv4InstPol.attributes.tnBfdIpv4InstPolName == "changed_bfd_ipv4_policy" + - nm_change_leaf_policy_group.current.0.infraAccNodePGrp.children.17.infraRsL2NodeAuthPol.attributes.tnL2NodeAuthPolName == "changed_node_802_1x_authentication_policy" + - nm_change_leaf_policy_group.current.0.infraAccNodePGrp.children.18.infraRsLeafPGrpToCdpIfPol.attributes.tnCdpIfPolName == "changed_cdp_policy" + - nm_change_leaf_policy_group.previous.0.infraAccNodePGrp.children.0.infraRsTopoctrlFwdScaleProfPol.attributes.tnTopoctrlFwdScaleProfilePolName == "" + - nm_change_leaf_policy_group.previous.0.infraAccNodePGrp.children.1.infraRsLeafTopoctrlUsbConfigProfilePol.attributes.tnTopoctrlUsbConfigProfilePolName == "" + - nm_change_leaf_policy_group.previous.0.infraAccNodePGrp.children.2.infraRsLeafPGrpToLldpIfPol.attributes.tnLldpIfPolName == "" + - nm_change_leaf_policy_group.previous.0.infraAccNodePGrp.children.3.infraRsBfdIpv6InstPol.attributes.tnBfdIpv6InstPolName == "" + - nm_change_leaf_policy_group.previous.0.infraAccNodePGrp.children.4.infraRsSynceInstPol.attributes.tnSynceInstPolName == "" + - nm_change_leaf_policy_group.previous.0.infraAccNodePGrp.children.5.infraRsPoeInstPol.attributes.tnPoeInstPolName == "" + - nm_change_leaf_policy_group.previous.0.infraAccNodePGrp.children.6.infraRsBfdMhIpv4InstPol.attributes.tnBfdMhIpv4InstPolName == "" + - nm_change_leaf_policy_group.previous.0.infraAccNodePGrp.children.7.infraRsBfdMhIpv6InstPol.attributes.tnBfdMhIpv6InstPolName == "" + - nm_change_leaf_policy_group.previous.0.infraAccNodePGrp.children.8.infraRsEquipmentFlashConfigPol.attributes.tnEquipmentFlashConfigPolName == "" + - nm_change_leaf_policy_group.previous.0.infraAccNodePGrp.children.9.infraRsMonNodeInfraPol.attributes.tnMonInfraPolName == "" + - nm_change_leaf_policy_group.previous.0.infraAccNodePGrp.children.10.infraRsFcInstPol.attributes.tnFcInstPolName == "" + - nm_change_leaf_policy_group.previous.0.infraAccNodePGrp.children.11.infraRsTopoctrlFastLinkFailoverInstPol.attributes.tnTopoctrlFastLinkFailoverInstPolName == "" + - nm_change_leaf_policy_group.previous.0.infraAccNodePGrp.children.12.infraRsMstInstPol.attributes.tnStpInstPolName == "" + - nm_change_leaf_policy_group.previous.0.infraAccNodePGrp.children.13.infraRsFcFabricPol.attributes.tnFcFabricPolName == "" + - nm_change_leaf_policy_group.previous.0.infraAccNodePGrp.children.14.infraRsLeafCoppProfile.attributes.tnCoppLeafProfileName == "" + - nm_change_leaf_policy_group.previous.0.infraAccNodePGrp.children.15.infraRsIaclLeafProfile.attributes.tnIaclLeafProfileName == "" + - nm_change_leaf_policy_group.previous.0.infraAccNodePGrp.children.16.infraRsBfdIpv4InstPol.attributes.tnBfdIpv4InstPolName == "" + - nm_change_leaf_policy_group.previous.0.infraAccNodePGrp.children.17.infraRsL2NodeAuthPol.attributes.tnL2NodeAuthPolName == "" + - nm_change_leaf_policy_group.previous.0.infraAccNodePGrp.children.18.infraRsLeafPGrpToCdpIfPol.attributes.tnCdpIfPolName == "" + when: version.current.0.topSystem.attributes.version == "6.0(2h)" + + - name: Verify change of access switch leaf policy group for version 6.0(1g) + ansible.builtin.assert: + that: + - nm_change_leaf_policy_group is changed + - nm_change_leaf_policy_group.current.0.infraAccNodePGrp.children.0.infraRsTopoctrlFwdScaleProfPol.attributes.tnTopoctrlFwdScaleProfilePolName == "changed_forward_scale_profile_policy" + - nm_change_leaf_policy_group.current.0.infraAccNodePGrp.children.1.infraRsLeafTopoctrlUsbConfigProfilePol.attributes.tnTopoctrlUsbConfigProfilePolName == "changed_usb_configuration_policy" + - nm_change_leaf_policy_group.current.0.infraAccNodePGrp.children.2.infraRsLeafPGrpToLldpIfPol.attributes.tnLldpIfPolName == "changed_lldp_policy" + - nm_change_leaf_policy_group.current.0.infraAccNodePGrp.children.3.infraRsLeafPGrpToCdpIfPol.attributes.tnCdpIfPolName == "changed_cdp_policy" + - nm_change_leaf_policy_group.current.0.infraAccNodePGrp.children.4.infraRsBfdIpv6InstPol.attributes.tnBfdIpv6InstPolName == "changed_bfd_ipv6_policy" + - nm_change_leaf_policy_group.current.0.infraAccNodePGrp.children.5.infraRsSynceInstPol.attributes.tnSynceInstPolName == "changed_sync_e_node_policy" + - nm_change_leaf_policy_group.current.0.infraAccNodePGrp.children.6.infraRsPoeInstPol.attributes.tnPoeInstPolName == "changed_poe_node_policy" + - nm_change_leaf_policy_group.current.0.infraAccNodePGrp.children.7.infraRsBfdMhIpv4InstPol.attributes.tnBfdMhIpv4InstPolName == "changed_bfd_multihop_ipv4_policy" + - nm_change_leaf_policy_group.current.0.infraAccNodePGrp.children.8.infraRsBfdMhIpv6InstPol.attributes.tnBfdMhIpv6InstPolName == "changed_bfd_multihop_ipv6_policy" + - nm_change_leaf_policy_group.current.0.infraAccNodePGrp.children.9.infraRsEquipmentFlashConfigPol.attributes.tnEquipmentFlashConfigPolName == "changed_equipment_flash_policy" + - nm_change_leaf_policy_group.current.0.infraAccNodePGrp.children.10.infraRsMonNodeInfraPol.attributes.tnMonInfraPolName == "changed_monitoring_policy" + - nm_change_leaf_policy_group.current.0.infraAccNodePGrp.children.11.infraRsFcInstPol.attributes.tnFcInstPolName == "changed_fibre_channel_node_policy" + - nm_change_leaf_policy_group.current.0.infraAccNodePGrp.children.12.infraRsTopoctrlFastLinkFailoverInstPol.attributes.tnTopoctrlFastLinkFailoverInstPolName == "changed_fast_link_failover_policy" + - nm_change_leaf_policy_group.current.0.infraAccNodePGrp.children.13.infraRsMstInstPol.attributes.tnStpInstPolName == "changed_spanning_tree_policy" + - nm_change_leaf_policy_group.current.0.infraAccNodePGrp.children.14.infraRsFcFabricPol.attributes.tnFcFabricPolName == "changed_fibre_channel_san_policy" + - nm_change_leaf_policy_group.current.0.infraAccNodePGrp.children.15.infraRsLeafCoppProfile.attributes.tnCoppLeafProfileName == "changed_copp_policy" + - nm_change_leaf_policy_group.current.0.infraAccNodePGrp.children.16.infraRsIaclLeafProfile.attributes.tnIaclLeafProfileName == "changed_copp_pre_filter_policy" + - nm_change_leaf_policy_group.current.0.infraAccNodePGrp.children.17.infraRsBfdIpv4InstPol.attributes.tnBfdIpv4InstPolName == "changed_bfd_ipv4_policy" + - nm_change_leaf_policy_group.current.0.infraAccNodePGrp.children.18.infraRsL2NodeAuthPol.attributes.tnL2NodeAuthPolName == "changed_node_802_1x_authentication_policy" + - nm_change_leaf_policy_group.previous.0.infraAccNodePGrp.children.0.infraRsTopoctrlFwdScaleProfPol.attributes.tnTopoctrlFwdScaleProfilePolName == "" + - nm_change_leaf_policy_group.previous.0.infraAccNodePGrp.children.1.infraRsLeafTopoctrlUsbConfigProfilePol.attributes.tnTopoctrlUsbConfigProfilePolName == "" + - nm_change_leaf_policy_group.previous.0.infraAccNodePGrp.children.2.infraRsLeafPGrpToLldpIfPol.attributes.tnLldpIfPolName == "" + - nm_change_leaf_policy_group.previous.0.infraAccNodePGrp.children.3.infraRsLeafPGrpToCdpIfPol.attributes.tnCdpIfPolName == "" + - nm_change_leaf_policy_group.previous.0.infraAccNodePGrp.children.4.infraRsBfdIpv6InstPol.attributes.tnBfdIpv6InstPolName == "" + - nm_change_leaf_policy_group.previous.0.infraAccNodePGrp.children.5.infraRsSynceInstPol.attributes.tnSynceInstPolName == "" + - nm_change_leaf_policy_group.previous.0.infraAccNodePGrp.children.6.infraRsPoeInstPol.attributes.tnPoeInstPolName == "" + - nm_change_leaf_policy_group.previous.0.infraAccNodePGrp.children.7.infraRsBfdMhIpv4InstPol.attributes.tnBfdMhIpv4InstPolName == "" + - nm_change_leaf_policy_group.previous.0.infraAccNodePGrp.children.8.infraRsBfdMhIpv6InstPol.attributes.tnBfdMhIpv6InstPolName == "" + - nm_change_leaf_policy_group.previous.0.infraAccNodePGrp.children.9.infraRsEquipmentFlashConfigPol.attributes.tnEquipmentFlashConfigPolName == "" + - nm_change_leaf_policy_group.previous.0.infraAccNodePGrp.children.10.infraRsMonNodeInfraPol.attributes.tnMonInfraPolName == "" + - nm_change_leaf_policy_group.previous.0.infraAccNodePGrp.children.11.infraRsFcInstPol.attributes.tnFcInstPolName == "" + - nm_change_leaf_policy_group.previous.0.infraAccNodePGrp.children.12.infraRsTopoctrlFastLinkFailoverInstPol.attributes.tnTopoctrlFastLinkFailoverInstPolName == "" + - nm_change_leaf_policy_group.previous.0.infraAccNodePGrp.children.13.infraRsMstInstPol.attributes.tnStpInstPolName == "" + - nm_change_leaf_policy_group.previous.0.infraAccNodePGrp.children.14.infraRsFcFabricPol.attributes.tnFcFabricPolName == "" + - nm_change_leaf_policy_group.previous.0.infraAccNodePGrp.children.15.infraRsLeafCoppProfile.attributes.tnCoppLeafProfileName == "" + - nm_change_leaf_policy_group.previous.0.infraAccNodePGrp.children.16.infraRsIaclLeafProfile.attributes.tnIaclLeafProfileName == "" + - nm_change_leaf_policy_group.previous.0.infraAccNodePGrp.children.17.infraRsBfdIpv4InstPol.attributes.tnBfdIpv4InstPolName == "" + - nm_change_leaf_policy_group.previous.0.infraAccNodePGrp.children.18.infraRsL2NodeAuthPol.attributes.tnL2NodeAuthPolName == "" + when: version.current.0.topSystem.attributes.version == "6.0(1g)" + + - name: Create netflow_node_policy in the ansible access switch leaf policy group 2 + cisco.aci.aci_access_switch_policy_group: &aci_create_leaf_policy_group_2 + <<: *aci_create_leaf_policy_group + name: ansible_access_switch_leaf_pol_grp_2 + netflow_node_policy: create_netflow_node_policy + register: nm_netflow_create + + - name: Change netflow_node_policy in the ansible access switch leaf policy group 2 + cisco.aci.aci_access_switch_policy_group: + <<: *aci_create_leaf_policy_group_2 + netflow_node_policy: changed_netflow_node_policy + register: nm_netflow_change + + - name: Create ptp_node_policy in the ansible access switch leaf policy group 2 for version >= 5.2 + cisco.aci.aci_access_switch_policy_group: + <<: *aci_create_leaf_policy_group_2 + ptp_node_policy: create_ptp_node_policy + register: nm_ptp_create + when: version.current.0.topSystem.attributes.version is version('5.2', '>=') + + - name: Change ptp_node_policy in the ansible access switch leaf policy group 2 for version >= 5.2 + cisco.aci.aci_access_switch_policy_group: + <<: *aci_create_leaf_policy_group_2 + ptp_node_policy: changed_ptp_node_policy + register: nm_ptp_change + when: version.current.0.topSystem.attributes.version is version('5.2', '>=') + + - name: Verify netflow_node_policy leaf policy group for version 4.2(7s) + ansible.builtin.assert: + that: + - nm_netflow_create is changed + - nm_netflow_create.current.0.infraAccNodePGrp.children.2.infraRsNetflowNodePol.attributes.tnNetflowNodePolName == "create_netflow_node_policy" + - nm_netflow_change is changed + - nm_netflow_change.current.0.infraAccNodePGrp.children.2.infraRsNetflowNodePol.attributes.tnNetflowNodePolName == "changed_netflow_node_policy" + when: version.current.0.topSystem.attributes.version == "4.2(7s)" + + - name: Verify netflow_node_policy and ptp_node_policy leaf policy group for version 5.2(5c) + ansible.builtin.assert: + that: + - nm_netflow_create is changed + - nm_netflow_create.current.0.infraAccNodePGrp.children.1.infraRsNetflowNodePol.attributes.tnNetflowNodePolName == "create_netflow_node_policy" + - nm_netflow_change is changed + - nm_netflow_change.current.0.infraAccNodePGrp.children.1.infraRsNetflowNodePol.attributes.tnNetflowNodePolName == "changed_netflow_node_policy" + - nm_ptp_create is changed + - nm_ptp_create.current.0.infraAccNodePGrp.children.10.infraRsPtpInstPol.attributes.tnPtpInstPolName == "create_ptp_node_policy" + - nm_ptp_change is changed + - nm_ptp_change.current.0.infraAccNodePGrp.children.10.infraRsPtpInstPol.attributes.tnPtpInstPolName == "changed_ptp_node_policy" + when: version.current.0.topSystem.attributes.version == "5.2(5c)" + + - name: Verify netflow_node_policy and ptp_node_policy leaf policy group for version 6.0(2h) + ansible.builtin.assert: + that: + - nm_netflow_create is changed + - nm_netflow_create.current.0.infraAccNodePGrp.children.1.infraRsNetflowNodePol.attributes.tnNetflowNodePolName == "create_netflow_node_policy" + - nm_netflow_change is changed + - nm_netflow_change.current.0.infraAccNodePGrp.children.1.infraRsNetflowNodePol.attributes.tnNetflowNodePolName == "changed_netflow_node_policy" + - nm_ptp_create is changed + - nm_ptp_create.current.0.infraAccNodePGrp.children.9.infraRsPtpInstPol.attributes.tnPtpInstPolName == "create_ptp_node_policy" + - nm_ptp_change is changed + - nm_ptp_change.current.0.infraAccNodePGrp.children.9.infraRsPtpInstPol.attributes.tnPtpInstPolName == "changed_ptp_node_policy" + when: version.current.0.topSystem.attributes.version == "6.0(2h)" + + - name: Verify netflow_node_policy and ptp_node_policy leaf policy group for version 6.0(1g) + ansible.builtin.assert: + that: + - nm_netflow_create is changed + - nm_netflow_create.current.0.infraAccNodePGrp.children.1.infraRsNetflowNodePol.attributes.tnNetflowNodePolName == "create_netflow_node_policy" + - nm_netflow_change is changed + - nm_netflow_change.current.0.infraAccNodePGrp.children.1.infraRsNetflowNodePol.attributes.tnNetflowNodePolName == "changed_netflow_node_policy" + - nm_ptp_create is changed + - nm_ptp_create.current.0.infraAccNodePGrp.children.10.infraRsPtpInstPol.attributes.tnPtpInstPolName == "create_ptp_node_policy" + - nm_ptp_change is changed + - nm_ptp_change.current.0.infraAccNodePGrp.children.10.infraRsPtpInstPol.attributes.tnPtpInstPolName == "changed_ptp_node_policy" + when: version.current.0.topSystem.attributes.version == "6.0(1g)" + + - name: Query the ansible access switch leaf policy group 2 + cisco.aci.aci_access_switch_policy_group: + <<: *aci_create_leaf_policy_group_2 + state: query + register: query_one + + - name: Query all the ansible access switch leaf policy groups + cisco.aci.aci_access_switch_policy_group: + <<: *aci_info + switch_type: leaf + state: query + register: query_all + + - name: Verify remove of access switch policy + ansible.builtin.assert: + that: + - query_one is not changed + - query_one.current | length == 1 + - query_all is not changed + - query_all.current | length > 1 + + - name: Remove the ansible access switch leaf policy group (check mode) + cisco.aci.aci_access_switch_policy_group: &aci_remove_leaf_policy_group + <<: *aci_info + switch_type: leaf + name: ansible_access_switch_leaf_pol_grp + state: absent + check_mode: true + register: cm_remove_leaf_policy_group + + - name: Remove the ansible access switch leaf policy group + cisco.aci.aci_access_switch_policy_group: + <<: *aci_remove_leaf_policy_group + register: nm_remove_leaf_policy_group + + - name: Remove the ansible access switch leaf policy group again + cisco.aci.aci_access_switch_policy_group: + <<: *aci_remove_leaf_policy_group + register: nm_remove_leaf_policy_group_again + + - name: Verify remove of access switch leaf policy group + ansible.builtin.assert: + that: + - cm_remove_leaf_policy_group is changed + - nm_remove_leaf_policy_group.previous != [] + - nm_remove_leaf_policy_group.proposed == {} + - nm_remove_leaf_policy_group is changed + - nm_remove_leaf_policy_group.previous != [] + - nm_remove_leaf_policy_group.current == [] + - nm_remove_leaf_policy_group_again is not changed + - nm_remove_leaf_policy_group_again.previous == [] + - nm_remove_leaf_policy_group_again.current == [] + + # ACCESS SWITCH SPINE POLICY GROUP + - name: Create the ansible access switch spine policy group (check mode) + cisco.aci.aci_access_switch_policy_group: &aci_create_spine_policy_group + <<: *aci_info + switch_type: spine + name: ansible_access_switch_spine_pol_grp + state: present + check_mode: yes + register: cm_create_spine_policy_group + + - name: Create the ansible access switch spine policy group + cisco.aci.aci_access_switch_policy_group: + <<: *aci_create_spine_policy_group + register: nm_create_spine_policy_group + + - name: Create the ansible access switch spine policy group again + cisco.aci.aci_access_switch_policy_group: + <<: *aci_create_spine_policy_group + register: nm_create_spine_policy_group_again + + - name: Verify creation of access switch spine policy group for version >= 5.2 + ansible.builtin.assert: + that: + - cm_create_spine_policy_group is changed + - cm_create_spine_policy_group.proposed.infraSpineAccNodePGrp.attributes.annotation == "orchestrator:ansible" + - cm_create_spine_policy_group.proposed.infraSpineAccNodePGrp.attributes.dn == "uni/infra/funcprof/spaccnodepgrp-ansible_access_switch_spine_pol_grp" + - cm_create_spine_policy_group.previous == [] + - cm_create_spine_policy_group.current == [] + - nm_create_spine_policy_group is changed + - nm_create_spine_policy_group.previous == [] + - nm_create_spine_policy_group.current.0.infraSpineAccNodePGrp.attributes.annotation == "orchestrator:ansible" + - nm_create_spine_policy_group.current.0.infraSpineAccNodePGrp.attributes.dn == "uni/infra/funcprof/spaccnodepgrp-ansible_access_switch_spine_pol_grp" + - nm_create_spine_policy_group.current.0.infraSpineAccNodePGrp.attributes.name == "ansible_access_switch_spine_pol_grp" + - nm_create_spine_policy_group.current.0.infraSpineAccNodePGrp.children.0.infraRsSpineTopoctrlUsbConfigProfilePol.attributes.tnTopoctrlUsbConfigProfilePolName == "" + - nm_create_spine_policy_group.current.0.infraSpineAccNodePGrp.children.1.infraRsSpinePGrpToLldpIfPol.attributes.tnLldpIfPolName == "" + - nm_create_spine_policy_group.current.0.infraSpineAccNodePGrp.children.2.infraRsSpinePGrpToCdpIfPol.attributes.tnCdpIfPolName == "" + - nm_create_spine_policy_group.current.0.infraSpineAccNodePGrp.children.3.infraRsSpineCoppProfile.attributes.tnCoppSpineProfileName == "" + - nm_create_spine_policy_group.current.0.infraSpineAccNodePGrp.children.4.infraRsSpineBfdIpv6InstPol.attributes.tnBfdIpv6InstPolName == "" + - nm_create_spine_policy_group.current.0.infraSpineAccNodePGrp.children.5.infraRsSpineBfdIpv4InstPol.attributes.tnBfdIpv4InstPolName == "" + - nm_create_spine_policy_group.current.0.infraSpineAccNodePGrp.children.6.infraRsIaclSpineProfile.attributes.tnIaclSpineProfileName == "" + - nm_create_spine_policy_group.previous == [] + - nm_create_spine_policy_group_again is not changed + - nm_create_spine_policy_group_again.current.0.infraSpineAccNodePGrp.attributes.annotation == "orchestrator:ansible" + - nm_create_spine_policy_group_again.current.0.infraSpineAccNodePGrp.attributes.dn == "uni/infra/funcprof/spaccnodepgrp-ansible_access_switch_spine_pol_grp" + - nm_create_spine_policy_group_again.current.0.infraSpineAccNodePGrp.attributes.name == "ansible_access_switch_spine_pol_grp" + - nm_create_spine_policy_group_again.current.0.infraSpineAccNodePGrp.children.0.infraRsSpineTopoctrlUsbConfigProfilePol.attributes.tnTopoctrlUsbConfigProfilePolName == "" + - nm_create_spine_policy_group_again.current.0.infraSpineAccNodePGrp.children.1.infraRsSpinePGrpToLldpIfPol.attributes.tnLldpIfPolName == "" + - nm_create_spine_policy_group_again.current.0.infraSpineAccNodePGrp.children.2.infraRsSpinePGrpToCdpIfPol.attributes.tnCdpIfPolName == "" + - nm_create_spine_policy_group_again.current.0.infraSpineAccNodePGrp.children.3.infraRsSpineCoppProfile.attributes.tnCoppSpineProfileName == "" + - nm_create_spine_policy_group_again.current.0.infraSpineAccNodePGrp.children.4.infraRsSpineBfdIpv6InstPol.attributes.tnBfdIpv6InstPolName == "" + - nm_create_spine_policy_group_again.current.0.infraSpineAccNodePGrp.children.5.infraRsSpineBfdIpv4InstPol.attributes.tnBfdIpv4InstPolName == "" + - nm_create_spine_policy_group_again.current.0.infraSpineAccNodePGrp.children.6.infraRsIaclSpineProfile.attributes.tnIaclSpineProfileName == "" + - nm_create_spine_policy_group_again.previous.0.infraSpineAccNodePGrp.attributes.annotation == "orchestrator:ansible" + - nm_create_spine_policy_group_again.previous.0.infraSpineAccNodePGrp.attributes.dn == "uni/infra/funcprof/spaccnodepgrp-ansible_access_switch_spine_pol_grp" + - nm_create_spine_policy_group_again.previous.0.infraSpineAccNodePGrp.attributes.name == "ansible_access_switch_spine_pol_grp" + - nm_create_spine_policy_group_again.previous.0.infraSpineAccNodePGrp.children.0.infraRsSpineTopoctrlUsbConfigProfilePol.attributes.tnTopoctrlUsbConfigProfilePolName == "" + - nm_create_spine_policy_group_again.previous.0.infraSpineAccNodePGrp.children.1.infraRsSpinePGrpToLldpIfPol.attributes.tnLldpIfPolName == "" + - nm_create_spine_policy_group_again.previous.0.infraSpineAccNodePGrp.children.2.infraRsSpinePGrpToCdpIfPol.attributes.tnCdpIfPolName == "" + - nm_create_spine_policy_group_again.previous.0.infraSpineAccNodePGrp.children.3.infraRsSpineCoppProfile.attributes.tnCoppSpineProfileName == "" + - nm_create_spine_policy_group_again.previous.0.infraSpineAccNodePGrp.children.4.infraRsSpineBfdIpv6InstPol.attributes.tnBfdIpv6InstPolName == "" + - nm_create_spine_policy_group_again.previous.0.infraSpineAccNodePGrp.children.5.infraRsSpineBfdIpv4InstPol.attributes.tnBfdIpv4InstPolName == "" + - nm_create_spine_policy_group_again.previous.0.infraSpineAccNodePGrp.children.6.infraRsIaclSpineProfile.attributes.tnIaclSpineProfileName == "" + when: version.current.0.topSystem.attributes.version is version('5.2', '>=') + + - name: Verify creation of access switch spine policy group for version < "5" + ansible.builtin.assert: + that: + - cm_create_spine_policy_group is changed + - cm_create_spine_policy_group.proposed.infraSpineAccNodePGrp.attributes.annotation == "orchestrator:ansible" + - cm_create_spine_policy_group.proposed.infraSpineAccNodePGrp.attributes.dn == "uni/infra/funcprof/spaccnodepgrp-ansible_access_switch_spine_pol_grp" + - cm_create_spine_policy_group.previous == [] + - cm_create_spine_policy_group.current == [] + - nm_create_spine_policy_group is changed + - nm_create_spine_policy_group.previous == [] + - nm_create_spine_policy_group.current.0.infraSpineAccNodePGrp.attributes.annotation == "orchestrator:ansible" + - nm_create_spine_policy_group.current.0.infraSpineAccNodePGrp.attributes.dn == "uni/infra/funcprof/spaccnodepgrp-ansible_access_switch_spine_pol_grp" + - nm_create_spine_policy_group.current.0.infraSpineAccNodePGrp.attributes.name == "ansible_access_switch_spine_pol_grp" + - nm_create_spine_policy_group.current.0.infraSpineAccNodePGrp.children.0.infraRsSpinePGrpToLldpIfPol.attributes.tnLldpIfPolName == "" + - nm_create_spine_policy_group.current.0.infraSpineAccNodePGrp.children.1.infraRsSpinePGrpToCdpIfPol.attributes.tnCdpIfPolName == "" + - nm_create_spine_policy_group.current.0.infraSpineAccNodePGrp.children.2.infraRsSpineCoppProfile.attributes.tnCoppSpineProfileName == "" + - nm_create_spine_policy_group.current.0.infraSpineAccNodePGrp.children.3.infraRsSpineBfdIpv6InstPol.attributes.tnBfdIpv6InstPolName == "" + - nm_create_spine_policy_group.current.0.infraSpineAccNodePGrp.children.4.infraRsSpineBfdIpv4InstPol.attributes.tnBfdIpv4InstPolName == "" + - nm_create_spine_policy_group.current.0.infraSpineAccNodePGrp.children.5.infraRsIaclSpineProfile.attributes.tnIaclSpineProfileName == "" + - nm_create_spine_policy_group.previous == [] + - nm_create_spine_policy_group_again is not changed + - nm_create_spine_policy_group_again.current.0.infraSpineAccNodePGrp.attributes.annotation == "orchestrator:ansible" + - nm_create_spine_policy_group_again.current.0.infraSpineAccNodePGrp.attributes.dn == "uni/infra/funcprof/spaccnodepgrp-ansible_access_switch_spine_pol_grp" + - nm_create_spine_policy_group_again.current.0.infraSpineAccNodePGrp.attributes.name == "ansible_access_switch_spine_pol_grp" + - nm_create_spine_policy_group_again.current.0.infraSpineAccNodePGrp.children.0.infraRsSpinePGrpToLldpIfPol.attributes.tnLldpIfPolName == "" + - nm_create_spine_policy_group_again.current.0.infraSpineAccNodePGrp.children.1.infraRsSpinePGrpToCdpIfPol.attributes.tnCdpIfPolName == "" + - nm_create_spine_policy_group_again.current.0.infraSpineAccNodePGrp.children.2.infraRsSpineCoppProfile.attributes.tnCoppSpineProfileName == "" + - nm_create_spine_policy_group_again.current.0.infraSpineAccNodePGrp.children.3.infraRsSpineBfdIpv6InstPol.attributes.tnBfdIpv6InstPolName == "" + - nm_create_spine_policy_group_again.current.0.infraSpineAccNodePGrp.children.4.infraRsSpineBfdIpv4InstPol.attributes.tnBfdIpv4InstPolName == "" + - nm_create_spine_policy_group_again.current.0.infraSpineAccNodePGrp.children.5.infraRsIaclSpineProfile.attributes.tnIaclSpineProfileName == "" + - nm_create_spine_policy_group_again.previous.0.infraSpineAccNodePGrp.attributes.annotation == "orchestrator:ansible" + - nm_create_spine_policy_group_again.previous.0.infraSpineAccNodePGrp.attributes.dn == "uni/infra/funcprof/spaccnodepgrp-ansible_access_switch_spine_pol_grp" + - nm_create_spine_policy_group_again.previous.0.infraSpineAccNodePGrp.attributes.name == "ansible_access_switch_spine_pol_grp" + - nm_create_spine_policy_group_again.previous.0.infraSpineAccNodePGrp.children.0.infraRsSpinePGrpToLldpIfPol.attributes.tnLldpIfPolName == "" + - nm_create_spine_policy_group_again.previous.0.infraSpineAccNodePGrp.children.1.infraRsSpinePGrpToCdpIfPol.attributes.tnCdpIfPolName == "" + - nm_create_spine_policy_group_again.previous.0.infraSpineAccNodePGrp.children.2.infraRsSpineCoppProfile.attributes.tnCoppSpineProfileName == "" + - nm_create_spine_policy_group_again.previous.0.infraSpineAccNodePGrp.children.3.infraRsSpineBfdIpv6InstPol.attributes.tnBfdIpv6InstPolName == "" + - nm_create_spine_policy_group_again.previous.0.infraSpineAccNodePGrp.children.4.infraRsSpineBfdIpv4InstPol.attributes.tnBfdIpv4InstPolName == "" + - nm_create_spine_policy_group_again.previous.0.infraSpineAccNodePGrp.children.5.infraRsIaclSpineProfile.attributes.tnIaclSpineProfileName == "" + when: version.current.0.topSystem.attributes.version is version('5.0', '<') + + - name: Change the ansible access switch spine policy group for version >= 5.2 + cisco.aci.aci_access_switch_policy_group: + <<: *aci_create_spine_policy_group + bfd_ipv4_policy: changed_bfd_ipv4_policy + bfd_ipv6_policy: changed_bfd_ipv6_policy + copp_policy: changed_copp_policy + copp_pre_filter_policy: changed_copp_pre_filter_policy + cdp_policy: changed_cdp_policy + lldp_policy: changed_lldp_policy + usb_configuration_policy: changed_usb_configuration_policy + register: nm_change_spine_policy_group + when: version.current.0.topSystem.attributes.version is version('5.2', '>=') + + - name: Verify change of access switch spine policy group for version >= 5.2 + ansible.builtin.assert: + that: + - nm_change_spine_policy_group is changed + - nm_change_spine_policy_group.current.0.infraSpineAccNodePGrp.attributes.annotation == "orchestrator:ansible" + - nm_change_spine_policy_group.current.0.infraSpineAccNodePGrp.attributes.dn == "uni/infra/funcprof/spaccnodepgrp-ansible_access_switch_spine_pol_grp" + - nm_change_spine_policy_group.current.0.infraSpineAccNodePGrp.attributes.name == "ansible_access_switch_spine_pol_grp" + - nm_change_spine_policy_group.current.0.infraSpineAccNodePGrp.children.0.infraRsSpineTopoctrlUsbConfigProfilePol.attributes.tnTopoctrlUsbConfigProfilePolName == "changed_usb_configuration_policy" + - nm_change_spine_policy_group.current.0.infraSpineAccNodePGrp.children.1.infraRsSpinePGrpToLldpIfPol.attributes.tnLldpIfPolName == "changed_lldp_policy" + - nm_change_spine_policy_group.current.0.infraSpineAccNodePGrp.children.2.infraRsSpinePGrpToCdpIfPol.attributes.tnCdpIfPolName == "changed_cdp_policy" + - nm_change_spine_policy_group.current.0.infraSpineAccNodePGrp.children.3.infraRsSpineCoppProfile.attributes.tnCoppSpineProfileName == "changed_copp_policy" + - nm_change_spine_policy_group.current.0.infraSpineAccNodePGrp.children.4.infraRsSpineBfdIpv6InstPol.attributes.tnBfdIpv6InstPolName == "changed_bfd_ipv6_policy" + - nm_change_spine_policy_group.current.0.infraSpineAccNodePGrp.children.5.infraRsSpineBfdIpv4InstPol.attributes.tnBfdIpv4InstPolName == "changed_bfd_ipv4_policy" + - nm_change_spine_policy_group.current.0.infraSpineAccNodePGrp.children.6.infraRsIaclSpineProfile.attributes.tnIaclSpineProfileName == "changed_copp_pre_filter_policy" + - nm_change_spine_policy_group.previous.0.infraSpineAccNodePGrp.attributes.annotation == "orchestrator:ansible" + - nm_change_spine_policy_group.previous.0.infraSpineAccNodePGrp.attributes.dn == "uni/infra/funcprof/spaccnodepgrp-ansible_access_switch_spine_pol_grp" + - nm_change_spine_policy_group.previous.0.infraSpineAccNodePGrp.attributes.name == "ansible_access_switch_spine_pol_grp" + - nm_change_spine_policy_group.previous.0.infraSpineAccNodePGrp.children.0.infraRsSpineTopoctrlUsbConfigProfilePol.attributes.tnTopoctrlUsbConfigProfilePolName == "" + - nm_change_spine_policy_group.previous.0.infraSpineAccNodePGrp.children.1.infraRsSpinePGrpToLldpIfPol.attributes.tnLldpIfPolName == "" + - nm_change_spine_policy_group.previous.0.infraSpineAccNodePGrp.children.2.infraRsSpinePGrpToCdpIfPol.attributes.tnCdpIfPolName == "" + - nm_change_spine_policy_group.previous.0.infraSpineAccNodePGrp.children.3.infraRsSpineCoppProfile.attributes.tnCoppSpineProfileName == "" + - nm_change_spine_policy_group.previous.0.infraSpineAccNodePGrp.children.4.infraRsSpineBfdIpv6InstPol.attributes.tnBfdIpv6InstPolName == "" + - nm_change_spine_policy_group.previous.0.infraSpineAccNodePGrp.children.5.infraRsSpineBfdIpv4InstPol.attributes.tnBfdIpv4InstPolName == "" + - nm_change_spine_policy_group.previous.0.infraSpineAccNodePGrp.children.6.infraRsIaclSpineProfile.attributes.tnIaclSpineProfileName == "" + when: version.current.0.topSystem.attributes.version is version('5.2', '>=') + + - name: Change the ansible access switch spine policy group for version < 5.0 + cisco.aci.aci_access_switch_policy_group: + <<: *aci_create_spine_policy_group + bfd_ipv4_policy: changed_bfd_ipv4_policy + bfd_ipv6_policy: changed_bfd_ipv6_policy + copp_policy: changed_copp_policy + copp_pre_filter_policy: changed_copp_pre_filter_policy + cdp_policy: changed_cdp_policy + lldp_policy: changed_lldp_policy + register: nm_change_spine_policy_group + when: version.current.0.topSystem.attributes.version is version('5.0', '<') + + - name: Verify change of access switch spine policy group for version < "5" + ansible.builtin.assert: + that: + - nm_change_spine_policy_group is changed + - nm_change_spine_policy_group.current.0.infraSpineAccNodePGrp.attributes.annotation == "orchestrator:ansible" + - nm_change_spine_policy_group.current.0.infraSpineAccNodePGrp.attributes.dn == "uni/infra/funcprof/spaccnodepgrp-ansible_access_switch_spine_pol_grp" + - nm_change_spine_policy_group.current.0.infraSpineAccNodePGrp.attributes.name == "ansible_access_switch_spine_pol_grp" + - nm_change_spine_policy_group.current.0.infraSpineAccNodePGrp.children.0.infraRsSpinePGrpToLldpIfPol.attributes.tnLldpIfPolName == "changed_lldp_policy" + - nm_change_spine_policy_group.current.0.infraSpineAccNodePGrp.children.1.infraRsSpinePGrpToCdpIfPol.attributes.tnCdpIfPolName == "changed_cdp_policy" + - nm_change_spine_policy_group.current.0.infraSpineAccNodePGrp.children.2.infraRsSpineCoppProfile.attributes.tnCoppSpineProfileName == "changed_copp_policy" + - nm_change_spine_policy_group.current.0.infraSpineAccNodePGrp.children.3.infraRsSpineBfdIpv6InstPol.attributes.tnBfdIpv6InstPolName == "changed_bfd_ipv6_policy" + - nm_change_spine_policy_group.current.0.infraSpineAccNodePGrp.children.4.infraRsSpineBfdIpv4InstPol.attributes.tnBfdIpv4InstPolName == "changed_bfd_ipv4_policy" + - nm_change_spine_policy_group.current.0.infraSpineAccNodePGrp.children.5.infraRsIaclSpineProfile.attributes.tnIaclSpineProfileName == "changed_copp_pre_filter_policy" + - nm_change_spine_policy_group.previous.0.infraSpineAccNodePGrp.attributes.annotation == "orchestrator:ansible" + - nm_change_spine_policy_group.previous.0.infraSpineAccNodePGrp.attributes.dn == "uni/infra/funcprof/spaccnodepgrp-ansible_access_switch_spine_pol_grp" + - nm_change_spine_policy_group.previous.0.infraSpineAccNodePGrp.attributes.name == "ansible_access_switch_spine_pol_grp" + - nm_change_spine_policy_group.previous.0.infraSpineAccNodePGrp.children.0.infraRsSpinePGrpToLldpIfPol.attributes.tnLldpIfPolName == "" + - nm_change_spine_policy_group.previous.0.infraSpineAccNodePGrp.children.1.infraRsSpinePGrpToCdpIfPol.attributes.tnCdpIfPolName == "" + - nm_change_spine_policy_group.previous.0.infraSpineAccNodePGrp.children.2.infraRsSpineCoppProfile.attributes.tnCoppSpineProfileName == "" + - nm_change_spine_policy_group.previous.0.infraSpineAccNodePGrp.children.3.infraRsSpineBfdIpv6InstPol.attributes.tnBfdIpv6InstPolName == "" + - nm_change_spine_policy_group.previous.0.infraSpineAccNodePGrp.children.4.infraRsSpineBfdIpv4InstPol.attributes.tnBfdIpv4InstPolName == "" + - nm_change_spine_policy_group.previous.0.infraSpineAccNodePGrp.children.5.infraRsIaclSpineProfile.attributes.tnIaclSpineProfileName == "" + when: version.current.0.topSystem.attributes.version is version('5.0', '<') + + - name: Create another ansible access switch spine policy group 2 + cisco.aci.aci_access_switch_policy_group: &aci_create_spine_policy_group_2 + <<: *aci_create_spine_policy_group + name: ansible_access_switch_leaf_pol_grp_2 + + - name: Query the ansible access switch spine policy group 2 + cisco.aci.aci_access_switch_policy_group: + <<: *aci_create_spine_policy_group_2 + state: query + register: query_one + + - name: Query all the ansible access switch spine policy groups + cisco.aci.aci_access_switch_policy_group: + <<: *aci_info + switch_type: spine + state: query + register: query_all + + - name: Verify remove of access switch policy + ansible.builtin.assert: + that: + - query_one is not changed + - query_one.current | length == 1 + - query_all is not changed + - query_all.current | length > 1 + + - name: Remove the ansible access switch spine policy group (check mode) + cisco.aci.aci_access_switch_policy_group: &aci_remove_spine_policy_group + <<: *aci_info + switch_type: spine + name: ansible_access_switch_spine_pol_grp + state: absent + check_mode: true + register: cm_remove_spine_policy_group + + - name: Remove the ansible access switch spine policy group + cisco.aci.aci_access_switch_policy_group: + <<: *aci_remove_spine_policy_group + register: nm_remove_spine_policy_group + + - name: Remove the ansible access switch spine policy group again + cisco.aci.aci_access_switch_policy_group: + <<: *aci_remove_spine_policy_group + register: nm_remove_spine_policy_group_again + + - name: Verify remove of access switch spine policy group + ansible.builtin.assert: + that: + - cm_remove_spine_policy_group is changed + - nm_remove_spine_policy_group.previous != [] + - nm_remove_spine_policy_group.proposed == {} + - nm_remove_spine_policy_group is changed + - nm_remove_spine_policy_group.previous != [] + - nm_remove_spine_policy_group.current == [] + - nm_remove_spine_policy_group_again is not changed + - nm_remove_spine_policy_group_again.previous == [] + - nm_remove_spine_policy_group_again.current == [] + + # WRONG CONFIGURATION FOR SPINE SWITCH TYPE + - name: Create the ansible access switch spine policy group with spanning_tree_policy (error) + cisco.aci.aci_access_switch_policy_group: + <<: *aci_info + switch_type: spine + name: ansible_access_switch_leaf_pol_grp + spanning_tree_policy: invalid_spanning_tree_policy + state: present + ignore_errors: true + register: err_create_spine_policy_group_with_spanning_tree_policy + + - name: Create the ansible access switch spine policy group with bfd_multihop_ipv4_policy (error) + cisco.aci.aci_access_switch_policy_group: + <<: *aci_info + switch_type: spine + name: ansible_access_switch_leaf_pol_grp + bfd_multihop_ipv4_policy: invalid_bfd_multihop_ipv4_policy + state: present + ignore_errors: true + register: err_create_spine_policy_group_with_bfd_multihop_ipv4_policy + + - name: Create the ansible access switch spine policy group with bfd_multihop_ipv6_policy (error) + cisco.aci.aci_access_switch_policy_group: + <<: *aci_info + switch_type: spine + name: ansible_access_switch_leaf_pol_grp + bfd_multihop_ipv6_policy: invalid_bfd_multihop_ipv6_policy + state: present + ignore_errors: true + register: err_create_spine_policy_group_with_bfd_multihop_ipv6_policy + + - name: Create the ansible access switch spine policy group with fibre_channel_node_policy (error) + cisco.aci.aci_access_switch_policy_group: + <<: *aci_info + switch_type: spine + name: ansible_access_switch_leaf_pol_grp + fibre_channel_node_policy: invalid_fibre_channel_node_policy + state: present + ignore_errors: true + register: err_create_spine_policy_group_with_fibre_channel_node_policy + + - name: Create the ansible access switch spine policy group with poe_node_policy (error) + cisco.aci.aci_access_switch_policy_group: + <<: *aci_info + switch_type: spine + name: ansible_access_switch_leaf_pol_grp + poe_node_policy: invalid_poe_node_policy + state: present + ignore_errors: true + register: err_create_spine_policy_group_with_poe_node_policy + + - name: Create the ansible access switch spine policy group with fibre_channel_san_policy (error) + cisco.aci.aci_access_switch_policy_group: + <<: *aci_info + switch_type: spine + name: ansible_access_switch_leaf_pol_grp + fibre_channel_san_policy: invalid_fibre_channel_san_policy + state: present + ignore_errors: true + register: err_create_spine_policy_group_with_fibre_channel_san_policy + + - name: Create the ansible access switch spine policy group with monitoring_policy (error) + cisco.aci.aci_access_switch_policy_group: + <<: *aci_info + switch_type: spine + name: ansible_access_switch_leaf_pol_grp + monitoring_policy: invalid_monitoring_policy + state: present + ignore_errors: true + register: err_create_spine_policy_group_with_monitoring_policy + + - name: Create the ansible access switch spine policy group with netflow_node_policy (error) + cisco.aci.aci_access_switch_policy_group: + <<: *aci_info + switch_type: spine + name: ansible_access_switch_leaf_pol_grp + netflow_node_policy: invalid_netflow_node_policy + state: present + ignore_errors: true + register: err_create_spine_policy_group_with_netflow_node_policy + + - name: Create the ansible access switch spine policy group with forward_scale_profile_policy (error) + cisco.aci.aci_access_switch_policy_group: + <<: *aci_info + switch_type: spine + name: ansible_access_switch_leaf_pol_grp + forward_scale_profile_policy: invalid_forward_scale_profile_policy + state: present + ignore_errors: true + register: err_create_spine_policy_group_with_forward_scale_profile_policy + + - name: Create the ansible access switch spine policy group with fast_link_failover_policy (error) + cisco.aci.aci_access_switch_policy_group: + <<: *aci_info + switch_type: spine + name: ansible_access_switch_leaf_pol_grp + fast_link_failover_policy: invalid_fast_link_failover_policy + state: present + ignore_errors: true + register: err_create_spine_policy_group_with_fast_link_failover_policy + + - name: Create the ansible access switch spine policy group with node_802_1x_authentication_policy (error) + cisco.aci.aci_access_switch_policy_group: + <<: *aci_info + switch_type: spine + name: ansible_access_switch_leaf_pol_grp + node_802_1x_authentication_policy: invalid_node_802_1x_authentication_policy + state: present + ignore_errors: true + register: err_create_spine_policy_group_with_node_802_1x_authentication_policy + + - name: Create the ansible access switch spine policy group with equipment_flash_policy (error) + cisco.aci.aci_access_switch_policy_group: + <<: *aci_info + switch_type: spine + name: ansible_access_switch_leaf_pol_grp + equipment_flash_policy: invalid_equipment_flash_policy + state: present + ignore_errors: true + register: err_create_spine_policy_group_with_equipment_flash_policy + + - name: Create the ansible access switch spine policy group with sync_e_node_policy (error) + cisco.aci.aci_access_switch_policy_group: + <<: *aci_info + switch_type: spine + name: ansible_access_switch_leaf_pol_grp + sync_e_node_policy: invalid_sync_e_node_policy + state: present + ignore_errors: true + register: err_create_spine_policy_group_with_sync_e_node_policy + + - name: Create the ansible access switch spine policy group with ptp_node_policy (error) + cisco.aci.aci_access_switch_policy_group: + <<: *aci_info + switch_type: spine + name: ansible_access_switch_leaf_pol_grp + ptp_node_policy: invalid_ptp_node_policy + state: present + ignore_errors: true + register: err_create_spine_policy_group_with_ptp_node_policy + + - name: Create the ansible access switch spine policy group with all (error) + cisco.aci.aci_access_switch_policy_group: + <<: *aci_info + switch_type: spine + name: ansible_access_switch_leaf_pol_grp + bfd_ipv4_policy: valid_bfd_ipv4_policy + bfd_ipv6_policy: valid_bfd_ipv6_policy + copp_policy: valid_copp_policy + copp_pre_filter_policy: valid_copp_pre_filter_policy + cdp_policy: valid_cdp_policy + lldp_policy: valid_lldp_policy + usb_configuration_policy: valid_usb_configuration_policy + spanning_tree_policy: invalid_spanning_tree_policy + bfd_multihop_ipv4_policy: invalid_bfd_multihop_ipv4_policy + bfd_multihop_ipv6_policy: invalid_bfd_multihop_ipv6_policy + fibre_channel_node_policy: invalid_fibre_channel_node_policy + poe_node_policy: invalid_poe_node_policy + fibre_channel_san_policy: invalid_fibre_channel_san_policy + monitoring_policy: invalid_monitoring_policy + netflow_node_policy: invalid_netflow_node_policy + forward_scale_profile_policy: invalid_forward_scale_profile_policy + fast_link_failover_policy: invalid_fast_link_failover_policy + node_802_1x_authentication_policy: invalid_node_802_1x_authentication_policy + equipment_flash_policy: invalid_equipment_flash_policy + sync_e_node_policy: invalid_sync_e_node_policy + ptp_node_policy: invalid_ptp_node_policy + state: present + ignore_errors: true + register: err_create_spine_policy_group_with_all + + - name: Verify errors of access switch spine policy group + ansible.builtin.assert: + that: + - err_create_spine_policy_group_with_spanning_tree_policy is failed + - err_create_spine_policy_group_with_spanning_tree_policy.msg == "Unsupported policy provided for spine switch type." + - err_create_spine_policy_group_with_bfd_multihop_ipv6_policy is failed + - err_create_spine_policy_group_with_bfd_multihop_ipv6_policy.msg == "Unsupported policy provided for spine switch type." + - err_create_spine_policy_group_with_fibre_channel_node_policy is failed + - err_create_spine_policy_group_with_fibre_channel_node_policy.msg == "Unsupported policy provided for spine switch type." + - err_create_spine_policy_group_with_poe_node_policy is failed + - err_create_spine_policy_group_with_poe_node_policy.msg == "Unsupported policy provided for spine switch type." + - err_create_spine_policy_group_with_fibre_channel_san_policy is failed + - err_create_spine_policy_group_with_fibre_channel_san_policy.msg == "Unsupported policy provided for spine switch type." + - err_create_spine_policy_group_with_monitoring_policy is failed + - err_create_spine_policy_group_with_monitoring_policy.msg == "Unsupported policy provided for spine switch type." + - err_create_spine_policy_group_with_netflow_node_policy is failed + - err_create_spine_policy_group_with_netflow_node_policy.msg == "Unsupported policy provided for spine switch type." + - err_create_spine_policy_group_with_forward_scale_profile_policy is failed + - err_create_spine_policy_group_with_forward_scale_profile_policy.msg == "Unsupported policy provided for spine switch type." + - err_create_spine_policy_group_with_fast_link_failover_policy is failed + - err_create_spine_policy_group_with_fast_link_failover_policy.msg == "Unsupported policy provided for spine switch type." + - err_create_spine_policy_group_with_node_802_1x_authentication_policy is failed + - err_create_spine_policy_group_with_node_802_1x_authentication_policy.msg == "Unsupported policy provided for spine switch type." + - err_create_spine_policy_group_with_equipment_flash_policy is failed + - err_create_spine_policy_group_with_equipment_flash_policy.msg == "Unsupported policy provided for spine switch type." + - err_create_spine_policy_group_with_sync_e_node_policy is failed + - err_create_spine_policy_group_with_sync_e_node_policy.msg == "Unsupported policy provided for spine switch type." + - err_create_spine_policy_group_with_ptp_node_policy is failed + - err_create_spine_policy_group_with_ptp_node_policy.msg == "Unsupported policy provided for spine switch type." + - err_create_spine_policy_group_with_all is failed + - err_create_spine_policy_group_with_all.msg == "Unsupported policy provided for spine switch type." diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_action_rule_additional_communities/aliases b/ansible_collections/cisco/aci/tests/integration/targets/aci_action_rule_additional_communities/aliases new file mode 100644 index 000000000..209b793f9 --- /dev/null +++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_action_rule_additional_communities/aliases @@ -0,0 +1,2 @@ +# No ACI simulator yet, so not enabled +# unsupported diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_action_rule_additional_communities/tasks/main.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_action_rule_additional_communities/tasks/main.yml new file mode 100644 index 000000000..f08bcf5c0 --- /dev/null +++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_action_rule_additional_communities/tasks/main.yml @@ -0,0 +1,147 @@ +# Test code for the ACI modules +# Copyright: (c) 2023, Gaspard Micol (@gmicol) + +# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) + +- name: Test that we have an ACI APIC host, ACI username and ACI password + ansible.builtin.fail: + msg: 'Please define the following variables: aci_hostname, aci_username and aci_password.' + when: aci_hostname is not defined or aci_username is not defined or aci_password is not defined + +- name: Set vars + ansible.builtin.set_fact: + aci_info: &aci_info + host: "{{ aci_hostname }}" + username: "{{ aci_username }}" + password: "{{ aci_password }}" + validate_certs: '{{ aci_validate_certs | default(false) }}' + use_ssl: '{{ aci_use_ssl | default(true) }}' + use_proxy: '{{ aci_use_proxy | default(true) }}' + output_level: debug + +# CLEAN ENVIRONMENT +- name: Remove the ansible_tenant + cisco.aci.aci_tenant: &aci_tenant_absent + <<: *aci_info + tenant: ansible_tenant + state: absent + +- name: Verify Cloud and Non-Cloud Sites in use. + ansible.builtin.include_tasks: ../../../../../../integration/targets/aci_cloud_provider/tasks/main.yml + +- name: Execute tasks only for non-cloud sites + when: query_cloud.current == [] # This condition will execute only non-cloud sites + block: # block specifies execution of tasks within, based on conditions + - name: Add a new tenant + cisco.aci.aci_tenant: &aci_tenant_present + <<: *aci_info + tenant: ansible_tenant + description: Ansible tenant + state: present + + - name: Add a new action rule profile + cisco.aci.aci_tenant_action_rule_profile: &aci_action_rule_present + <<: *aci_info + tenant: ansible_tenant + action_rule: ansible_action_rule + description: Ansible action rule profile for ansible_tenant tenant + state: present + + - name: Add an additional communities action rule (check_mode) + cisco.aci.aci_action_rule_additional_communities: &aci_action_rule_additional_communities_present + <<: *aci_info + tenant: ansible_tenant + action_rule: ansible_action_rule + community: regular:as2-nn2:4:15 + criteria: append + state: present + check_mode: true + register: cm_add_action_rule_add_comm + + - name: Add an additional communities action rule again (normal_mode) + cisco.aci.aci_action_rule_additional_communities: + <<: *aci_action_rule_additional_communities_present + register: nm_add_action_rule_add_comm + + - name: Add an additional communities action rule again - testing idempotency + cisco.aci.aci_action_rule_additional_communities: + <<: *aci_action_rule_additional_communities_present + register: nm_add_action_rule_add_comm_idempotency + + - name: Add an additional communities action rule + cisco.aci.aci_action_rule_additional_communities: + <<: *aci_info + tenant: ansible_tenant + action_rule: ansible_action_rule + community: extended:as4-nn2:5:16 + state: present + register: nm_add_action_rule_add_comm_2 + + - name: Asserts for additional communities action rules creation tasks + ansible.builtin.assert: + that: + - cm_add_action_rule_add_comm is changed + - cm_add_action_rule_add_comm.previous == [] + - cm_add_action_rule_add_comm.current == [] + - nm_add_action_rule_add_comm is changed + - nm_add_action_rule_add_comm.current.0.rtctrlSetAddComm.attributes.community == "regular:as2-nn2:4:15" + - nm_add_action_rule_add_comm.current.0.rtctrlSetAddComm.attributes.setCriteria == "append" + - nm_add_action_rule_add_comm_idempotency is not changed + - nm_add_action_rule_add_comm_2 is changed + - nm_add_action_rule_add_comm_2.previous == [] + - nm_add_action_rule_add_comm_2.current.0.rtctrlSetAddComm.attributes.community == "extended:as4-nn2:5:16" + - nm_add_action_rule_add_comm_2.current.0.rtctrlSetAddComm.attributes.setCriteria == "append" + + - name: Query all additional communities action rules + cisco.aci.aci_action_rule_additional_communities: + <<: *aci_info + state: query + register: query_all_action_rule_add_comm + + - name: Query ansible_action_rule_add_comm additional communities action rule + cisco.aci.aci_action_rule_additional_communities: + <<: *aci_action_rule_additional_communities_present + state: query + register: query_action_rule_add_comm + + - name: Asserts query tasks + ansible.builtin.assert: + that: + - query_all_action_rule_add_comm is not changed + - query_all_action_rule_add_comm.current|length >= 2 + - query_action_rule_add_comm is not changed + - query_action_rule_add_comm.current.0.rtctrlSetAddComm.attributes.community == "regular:as2-nn2:4:15" + - query_action_rule_add_comm.current.0.rtctrlSetAddComm.attributes.setCriteria == "append" + + - name: Remove additional communities action rule (check_mode) + cisco.aci.aci_action_rule_additional_communities: &aci_action_rule_additional_communities_absent + <<: *aci_action_rule_additional_communities_present + state: absent + check_mode: true + register: cm_remove_action_rule_add_comm + + - name: Remove additional communities action rule (normal_mode) + cisco.aci.aci_action_rule_additional_communities: + <<: *aci_action_rule_additional_communities_absent + register: nm_remove_remove_action_rule_add_comm + + - name: Remove additional communities action rule again - testing previous Removal + cisco.aci.aci_action_rule_additional_communities: + <<: *aci_action_rule_additional_communities_absent + register: nm_remove_action_rule_add_comm_idempotency + + - name: Asserts deletion tasks + ansible.builtin.assert: + that: + - cm_remove_action_rule_add_comm is changed + - cm_remove_action_rule_add_comm.proposed == {} + - nm_remove_remove_action_rule_add_comm is changed + - nm_remove_remove_action_rule_add_comm.previous != [] + - nm_remove_remove_action_rule_add_comm.method == "DELETE" + - nm_remove_action_rule_add_comm_idempotency is not changed + - nm_remove_action_rule_add_comm_idempotency.previous == [] + + - name: Remove the ansible_tenant - cleanup before ending tests + cisco.aci.aci_tenant: + <<: *aci_tenant_present + state: absent diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_action_rule_set_as_path/aliases b/ansible_collections/cisco/aci/tests/integration/targets/aci_action_rule_set_as_path/aliases new file mode 100644 index 000000000..209b793f9 --- /dev/null +++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_action_rule_set_as_path/aliases @@ -0,0 +1,2 @@ +# No ACI simulator yet, so not enabled +# unsupported diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_action_rule_set_as_path/tasks/main.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_action_rule_set_as_path/tasks/main.yml new file mode 100644 index 000000000..2ce0aadf0 --- /dev/null +++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_action_rule_set_as_path/tasks/main.yml @@ -0,0 +1,148 @@ +# Test code for the ACI modules +# Copyright: (c) 2023, Gaspard Micol (@gmicol) + +# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) + +- name: Test that we have an ACI APIC host, ACI username and ACI password + ansible.builtin.fail: + msg: 'Please define the following variables: aci_hostname, aci_username and aci_password.' + when: aci_hostname is not defined or aci_username is not defined or aci_password is not defined + +- name: Set vars + ansible.builtin.set_fact: + aci_info: &aci_info + host: "{{ aci_hostname }}" + username: "{{ aci_username }}" + password: "{{ aci_password }}" + validate_certs: '{{ aci_validate_certs | default(false) }}' + use_ssl: '{{ aci_use_ssl | default(true) }}' + use_proxy: '{{ aci_use_proxy | default(true) }}' + output_level: debug + +# CLEAN ENVIRONMENT +- name: Remove the ansible_tenant + cisco.aci.aci_tenant: &aci_tenant_absent + <<: *aci_info + tenant: ansible_tenant + state: absent + +- name: Verify Cloud and Non-Cloud Sites in use. + ansible.builtin.include_tasks: ../../../../../../integration/targets/aci_cloud_provider/tasks/main.yml + +- name: Execute tasks only for non-cloud sites + when: query_cloud.current == [] # This condition will execute only non-cloud sites + block: # block specifies execution of tasks within, based on conditions + - name: Add a new tenant + cisco.aci.aci_tenant: &aci_tenant_present + <<: *aci_info + tenant: ansible_tenant + description: Ansible tenant + state: present + + - name: Add a new action rule profile + cisco.aci.aci_tenant_action_rule_profile: &aci_action_rule_present + <<: *aci_info + tenant: ansible_tenant + action_rule: ansible_action_rule + description: Ansible action rule profile for ansible_tenant tenant + state: present + + - name: Add a set AS path action rule (check_mode) + cisco.aci.aci_action_rule_set_as_path: &aci_action_rule_set_as_path_present + <<: *aci_info + tenant: ansible_tenant + action_rule: ansible_action_rule + last_as_number: 0 + criteria: prepend + state: present + check_mode: true + register: cm_add_action_rule_set_as_path + + - name: Add a set AS path action rule again (normal_mode) + cisco.aci.aci_action_rule_set_as_path: + <<: *aci_action_rule_set_as_path_present + register: nm_add_action_rule_set_as_path + + - name: Add a set AS path action rule again - testing idempotency + cisco.aci.aci_action_rule_set_as_path: + <<: *aci_action_rule_set_as_path_present + register: nm_add_action_rule_set_as_path_idempotency + + - name: Add a set AS path action rule + cisco.aci.aci_action_rule_set_as_path: + <<: *aci_info + tenant: ansible_tenant + action_rule: ansible_action_rule + last_as_number: 2 + criteria: prepend-last-as + state: present + register: nm_add_action_rule_set_as_path_2 + + - name: Asserts for set AS path action rule creation tasks + ansible.builtin.assert: + that: + - cm_add_action_rule_set_as_path is changed + - cm_add_action_rule_set_as_path.previous == [] + - cm_add_action_rule_set_as_path.current == [] + - nm_add_action_rule_set_as_path is changed + - nm_add_action_rule_set_as_path.current.0.rtctrlSetASPath.attributes.lastnum == "0" + - nm_add_action_rule_set_as_path.current.0.rtctrlSetASPath.attributes.criteria == "prepend" + - nm_add_action_rule_set_as_path_idempotency is not changed + - nm_add_action_rule_set_as_path_2 is changed + - nm_add_action_rule_set_as_path_2.previous == [] + - nm_add_action_rule_set_as_path_2.current.0.rtctrlSetASPath.attributes.lastnum == "2" + - nm_add_action_rule_set_as_path_2.current.0.rtctrlSetASPath.attributes.criteria == "prepend-last-as" + + - name: Query all set AS path action rules + cisco.aci.aci_action_rule_set_as_path: + <<: *aci_info + state: query + register: query_all_action_rule_set_as_path + + - name: Query ansible_action_rule_set_as_path set AS path action rule + cisco.aci.aci_action_rule_set_as_path: + <<: *aci_action_rule_set_as_path_present + state: query + register: query_action_rule_set_as_path + + - name: Asserts query tasks + ansible.builtin.assert: + that: + - query_all_action_rule_set_as_path is not changed + - query_all_action_rule_set_as_path.current|length >= 2 + - query_action_rule_set_as_path is not changed + - query_action_rule_set_as_path.current.0.rtctrlSetASPath.attributes.lastnum == "0" + - query_action_rule_set_as_path.current.0.rtctrlSetASPath.attributes.criteria == "prepend" + + - name: Remove set AS path action rule (check_mode) + cisco.aci.aci_action_rule_set_as_path: &aci_action_rule_set_as_path_absent + <<: *aci_action_rule_set_as_path_present + state: absent + check_mode: true + register: cm_remove_action_rule_set_as_path + + - name: Remove set AS path action rule (normal_mode) + cisco.aci.aci_action_rule_set_as_path: + <<: *aci_action_rule_set_as_path_absent + register: nm_remove_remove_action_rule_set_as_path + + - name: Remove set AS path action rule again - testing previous Removal + cisco.aci.aci_action_rule_set_as_path: + <<: *aci_action_rule_set_as_path_absent + register: nm_remove_action_rule_set_as_path_idempotency + + - name: Asserts deletion tasks + ansible.builtin.assert: + that: + - cm_remove_action_rule_set_as_path is changed + - cm_remove_action_rule_set_as_path.proposed == {} + - nm_remove_remove_action_rule_set_as_path is changed + - nm_remove_remove_action_rule_set_as_path.previous != [] + - nm_remove_remove_action_rule_set_as_path.method == "DELETE" + - nm_remove_action_rule_set_as_path_idempotency is not changed + - nm_remove_action_rule_set_as_path_idempotency.previous == [] + + - name: Remove the ansible_tenant - cleanup before ending tests + cisco.aci.aci_tenant: + <<: *aci_tenant_present + state: absent diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_action_rule_set_as_path_asn/aliases b/ansible_collections/cisco/aci/tests/integration/targets/aci_action_rule_set_as_path_asn/aliases new file mode 100644 index 000000000..209b793f9 --- /dev/null +++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_action_rule_set_as_path_asn/aliases @@ -0,0 +1,2 @@ +# No ACI simulator yet, so not enabled +# unsupported diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_action_rule_set_as_path_asn/tasks/main.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_action_rule_set_as_path_asn/tasks/main.yml new file mode 100644 index 000000000..f17ed2f23 --- /dev/null +++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_action_rule_set_as_path_asn/tasks/main.yml @@ -0,0 +1,156 @@ +# Test code for the ACI modules +# Copyright: (c) 2023, Gaspard Micol (@gmicol) + +# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) + +- name: Test that we have an ACI APIC host, ACI username and ACI password + ansible.builtin.fail: + msg: 'Please define the following variables: aci_hostname, aci_username and aci_password.' + when: aci_hostname is not defined or aci_username is not defined or aci_password is not defined + +- name: Set vars + ansible.builtin.set_fact: + aci_info: &aci_info + host: "{{ aci_hostname }}" + username: "{{ aci_username }}" + password: "{{ aci_password }}" + validate_certs: '{{ aci_validate_certs | default(false) }}' + use_ssl: '{{ aci_use_ssl | default(true) }}' + use_proxy: '{{ aci_use_proxy | default(true) }}' + output_level: debug + +# CLEAN ENVIRONMENT +- name: Remove the ansible_tenant + cisco.aci.aci_tenant: &aci_tenant_absent + <<: *aci_info + tenant: ansible_tenant + state: absent + +- name: Verify Cloud and Non-Cloud Sites in use. + ansible.builtin.include_tasks: ../../../../../../integration/targets/aci_cloud_provider/tasks/main.yml + +- name: Execute tasks only for non-cloud sites + when: query_cloud.current == [] # This condition will execute only non-cloud sites + block: # block specifies execution of tasks within, based on conditions + - name: Add a new tenant + cisco.aci.aci_tenant: &aci_tenant_present + <<: *aci_info + tenant: ansible_tenant + description: Ansible tenant + state: present + + - name: Add a new action rule profile + cisco.aci.aci_tenant_action_rule_profile: &aci_action_rule_present + <<: *aci_info + tenant: ansible_tenant + action_rule: ansible_action_rule + description: Ansible action rule profile for ansible_tenant tenant + state: present + + - name: Add a set AS path action rule + cisco.aci.aci_action_rule_set_as_path: &aci_action_rule_set_as_path_present + <<: *aci_info + tenant: ansible_tenant + action_rule: ansible_action_rule + criteria: prepend + state: present + + - name: Add a set AS path ASN action rule (check_mode) + cisco.aci.aci_action_rule_set_as_path_asn: &aci_action_rule_set_as_path_asn_present + <<: *aci_info + tenant: ansible_tenant + action_rule: ansible_action_rule + asn: 1 + order: 1 + state: present + check_mode: true + register: cm_add_action_rule_set_as_path_asn + + - name: Add a set AS path ASN action rule again (normal_mode) + cisco.aci.aci_action_rule_set_as_path_asn: + <<: *aci_action_rule_set_as_path_asn_present + register: nm_add_action_rule_set_as_path_asn + + - name: Add a set AS path ASN action rule again - testing idempotency + cisco.aci.aci_action_rule_set_as_path_asn: + <<: *aci_action_rule_set_as_path_asn_present + register: nm_add_action_rule_set_as_path_asn_idempotency + + - name: Add a set AS path ASN action rule + cisco.aci.aci_action_rule_set_as_path_asn: + <<: *aci_info + tenant: ansible_tenant + action_rule: ansible_action_rule + asn: 2 + order: 2 + state: present + register: nm_add_action_rule_set_as_path_asn_2 + + - name: Asserts for Set AS Path ASN action rule creation tasks + ansible.builtin.assert: + that: + - cm_add_action_rule_set_as_path_asn is changed + - cm_add_action_rule_set_as_path_asn.previous == [] + - cm_add_action_rule_set_as_path_asn.current == [] + - nm_add_action_rule_set_as_path_asn is changed + - nm_add_action_rule_set_as_path_asn.current.0.rtctrlSetASPathASN.attributes.asn == "1" + - nm_add_action_rule_set_as_path_asn.current.0.rtctrlSetASPathASN.attributes.order == "1" + - nm_add_action_rule_set_as_path_asn_idempotency is not changed + - nm_add_action_rule_set_as_path_asn_2 is changed + - nm_add_action_rule_set_as_path_asn_2.previous == [] + - nm_add_action_rule_set_as_path_asn_2.current.0.rtctrlSetASPathASN.attributes.asn == "2" + - nm_add_action_rule_set_as_path_asn_2.current.0.rtctrlSetASPathASN.attributes.order == "2" + + - name: Query all set AS path ASN action rules + cisco.aci.aci_action_rule_set_as_path_asn: + <<: *aci_info + state: query + register: query_all_action_rule_set_as_path_asn + + - name: Query ansible_action_rule_set_as_path_asn set AS path ASN action rule + cisco.aci.aci_action_rule_set_as_path_asn: + <<: *aci_action_rule_set_as_path_asn_present + state: query + register: query_action_rule_set_as_path_asn + + - name: Asserts query tasks + ansible.builtin.assert: + that: + - query_all_action_rule_set_as_path_asn is not changed + - query_all_action_rule_set_as_path_asn.current|length >= 2 + - query_action_rule_set_as_path_asn is not changed + - query_action_rule_set_as_path_asn.current.0.rtctrlSetASPathASN.attributes.asn == "1" + - query_action_rule_set_as_path_asn.current.0.rtctrlSetASPathASN.attributes.order == "1" + + - name: Remove set AS path ASN action rule (check_mode) + cisco.aci.aci_action_rule_set_as_path_asn: &aci_action_rule_set_as_path_asn_absent + <<: *aci_action_rule_set_as_path_asn_present + state: absent + check_mode: true + register: cm_remove_action_rule_set_as_path_asn + + - name: Remove set AS path ASN action rule (normal_mode) + cisco.aci.aci_action_rule_set_as_path_asn: + <<: *aci_action_rule_set_as_path_asn_absent + register: nm_remove_remove_action_rule_set_as_path_asn + + - name: Remove set AS path ASN action rule again - testing previous Removal + cisco.aci.aci_action_rule_set_as_path_asn: + <<: *aci_action_rule_set_as_path_asn_absent + register: nm_remove_action_rule_set_as_path_asn_idempotency + + - name: Asserts deletion tasks + ansible.builtin.assert: + that: + - cm_remove_action_rule_set_as_path_asn is changed + - cm_remove_action_rule_set_as_path_asn.proposed == {} + - nm_remove_remove_action_rule_set_as_path_asn is changed + - nm_remove_remove_action_rule_set_as_path_asn.previous != [] + - nm_remove_remove_action_rule_set_as_path_asn.method == "DELETE" + - nm_remove_action_rule_set_as_path_asn_idempotency is not changed + - nm_remove_action_rule_set_as_path_asn_idempotency.previous == [] + + - name: Remove the ansible_tenant - cleanup before ending tests + cisco.aci.aci_tenant: + <<: *aci_tenant_present + state: absent diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_aep/tasks/main.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_aep/tasks/main.yml index 1a389a9fc..81ff17663 100644 --- a/ansible_collections/cisco/aci/tests/integration/targets/aci_aep/tasks/main.yml +++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_aep/tasks/main.yml @@ -1,15 +1,16 @@ # Test code for the ACI modules # Copyright: (c) 2018, Dag Wieers (@dagwieers) +# Copyright: (c) 2024, Samita Bhattacharjee (@samiib) # GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) - name: Test that we have an ACI APIC host, ACI username and ACI password - fail: + ansible.builtin.fail: msg: 'Please define the following variables: aci_hostname, aci_username and aci_password.' when: aci_hostname is not defined or aci_username is not defined or aci_password is not defined - name: Verify Cloud and Non-Cloud Sites in use. - include_tasks: ../../../../../../integration/targets/aci_cloud_provider/tasks/main.yml + ansible.builtin.include_tasks: ../../../../../../integration/targets/aci_cloud_provider/tasks/main.yml - name: Execute tasks only for non-cloud sites when: query_cloud.current == [] # This condition will execute only non-cloud sites @@ -66,7 +67,7 @@ register: nm_add_aep3 - name: Verify add_aep - assert: + ansible.builtin.assert: that: - cm_add_aep is changed - nm_add_aep is changed @@ -106,7 +107,7 @@ register: nm_add_aep_again - name: Verify add_aep_again - assert: + ansible.builtin.assert: that: - cm_add_aep_again is not changed - nm_add_aep_again is not changed @@ -132,7 +133,7 @@ register: nm_add_aep_descr - name: Verify add_aep_descr - assert: + ansible.builtin.assert: that: - cm_add_aep_descr is changed - nm_add_aep_descr is changed @@ -159,7 +160,7 @@ register: nm_add_aep_descr_again - name: Verify add_aep_descr_again - assert: + ansible.builtin.assert: that: - cm_add_aep_descr_again is not changed - nm_add_aep_descr_again is not changed @@ -182,7 +183,7 @@ register: nm_add_aep_again_no_descr - name: Verify add_aep_again_no_descr - assert: + ansible.builtin.assert: that: - cm_add_aep_again_no_descr is not changed - nm_add_aep_again_no_descr is not changed @@ -192,6 +193,75 @@ - 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' + # TEST NO VERIFICATION + - name: Create aep with no verification (check mode) + cisco.aci.aci_aep: &aci_aep_no_verify + <<: *aep_present + aep: anstest-no-verify + description: Ansible Test + no_verification: true + check_mode: true + register: aep_present_no_verify_cm + + - name: Create aep with no verification + cisco.aci.aci_aep: + <<: *aci_aep_no_verify + register: aep_present_no_verify + + - name: Create aep with no verification again + cisco.aci.aci_aep: + <<: *aci_aep_no_verify + register: aep_present_no_verify_again + + - name: Update aep with no verification + cisco.aci.aci_aep: + <<: *aci_aep_no_verify + description: Ansible Test No Verify + register: update_aep_present_no_verify + + - name: Delete aep with no verification + cisco.aci.aci_aep: + <<: *aci_aep_no_verify + state: absent + register: delete_aep_present_no_verify + + - name: Delete aep with no verification again + cisco.aci.aci_aep: + <<: *aci_aep_no_verify + state: absent + register: delete_aep_present_no_verify_again + + - name: No verification asserts + ansible.builtin.assert: + that: + - aep_present_no_verify_cm is changed + - aep_present_no_verify_cm.current_verified == false + - aep_present_no_verify_cm.current.0 == aep_present_no_verify_cm.proposed + - aep_present_no_verify is changed + - aep_present_no_verify.current_verified == false + - aep_present_no_verify.current.0 == aep_present_no_verify.proposed + - aep_present_no_verify.previous == [] + - aep_present_no_verify_again is not changed + - aep_present_no_verify_again.current_verified == true + - aep_present_no_verify_again.current.0.infraAttEntityP.attributes.name == "anstest-no-verify" + - aep_present_no_verify_again.current.0.infraAttEntityP.attributes.descr == "Ansible Test" + - aep_present_no_verify_again.previous.0.infraAttEntityP.attributes.name == "anstest-no-verify" + - aep_present_no_verify_again.previous.0.infraAttEntityP.attributes.descr == "Ansible Test" + - update_aep_present_no_verify is changed + - update_aep_present_no_verify.current_verified == false + - update_aep_present_no_verify.current.0 == update_aep_present_no_verify.proposed + - update_aep_present_no_verify.previous.0.infraAttEntityP.attributes.name == "anstest-no-verify" + - update_aep_present_no_verify.previous.0.infraAttEntityP.attributes.descr == "Ansible Test" + - delete_aep_present_no_verify is changed + - delete_aep_present_no_verify.current_verified == false + - delete_aep_present_no_verify.current.0 == delete_aep_present_no_verify.proposed + - delete_aep_present_no_verify.previous.0.infraAttEntityP.attributes.name == "anstest-no-verify" + - delete_aep_present_no_verify.previous.0.infraAttEntityP.attributes.descr == "Ansible Test No Verify" + - delete_aep_present_no_verify_again is not changed + - delete_aep_present_no_verify_again.current_verified == true + - delete_aep_present_no_verify_again.current == [] + - delete_aep_present_no_verify_again.previous == [] + - delete_aep_present_no_verify_again.proposed == {} # QUERY ALL AEPS - name: Query all AEPs (check_mode) @@ -212,7 +282,7 @@ register: nm_query_all_aeps - name: Verify query_all_aeps - assert: + ansible.builtin.assert: that: - cm_query_all_aeps is not changed - nm_query_all_aeps is not changed @@ -235,7 +305,7 @@ register: nm_query_aep - name: Verify query_aep - assert: + ansible.builtin.assert: that: - cm_query_aep is not changed - nm_query_aep is not changed @@ -260,7 +330,7 @@ register: nm_remove_aep - name: Verify remove_aep - assert: + ansible.builtin.assert: that: - cm_remove_aep is changed - nm_remove_aep is changed @@ -285,7 +355,7 @@ register: nm_remove_aep_again - name: Verify remove_aep_again - assert: + ansible.builtin.assert: that: - cm_remove_aep_again is not changed - nm_remove_aep_again is not changed @@ -309,7 +379,7 @@ register: nm_query_non_aep - name: Verify query_non_aep - assert: + ansible.builtin.assert: that: - cm_query_non_aep is not changed - nm_query_non_aep is not changed @@ -332,7 +402,7 @@ register: error_on_missing_required_param - name: Verify error_on_missing_required_param - assert: + ansible.builtin.assert: that: - error_on_missing_required_param is failed - 'error_on_missing_required_param.msg == "state is present but all of the following are missing: aep"' diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_aep_to_domain/tasks/main.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_aep_to_domain/tasks/main.yml index 2a4f6f23e..2cd820811 100644 --- a/ansible_collections/cisco/aci/tests/integration/targets/aci_aep_to_domain/tasks/main.yml +++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_aep_to_domain/tasks/main.yml @@ -4,7 +4,7 @@ # GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) - name: Test that we have an ACI APIC host, ACI username and ACI password - fail: + ansible.builtin.fail: msg: 'Please define the following variables: aci_hostname, aci_username and aci_password.' when: aci_hostname is not defined or aci_username is not defined or aci_password is not defined @@ -21,7 +21,7 @@ - name: Verify Cloud and Non-Cloud Sites in use. - include_tasks: ../../../../../../integration/targets/aci_cloud_provider/tasks/main.yml + ansible.builtin.include_tasks: ../../../../../../integration/targets/aci_cloud_provider/tasks/main.yml - name: Execute tasks only for non-cloud sites when: query_cloud.current == [] # This condition will execute only non-cloud sites @@ -78,7 +78,7 @@ register: nm_add_binding - name: Verify add_binding - assert: + ansible.builtin.assert: that: - cm_add_binding is changed - nm_add_binding is changed @@ -99,7 +99,7 @@ register: nm_add_binding_again - name: Verify add_binding_again - assert: + ansible.builtin.assert: that: - cm_add_binding_again is not changed - nm_add_binding_again is not changed @@ -148,7 +148,7 @@ register: nm_vmm_type - name: Verify bindings with domain types - assert: + ansible.builtin.assert: that: - err_not_vmm_with_vm_provider is not changed - err_not_vmm_with_vm_provider.msg == "Domain type 'phys' cannot have a 'vm_provider'" @@ -174,7 +174,7 @@ register: nm_query_all_bindings - name: Verify query_all_bindings - assert: + ansible.builtin.assert: that: - cm_query_all_bindings is not changed - nm_query_all_bindings is not changed @@ -201,7 +201,7 @@ register: nm_query_binding - name: Verify query_binding - assert: + ansible.builtin.assert: that: - cm_query_binding is not changed - nm_query_binding is not changed @@ -222,7 +222,7 @@ register: nm_remove_binding - name: Verify remove_binding - assert: + ansible.builtin.assert: that: - cm_remove_binding is changed - nm_remove_binding is changed @@ -240,7 +240,7 @@ register: nm_remove_binding_again - name: Verify remove_binding_again - assert: + ansible.builtin.assert: that: - cm_remove_binding_again is not changed - nm_remove_binding_again is not changed @@ -265,7 +265,7 @@ register: nm_query_non_binding - name: Verify query_non_binding - assert: + ansible.builtin.assert: that: - cm_query_non_binding is not changed - nm_query_non_binding is not changed diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_aep_to_epg/tasks/main.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_aep_to_epg/tasks/main.yml index 86ee212bd..6d3430519 100644 --- a/ansible_collections/cisco/aci/tests/integration/targets/aci_aep_to_epg/tasks/main.yml +++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_aep_to_epg/tasks/main.yml @@ -4,7 +4,7 @@ # SET VARS - name: Set vars - set_fact: + ansible.builtin.set_fact: aci_info: &aci_info host: '{{ aci_hostname }}' username: '{{ aci_username }}' @@ -15,7 +15,7 @@ output_level: '{{ aci_output_level | default("info") }}' - name: Verify Cloud and Non-Cloud Sites in use. - include_tasks: ../../../../../../integration/targets/aci_cloud_provider/tasks/main.yml + ansible.builtin.include_tasks: ../../../../../../integration/targets/aci_cloud_provider/tasks/main.yml - name: Execute tasks only for non-cloud sites when: query_cloud.current == [] # This condition will execute only non-cloud sites @@ -84,7 +84,7 @@ register: nm_add_assoc - name: Verify add_assoc - assert: + ansible.builtin.assert: that: - cm_add_assoc is changed - nm_add_assoc is changed @@ -106,7 +106,7 @@ register: nm_add_assoc_again - name: Verify add_assoc_again - assert: + ansible.builtin.assert: that: - cm_add_assoc_again is not changed - nm_add_assoc_again is not changed @@ -126,7 +126,7 @@ register: nm_update_assoc - name: Verify update_assoc - assert: + ansible.builtin.assert: that: - cm_update_assoc is changed - nm_update_assoc is changed @@ -149,7 +149,7 @@ register: query_all_assocs - name: Verify query_all_assocs - assert: + ansible.builtin.assert: that: - query_all_assocs is not changed - query_all_assocs.current|length >= 1 @@ -162,7 +162,7 @@ register: query_spec_assoc - name: Verify query_spec_assoc - assert: + ansible.builtin.assert: that: - query_spec_assoc is not changed - query_spec_assoc.current|length == 1 @@ -181,7 +181,7 @@ register: nm_remove_spec_assoc - name: Verify remove_spec_assoc - assert: + ansible.builtin.assert: that: - cm_remove_spec_assoc is changed - nm_remove_spec_assoc is changed @@ -193,7 +193,7 @@ register: nm_remove_spec_assoc_again - name: Verify remove_spec_assoc_again - assert: + ansible.builtin.assert: that: - nm_remove_spec_assoc_again is not changed @@ -206,7 +206,7 @@ register: query_existing_assoc - name: Verify query_existing_assoc - assert: + ansible.builtin.assert: that: - query_existing_assoc is not changed - query_existing_assoc.current|length == 1 @@ -219,7 +219,7 @@ register: nm_query_non_exist - name: Verify nm_query_non_exist - assert: + ansible.builtin.assert: that: - nm_query_non_exist is not changed - nm_query_non_exist.current == [] diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_ap/tasks/main.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_ap/tasks/main.yml index c527a9059..94db7989e 100644 --- a/ansible_collections/cisco/aci/tests/integration/targets/aci_ap/tasks/main.yml +++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_ap/tasks/main.yml @@ -1,16 +1,17 @@ # Test code for the ACI modules # Copyright: (c) 2017, Jacob McGill (@jmcgill298) # Copyright: (c) 2020, Shreyas Srish (@shrsr) +# Copyright: (c) 2024, Samita Bhattacharjee (@samiib) # GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) - name: Test that we have an ACI APIC host, ACI username and ACI password - fail: + ansible.builtin.fail: msg: 'Please define the following variables: aci_hostname, aci_username and aci_password.' when: aci_hostname is not defined or aci_username is not defined or aci_password is not defined - name: Verify Cloud and Non-Cloud Sites in use. - include_tasks: ../../../../../../integration/targets/aci_cloud_provider/tasks/main.yml + ansible.builtin.include_tasks: ../../../../../../integration/targets/aci_cloud_provider/tasks/main.yml - name: ensure tenant does not exists cisco.aci.aci_tenant: &aci_tenant_absent @@ -88,7 +89,7 @@ register: ap_present_missing_param - name: present asserts - assert: + ansible.builtin.assert: that: - ap_present_check_mode is changed - ap_present is changed @@ -106,6 +107,75 @@ - ap_present_missing_param is failed - 'ap_present_missing_param.msg == "state is present but all of the following are missing: ap"' + # TEST NO VERIFICATION + - name: create ap with no verification (check mode) + cisco.aci.aci_ap: &aci_ap_no_verify + <<: *aci_ap_present + ap: anstest-no-verify + no_verification: true + check_mode: true + register: ap_present_no_verify_cm + + - name: create ap with no verification + cisco.aci.aci_ap: + <<: *aci_ap_no_verify + register: ap_present_no_verify + + - name: create ap with no verification again + cisco.aci.aci_ap: + <<: *aci_ap_no_verify + register: ap_present_no_verify_again + + - name: update ap with no verification + cisco.aci.aci_ap: + <<: *aci_ap_no_verify + description: Ansible Test No Verify + register: update_ap_present_no_verify + + - name: delete ap with no verification + cisco.aci.aci_ap: + <<: *aci_ap_no_verify + state: absent + register: delete_ap_present_no_verify + + - name: delete ap with no verification again + cisco.aci.aci_ap: + <<: *aci_ap_no_verify + state: absent + register: delete_ap_present_no_verify_again + + - name: no verification asserts + ansible.builtin.assert: + that: + - ap_present_no_verify_cm is changed + - ap_present_no_verify_cm.current_verified == false + - ap_present_no_verify_cm.current.0 == ap_present_no_verify_cm.proposed + - ap_present_no_verify is changed + - ap_present_no_verify.current_verified == false + - ap_present_no_verify.current.0 == ap_present_no_verify.proposed + - ap_present_no_verify.previous == [] + - ap_present_no_verify_again is not changed + - ap_present_no_verify_again.current_verified == true + - ap_present_no_verify_again.current.0.fvAp.attributes.name == "anstest-no-verify" + - ap_present_no_verify_again.current.0.fvAp.attributes.descr == "Ansible Test" + - ap_present_no_verify_again.previous.0.fvAp.attributes.name == "anstest-no-verify" + - ap_present_no_verify_again.previous.0.fvAp.attributes.descr == "Ansible Test" + - update_ap_present_no_verify is changed + - update_ap_present_no_verify.current_verified == false + - update_ap_present_no_verify.current.0 == update_ap_present_no_verify.proposed + - update_ap_present_no_verify.previous.0.fvAp.attributes.name == "anstest-no-verify" + - update_ap_present_no_verify.previous.0.fvAp.attributes.descr == "Ansible Test" + - delete_ap_present_no_verify is changed + - delete_ap_present_no_verify.current_verified == false + - delete_ap_present_no_verify.current.0 == delete_ap_present_no_verify.proposed + - delete_ap_present_no_verify.previous.0.fvAp.attributes.name == "anstest-no-verify" + - delete_ap_present_no_verify.previous.0.fvAp.attributes.descr == "Ansible Test No Verify" + - delete_ap_present_no_verify_again is not changed + - delete_ap_present_no_verify_again.current_verified == true + - delete_ap_present_no_verify_again.current == [] + - delete_ap_present_no_verify_again.previous == [] + - delete_ap_present_no_verify_again.proposed == {} + - name: get ap - query specific ap cisco.aci.aci_ap: &aci_ap_query <<: *aci_ap_present @@ -132,7 +202,7 @@ register: query_all - name: query assertions - assert: + ansible.builtin.assert: that: - query_ap is not changed - query_ap.current | length == 1 @@ -183,7 +253,7 @@ ap: anstest2 - name: absent assertions - assert: + ansible.builtin.assert: that: - ap_delete_check_mode is changed - ap_delete_check_mode.previous != [] diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_bd/tasks/main.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_bd/tasks/main.yml index 3af05fd0f..4bb951c69 100644 --- a/ansible_collections/cisco/aci/tests/integration/targets/aci_bd/tasks/main.yml +++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_bd/tasks/main.yml @@ -1,15 +1,16 @@ # Test code for the ACI modules # Copyright: (c) 2017, Jacob McGill (@jmcgill298) +# Copyright: (c) 2024, Samita Bhattacharjee (@samiib) # GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) - name: Test that we have an ACI APIC host, ACI username and ACI password - fail: + ansible.builtin.fail: msg: 'Please define the following variables: aci_hostname, aci_username and aci_password.' when: aci_hostname is not defined or aci_username is not defined or aci_password is not defined - name: Set vars - set_fact: + ansible.builtin.set_fact: aci_info: &aci_info host: "{{ aci_hostname }}" username: "{{ aci_username }}" @@ -20,14 +21,14 @@ output_level: debug - name: Query system information - aci_system: + cisco.aci.aci_system: <<: *aci_info id: 1 state: query register: version - name: Verify Cloud and Non-Cloud Sites in use. - include_tasks: ../../../../../../integration/targets/aci_cloud_provider/tasks/main.yml + ansible.builtin.include_tasks: ../../../../../../integration/targets/aci_cloud_provider/tasks/main.yml - name: ensure tenant does not exists cisco.aci.aci_tenant: &aci_tenant_absent @@ -73,11 +74,63 @@ l3protocol: ospf state: present + - name: ensure IGMP Interface Policy exists + cisco.aci.aci_igmp_interface_policy: &aci_igmp_policy_present + <<: *aci_tenant_present + name: ansible_igmp_pol + state: present + + - name: ensure Monitoring Policy exists + cisco.aci.aci_epg_monitoring_policy: &aci_monitoring_policy_present + <<: *aci_tenant_present + name: ansible_monitoring_pol + state: present + + - name: ensure PIM Route Map Policy exists + cisco.aci.aci_pim_route_map_policy: &aci_route_map_policy_present + <<: *aci_tenant_present + name: ansible_route_map_pol + state: present + when: version.current.0.topSystem.attributes.version is version('5.2', '>=') + + - name: ensure IGMP Snoop Policy exists + cisco.aci.aci_rest: + <<: *aci_info + path: /api/mo/uni/tn-ansible_test.json + method: post + content: + igmpSnoopPol: + attributes: + name: ansible_igmp_snoop + + - name: ensure MLD Snoop Policy exists + cisco.aci.aci_rest: + <<: *aci_info + path: /api/mo/uni/tn-ansible_test.json + method: post + content: + mldSnoopPol: + attributes: + name: ansible_mld_snoop + + - name: ensure FHS policy exists + cisco.aci.aci_rest: + <<: *aci_info + path: /api/mo/uni/tn-ansible_test.json + method: post + content: + fhsBDPol: + attributes: + name: ansible_fhs + - name: create bd - check mode works cisco.aci.aci_bd: &aci_bd_present <<: *aci_tenant_present bd: anstest description: Ansible Test + mld_snoop_policy: ansible_mld_snoop + first_hop_security_policy: ansible_fhs + igmp_policy: ansible_igmp_pol check_mode: true register: bd_present_check_mode @@ -91,6 +144,7 @@ <<: *aci_bd_present register: bd_present_idempotent + # UPDATE BD - name: update bd - update works cisco.aci.aci_bd: <<: *aci_bd_present @@ -98,6 +152,25 @@ description: Ansible Test Update register: bd_update + - name: Update bd to remove child config (check_mode) + cisco.aci.aci_bd: &aci_bd_update + <<: *aci_bd_present + mld_snoop_policy: "" + first_hop_security_policy: "" + igmp_policy: "" + check_mode: true + register: cm_update_bd_2 + + - name: Update bd to remove child config (normal_mode) + cisco.aci.aci_bd: + <<: *aci_bd_update + register: nm_update_bd_2 + + - name: Update bd again to remove child config (testing idempotency) + cisco.aci.aci_bd: + <<: *aci_bd_update + register: nm_update_bd_2_again + - name: create another bd - check more params cisco.aci.aci_bd: <<: *aci_bd_present @@ -115,7 +188,7 @@ register: bd_present_2 when: version.current.0.topSystem.attributes.version is version('4.2', '<') - - name: create another bd - check more params (>v4.2) + - name: create another bd - check more params (>=v4.2 & <6.0) cisco.aci.aci_bd: <<: *aci_bd_present bd: anstest2 @@ -126,12 +199,61 @@ l3_unknown_multicast: opt-flood ipv6_l3_unknown_multicast: opt-flood multi_dest: drop - enable_routing: "no" + enable_routing: "yes" arp_flooding: "yes" route_profile_l3out: ansible_l3out route_profile: ansible_l3out_route + host_based_routing: true + allow_intersite_bum_traffic: true + allow_intersite_l2_stretch: true + allow_ipv6_mcast: true + ll_addr: "fe80::1322:33ff:fe44:5566" + vmac: "00:AA:BB:CC:DD:03" + optimize_wan_bandwidth: true + vlan: vlan-101 + igmp_policy: ansible_igmp_pol + monitoring_policy: ansible_monitoring_pol + igmp_snoop_policy: ansible_igmp_snoop + mld_snoop_policy: ansible_mld_snoop + first_hop_security_policy: ansible_fhs register: bd_present_2b - when: version.current.0.topSystem.attributes.version is version('4.2', '>=') + when: version.current.0.topSystem.attributes.version is version('4.2', '>=') and + version.current.0.topSystem.attributes.version is version('6.0', '<') + + - name: create another bd - check more params (>=v6.0) + cisco.aci.aci_bd: + <<: *aci_bd_present + bd: anstest2 + bd_type: ethernet + endpoint_move_detect: default + ip_learning: "no" + l2_unknown_unicast: flood + l3_unknown_multicast: opt-flood + ipv6_l3_unknown_multicast: opt-flood + multi_dest: drop + enable_routing: "yes" + arp_flooding: "yes" + route_profile_l3out: ansible_l3out + route_profile: ansible_l3out_route + host_based_routing: true + enable_rogue_except_mac: true + allow_intersite_bum_traffic: true + allow_intersite_l2_stretch: true + allow_ipv6_mcast: true + ll_addr: "fe80::1322:33ff:fe44:5566" + mcast_arp_drop: true + vmac: "00:AA:BB:CC:DD:03" + optimize_wan_bandwidth: true + vlan: vlan-101 + igmp_policy: ansible_igmp_pol + monitoring_policy: ansible_monitoring_pol + igmp_snoop_policy: ansible_igmp_snoop + mld_snoop_policy: ansible_mld_snoop + pim_source_filter: ansible_route_map_pol + pim_destination_filter: ansible_route_map_pol + first_hop_security_policy: ansible_fhs + register: bd_present_2c + when: version.current.0.topSystem.attributes.version is version('6.0', '>=') - name: create bd without all necessary params - failure message works cisco.aci.aci_bd: @@ -140,8 +262,27 @@ ignore_errors: true register: bd_present_missing_param + - name: present asserts for removing children + ansible.builtin.assert: + that: + - cm_update_bd_2 is changed + - cm_update_bd_2.previous == cm_update_bd_2.current + - cm_update_bd_2.proposed.fvBD.children | length == 3 + - cm_update_bd_2.proposed.fvBD.children.0.fvRsMldsn.attributes.tnMldSnoopPolName == '' + - cm_update_bd_2.proposed.fvBD.children.1.fvRsBDToFhs.attributes.tnFhsBDPolName == '' + - cm_update_bd_2.proposed.fvBD.children.2.igmpIfP.children.0.igmpRsIfPol.attributes.tDn == '' + - nm_update_bd_2 is changed + - nm_update_bd_2.previous.0.fvBD.children.0.fvRsMldsn.attributes.tnMldSnoopPolName == 'ansible_mld_snoop' + - nm_update_bd_2.previous.0.fvBD.children.1.fvRsBDToFhs.attributes.tnFhsBDPolName == 'ansible_fhs' + - nm_update_bd_2.previous.0.fvBD.children.2.igmpIfP.children.0.igmpRsIfPol.attributes.tDn == 'uni/tn-ansible_test/igmpIfPol-ansible_igmp_pol' + - nm_update_bd_2.current.0.fvBD.children.0.fvRsMldsn.attributes.tnMldSnoopPolName == '' + - nm_update_bd_2.current.0.fvBD.children.1.fvRsBDToFhs.attributes.tnFhsBDPolName == '' + - nm_update_bd_2.current.0.fvBD.children.2.igmpIfP.children.0.igmpRsIfPol.attributes.tDn == '' + - nm_update_bd_2_again is not changed + - nm_update_bd_2_again.previous == nm_update_bd_2_again.current + - name: present asserts (v4.2) - assert: + - name: present asserts (>=v4.2 & =') + when: version.current.0.topSystem.attributes.version is version('4.2', '>=') and + version.current.0.topSystem.attributes.version is version('6.0', '<') + + - name: present asserts (>=v6.0) + ansible.builtin.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_2c.sent.fvBD.attributes.arpFlood == 'yes' + - bd_present_2c.sent.fvBD.attributes.descr == 'Ansible Test' + - bd_present_2c.sent.fvBD.attributes.ipLearning == 'no' + - bd_present_2c.sent.fvBD.attributes.multiDstPktAct == 'drop' + - bd_present_2c.sent.fvBD.attributes.name == 'anstest2' + - bd_present_2c.sent.fvBD.attributes.unicastRoute == 'yes' + - bd_present_2c.sent.fvBD.attributes.unkMacUcastAct == 'flood' + - bd_present_2c.sent.fvBD.attributes.unkMcastAct == 'opt-flood' + - bd_present_2c.sent.fvBD.attributes.v6unkMcastAct == 'opt-flood' + - bd_present_2c.sent.fvBD.attributes.type == 'regular' + - bd_present_2c.sent.fvBD.attributes.hostBasedRouting == 'yes' + - bd_present_2c.sent.fvBD.attributes.intersiteBumTrafficAllow == 'yes' + - bd_present_2c.sent.fvBD.attributes.intersiteL2Stretch == 'yes' + - bd_present_2c.sent.fvBD.attributes.ipv6McastAllow == 'yes' + - bd_present_2c.sent.fvBD.attributes.llAddr == 'fe80::1322:33ff:fe44:5566' + - bd_present_2c.sent.fvBD.attributes.mcastARPDrop == 'yes' + - bd_present_2c.sent.fvBD.attributes.enableRogueExceptMac == 'yes' + - bd_present_2c.sent.fvBD.attributes.vmac == '00:AA:BB:CC:DD:03' + - bd_present_2c.sent.fvBD.attributes.OptimizeWanBandwidth == 'yes' + - bd_present_2c.sent.fvBD.children.0.fvRsIgmpsn.attributes.tnIgmpSnoopPolName == 'ansible_igmp_snoop' + - bd_present_2c.sent.fvBD.children.1.fvRsMldsn.attributes.tnMldSnoopPolName == 'ansible_mld_snoop' + - bd_present_2c.sent.fvBD.children.2.fvRsBDToProfile.attributes.tnRtctrlProfileName == 'ansible_l3out_route' + - bd_present_2c.sent.fvBD.children.2.fvRsBDToProfile.attributes.tnL3extOutName == 'ansible_l3out' + - bd_present_2c.sent.fvBD.children.3.fvRsBDToFhs.attributes.tnFhsBDPolName == 'ansible_fhs' + - bd_present_2c.sent.fvBD.children.4.fvAccP.attributes.encap == 'vlan-101' + - bd_present_2c.sent.fvBD.children.5.fvRsABDPolMonPol.attributes.tnMonEPGPolName == 'ansible_monitoring_pol' + - bd_present_2c.sent.fvBD.children.6.igmpIfP.children.0.igmpRsIfPol.attributes.tDn == 'uni/tn-ansible_test/igmpIfPol-ansible_igmp_pol' + - bd_present_2c.sent.fvBD.children.7.pimBDP.children.0.pimBDFilterPol.children.0.pimBDSrcFilterPol.children.0.rtdmcRsFilterToRtMapPol.attributes.tDn == 'uni/tn-ansible_test/rtmap-ansible_route_map_pol' + - bd_present_2c.sent.fvBD.children.7.pimBDP.children.0.pimBDFilterPol.children.1.pimBDDestFilterPol.children.0.rtdmcRsFilterToRtMapPol.attributes.tDn == 'uni/tn-ansible_test/rtmap-ansible_route_map_pol' + - bd_present_missing_param is failed + - 'bd_present_missing_param.msg == "state is present but all of the following are missing: tenant"' + when: version.current.0.topSystem.attributes.version is version('6.0', '>=') + + - name: execute tasks for pim source filter & pim destination filter (>=v5.2) + when: version.current.0.topSystem.attributes.version is version('5.2', '>=') + block: + + - name: create another bd - check pim source filter (check_mode) + cisco.aci.aci_bd: &aci_bd_pim_s + <<: *aci_bd_present + bd: anstest_pim_s + pim_source_filter: ansible_route_map_pol + check_mode: true + register: cm_bd_pim_s + + - name: create another bd - check pim source filter (normal_mode) + cisco.aci.aci_bd: + <<: *aci_bd_pim_s + register: nm_bd_pim_s + + - name: create another bd - check pim source filter (testing idempotency) + cisco.aci.aci_bd: + <<: *aci_bd_pim_s + register: nm_bd_pim_s_again + + - name: update bd - remove pim source filter + cisco.aci.aci_bd: + <<: *aci_bd_pim_s + pim_source_filter: "" + register: nm_bd_pim_s_remove + + - name: create another bd - check pim destination filter (check_mode) + cisco.aci.aci_bd: &aci_bd_pim_d + <<: *aci_bd_present + bd: anstest_pim_d + pim_destination_filter: ansible_route_map_pol + check_mode: true + register: cm_bd_pim_d + + - name: create another bd - check pim destination filter (normal_mode) + cisco.aci.aci_bd: + <<: *aci_bd_pim_d + register: nm_bd_pim_d + + - name: create another bd - check pim destination filter (testing idempotency) + cisco.aci.aci_bd: + <<: *aci_bd_pim_d + register: nm_bd_pim_d_again + + - name: update bd - remove pim destination filter + cisco.aci.aci_bd: + <<: *aci_bd_pim_d + pim_destination_filter: "" + register: nm_bd_pim_d_remove + + - name: cleanup pim_s and pim_d BDs + cisco.aci.aci_bd: + <<: *aci_bd_present + bd: "{{ item }}" + state: absent + loop: + - anstest_pim_s + - anstest_pim_d + + - name: asserts for pim source filter and pim destination filter + ansible.builtin.assert: + that: + - cm_bd_pim_s is changed + - cm_bd_pim_s.current == [] + - cm_bd_pim_s.previous == [] + - cm_bd_pim_s.proposed.fvBD.children.3.pimBDP.children.0.pimBDFilterPol.children | length == 1 + - cm_bd_pim_s.proposed.fvBD.children.3.pimBDP.children.0.pimBDFilterPol.children.0.pimBDSrcFilterPol.children.0.rtdmcRsFilterToRtMapPol.attributes.tDn == 'uni/tn-ansible_test/rtmap-ansible_route_map_pol' + - nm_bd_pim_s is changed + - nm_bd_pim_s.previous == [] + - nm_bd_pim_s.current.0.fvBD.children.5.pimBDP.children.0.pimBDFilterPol.children | length == 1 + - nm_bd_pim_s.current.0.fvBD.children.5.pimBDP.children.0.pimBDFilterPol.children.0.pimBDSrcFilterPol.children.0.rtdmcRsFilterToRtMapPol.attributes.tDn == 'uni/tn-ansible_test/rtmap-ansible_route_map_pol' + - nm_bd_pim_s_again.current.0.fvBD.children.5.pimBDP.children.0.pimBDFilterPol.children | length == 1 + - nm_bd_pim_s_again.current.0.fvBD.children.5.pimBDP.children.0.pimBDFilterPol.children.0.pimBDSrcFilterPol.children.0.rtdmcRsFilterToRtMapPol.attributes.tDn == 'uni/tn-ansible_test/rtmap-ansible_route_map_pol' + - nm_bd_pim_s_again.previous.0.fvBD.children.5.pimBDP.children.0.pimBDFilterPol.children | length == 1 + - nm_bd_pim_s_again.previous.0.fvBD.children.5.pimBDP.children.0.pimBDFilterPol.children.0.pimBDSrcFilterPol.children.0.rtdmcRsFilterToRtMapPol.attributes.tDn == 'uni/tn-ansible_test/rtmap-ansible_route_map_pol' + - nm_bd_pim_s_remove.previous == nm_bd_pim_s.current + - nm_bd_pim_s_remove.current.0.fvBD.children.5.pimBDP.children.0.pimBDFilterPol.children.0.pimBDSrcFilterPol.children.0.rtdmcRsFilterToRtMapPol.attributes.tDn == '' + - cm_bd_pim_d is changed + - cm_bd_pim_d.current == [] + - cm_bd_pim_d.previous == [] + - cm_bd_pim_d.proposed.fvBD.children.3.pimBDP.children.0.pimBDFilterPol.children | length == 1 + - cm_bd_pim_d.proposed.fvBD.children.3.pimBDP.children.0.pimBDFilterPol.children.0.pimBDDestFilterPol.children.0.rtdmcRsFilterToRtMapPol.attributes.tDn == 'uni/tn-ansible_test/rtmap-ansible_route_map_pol' + - nm_bd_pim_d is changed + - nm_bd_pim_d.previous == [] + - nm_bd_pim_d.current.0.fvBD.children.5.pimBDP.children.0.pimBDFilterPol.children | length == 1 + - nm_bd_pim_d.current.0.fvBD.children.5.pimBDP.children.0.pimBDFilterPol.children.0.pimBDDestFilterPol.children.0.rtdmcRsFilterToRtMapPol.attributes.tDn == 'uni/tn-ansible_test/rtmap-ansible_route_map_pol' + - nm_bd_pim_d_again.current.0.fvBD.children.5.pimBDP.children.0.pimBDFilterPol.children | length == 1 + - nm_bd_pim_d_again.current.0.fvBD.children.5.pimBDP.children.0.pimBDFilterPol.children.0.pimBDDestFilterPol.children.0.rtdmcRsFilterToRtMapPol.attributes.tDn == 'uni/tn-ansible_test/rtmap-ansible_route_map_pol' + - nm_bd_pim_d_again.previous.0.fvBD.children.5.pimBDP.children.0.pimBDFilterPol.children | length == 1 + - nm_bd_pim_d_again.previous.0.fvBD.children.5.pimBDP.children.0.pimBDFilterPol.children.0.pimBDDestFilterPol.children.0.rtdmcRsFilterToRtMapPol.attributes.tDn == 'uni/tn-ansible_test/rtmap-ansible_route_map_pol' + - nm_bd_pim_d_remove.previous == nm_bd_pim_d.current + - nm_bd_pim_d_remove.current.0.fvBD.children.5.pimBDP.children.0.pimBDFilterPol.children.0.pimBDDestFilterPol.children.0.rtdmcRsFilterToRtMapPol.attributes.tDn == '' + + # TEST NO VERIFICATION + - name: create bd with no verification (check mode) + cisco.aci.aci_bd: &aci_bd_no_verify + <<: *aci_bd_present + bd: anstest-no-verify + no_verification: true + check_mode: true + register: bd_present_no_verify_cm + + - name: create bd with no verification + cisco.aci.aci_bd: + <<: *aci_bd_no_verify + register: bd_present_no_verify + + - name: create bd with no verification again + cisco.aci.aci_bd: + <<: *aci_bd_no_verify + register: bd_present_no_verify_again + + - name: update bd with no verification + cisco.aci.aci_bd: + <<: *aci_bd_no_verify + description: Ansible Test No Verify + register: update_bd_present_no_verify + + - name: delete bd with no verification + cisco.aci.aci_bd: + <<: *aci_bd_no_verify + state: absent + register: delete_bd_present_no_verify + + - name: delete bd with no verification again + cisco.aci.aci_bd: + <<: *aci_bd_no_verify + state: absent + register: delete_bd_present_no_verify_again + + - name: no verification asserts + ansible.builtin.assert: + that: + - bd_present_no_verify_cm is changed + - bd_present_no_verify_cm.current_verified == false + - bd_present_no_verify_cm.current.0 == bd_present_no_verify_cm.proposed + - bd_present_no_verify is changed + - bd_present_no_verify.current_verified == false + - bd_present_no_verify.current.0 == bd_present_no_verify.proposed + - bd_present_no_verify.previous == [] + - bd_present_no_verify_again is not changed + - bd_present_no_verify_again.current_verified == true + - bd_present_no_verify_again.current.0.fvBD.attributes.name == "anstest-no-verify" + - bd_present_no_verify_again.current.0.fvBD.attributes.descr == "Ansible Test" + - bd_present_no_verify_again.previous.0.fvBD.attributes.name == "anstest-no-verify" + - bd_present_no_verify_again.previous.0.fvBD.attributes.descr == "Ansible Test" + - update_bd_present_no_verify is changed + - update_bd_present_no_verify.current_verified == false + - update_bd_present_no_verify.current.0 == update_bd_present_no_verify.proposed + - update_bd_present_no_verify.previous.0.fvBD.attributes.name == "anstest-no-verify" + - update_bd_present_no_verify.previous.0.fvBD.attributes.descr == "Ansible Test" + - delete_bd_present_no_verify is changed + - delete_bd_present_no_verify.current_verified == false + - delete_bd_present_no_verify.current.0 == delete_bd_present_no_verify.proposed + - delete_bd_present_no_verify.previous.0.fvBD.attributes.name == "anstest-no-verify" + - delete_bd_present_no_verify.previous.0.fvBD.attributes.descr == "Ansible Test No Verify" + - delete_bd_present_no_verify_again is not changed + - delete_bd_present_no_verify_again.current_verified == true + - delete_bd_present_no_verify_again.current == [] + - delete_bd_present_no_verify_again.previous == [] + - delete_bd_present_no_verify_again.proposed == {} - name: get all bd cisco.aci.aci_bd: &aci_query @@ -230,27 +598,27 @@ register: query_bd - name: query asserts - assert: + ansible.builtin.assert: that: - query_all is not changed - query_all.current | length > 1 - query_all.current.0.fvBD is defined - - '"rsp-subtree-class=fvRsBDToNdP,fvRsBDToProfile,fvRsBdToEpRet,fvRsCtx,fvRsIgmpsn" in query_all.filter_string' + - '"rsp-subtree-class=fvAccP,fvRsABDPolMonPol,fvRsBDToFhs,fvRsBDToNdP,fvRsBDToProfile,fvRsBdToEpRet,fvRsCtx,fvRsIgmpsn,fvRsMldsn,igmpIfP,igmpRsIfPol" in query_all.filter_string' - '"class/fvBD.json" in query_all.url' - query_tenant is not changed - query_tenant.current | length == 1 - query_tenant.current.0.fvTenant.children | length == 2 - - '"rsp-subtree-class=fvBD,fvRsBDToNdP,fvRsBDToProfile,fvRsBdToEpRet,fvRsCtx,fvRsIgmpsn" in query_tenant.filter_string' + - '"rsp-subtree-class=fvAccP,fvBD,fvRsABDPolMonPol,fvRsBDToFhs,fvRsBDToNdP,fvRsBDToProfile,fvRsBdToEpRet,fvRsCtx,fvRsIgmpsn,fvRsMldsn,igmpIfP,igmpRsIfPol" in query_tenant.filter_string' - '"tn-ansible_test.json" in query_tenant.url' - query_bd_bd is not changed - query_bd_bd.current != [] - '"query-target-filter=eq(fvBD.name,\"anstest\")" in query_bd_bd.filter_string' - - '"rsp-subtree-class=fvRsBDToNdP,fvRsBDToProfile,fvRsBdToEpRet,fvRsCtx,fvRsIgmpsn" in query_bd_bd.filter_string' + - '"rsp-subtree-class=fvAccP,fvRsABDPolMonPol,fvRsBDToFhs,fvRsBDToNdP,fvRsBDToProfile,fvRsBdToEpRet,fvRsCtx,fvRsIgmpsn,fvRsMldsn,igmpIfP,igmpRsIfPol" in query_bd_bd.filter_string' - '"class/fvBD.json" in query_bd_bd.url' - query_bd is not changed - query_bd.current | length == 1 - query_bd.current.0.fvBD.attributes.name == "anstest" - - '"rsp-subtree-class=fvRsBDToNdP,fvRsBDToProfile,fvRsBdToEpRet,fvRsCtx,fvRsIgmpsn" in query_bd.filter_string' + - '"rsp-subtree-class=fvAccP,fvRsABDPolMonPol,fvRsBDToFhs,fvRsBDToNdP,fvRsBDToProfile,fvRsBdToEpRet,fvRsCtx,fvRsIgmpsn,fvRsMldsn,igmpIfP,igmpRsIfPol" in query_bd.filter_string' - '"tn-ansible_test/BD-anstest.json" in query_bd.url' - name: delete bd - check mode works @@ -283,7 +651,7 @@ register: bd_absent_missing_param - name: asserts for deletion task - assert: + ansible.builtin.assert: that: - bd_absent_check_mode is changed - bd_absent_check_mode.proposed == {} @@ -294,6 +662,40 @@ - bd_absent_missing_param is failed - 'bd_absent_missing_param.msg == "state is absent but all of the following are missing: bd"' + - name: delete FHS - cleanup before ending tests + cisco.aci.aci_rest: + <<: *aci_info + path: /api/mo/uni/tn-ansible_test/bdpol-ansible_fhs.json + method: delete + + - name: delete IGMP Snoop Policy - cleanup before ending tests + cisco.aci.aci_rest: + <<: *aci_info + path: /api/mo/uni/tn-ansible_test/snPol-ansible_igmp_snoop.json + method: delete + + - name: delete MLD Snoop Policy - cleanup before ending tests + cisco.aci.aci_rest: + <<: *aci_info + path: /api/mo/uni/tn-ansible_test/mldsnoopPol-ansible_mld_snoop.json + method: delete + + - name: delete IGMP Interface Policy - cleanup before ending tests + cisco.aci.aci_igmp_interface_policy: + <<: *aci_igmp_policy_present + state: absent + + - name: delete Monitoring Policy - cleanup before ending tests + cisco.aci.aci_epg_monitoring_policy: + <<: *aci_monitoring_policy_present + state: absent + + - name: delete PIM Route Map Policy - cleanup before ending tests + cisco.aci.aci_pim_route_map_policy: + <<: *aci_route_map_policy_present + state: absent + when: version.current.0.topSystem.attributes.version is version('5.2', '>=') + - name: delete vrf - cleanup before ending tests cisco.aci.aci_vrf: <<: *aci_vrf_present diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_bd_dhcp_label/tasks/main.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_bd_dhcp_label/tasks/main.yml index 937ea80a3..c7641b7b0 100644 --- a/ansible_collections/cisco/aci/tests/integration/targets/aci_bd_dhcp_label/tasks/main.yml +++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_bd_dhcp_label/tasks/main.yml @@ -4,12 +4,12 @@ # GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) - name: Test that we have an ACI APIC host, ACI username and ACI password - fail: + ansible.builtin.fail: msg: 'Please define the following variables: aci_hostname, aci_username and aci_password.' when: aci_hostname is not defined or aci_username is not defined or aci_password is not defined - name: Set vars - set_fact: + ansible.builtin.set_fact: aci_info: &aci_info host: "{{ aci_hostname }}" username: "{{ aci_username }}" @@ -21,26 +21,26 @@ # CLEAN ENVIRONMENT - name: Remove the ansible_tenant - aci_tenant: + cisco.aci.aci_tenant: <<: *aci_info tenant: ansible_tenant state: absent - name: Verify Cloud and Non-Cloud Sites in use. - include_tasks: ../../../../../../integration/targets/aci_cloud_provider/tasks/main.yml + ansible.builtin.include_tasks: ../../../../../../integration/targets/aci_cloud_provider/tasks/main.yml - name: Execute tasks only for non-cloud sites when: query_cloud.current == [] # This condition will execute only non-cloud sites block: # block specifies execution of tasks within, based on conditions - name: Add a new tenant - aci_tenant: + cisco.aci.aci_tenant: <<: *aci_info tenant: ansible_tenant description: Ansible tenant state: present - name: create bd - creation works - aci_bd: + cisco.aci.aci_bd: <<: *aci_info tenant: ansible_tenant bd: database @@ -48,7 +48,7 @@ #CREATE LABELS - name: Create a new DHCP Relay Label to a Bridge Domain - check mode - aci_bd_dhcp_label: + cisco.aci.aci_bd_dhcp_label: <<: *aci_info tenant: ansible_tenant bd: database @@ -59,13 +59,13 @@ register: cm_dhcp_label1 - name: Verify creation of label1 in check mode - assert: + ansible.builtin.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: + cisco.aci.aci_bd_dhcp_label: <<: *aci_info tenant: ansible_tenant bd: database @@ -75,7 +75,7 @@ register: nm_dhcp_label1 - name: Verify creation of label1 - assert: + ansible.builtin.assert: that: - nm_dhcp_label1 is changed - nm_dhcp_label1.current.0.dhcpLbl.attributes.dn == 'uni/tn-ansible_tenant/BD-database/dhcplbl-label1' @@ -83,7 +83,7 @@ - nm_dhcp_label1.current.0.dhcpLbl.attributes.annotation == 'orchestrator:ansible' - name: Create another DHCP Relay Label to a Bridge Domain - normal mode - aci_bd_dhcp_label: + cisco.aci.aci_bd_dhcp_label: <<: *aci_info tenant: ansible_tenant bd: database @@ -93,7 +93,7 @@ register: nm_dhcp_label2 - name: Verify creation of label2 - assert: + ansible.builtin.assert: that: - nm_dhcp_label2 is changed - nm_dhcp_label2.current.0.dhcpLbl.attributes.dn == 'uni/tn-ansible_tenant/BD-database/dhcplbl-label2' @@ -101,7 +101,7 @@ #QUERY LABELS - name: Query a DHCP Relay Label of a Bridge Domain - aci_bd_dhcp_label: + cisco.aci.aci_bd_dhcp_label: <<: *aci_info tenant: ansible_tenant bd: database @@ -111,13 +111,13 @@ register: query_dhcp_label1 - name: Verify query of label - assert: + ansible.builtin.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: + cisco.aci.aci_bd_dhcp_label: <<: *aci_info tenant: ansible_tenant bd: database @@ -125,13 +125,13 @@ register: query_all_labels - name: Verify query all of labels - assert: + ansible.builtin.assert: that: - query_all_labels is not changed #REMOVE LABELS - name: Remove a DHCP Relay Label for a Bridge Domain - aci_bd_dhcp_label: + cisco.aci.aci_bd_dhcp_label: <<: *aci_info tenant: ansible_tenant bd: database @@ -141,14 +141,14 @@ register: delete_dhcp_label - name: Verify deletion of label - assert: + ansible.builtin.assert: that: - delete_dhcp_label is changed - delete_dhcp_label.current == [] # CLEAN ENVIRONMENT AGAIN - name: Remove the ansible_tenant - aci_tenant: + cisco.aci.aci_tenant: <<: *aci_info tenant: ansible_tenant state: absent \ No newline at end of file diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_bd_rogue_exception_mac/aliases b/ansible_collections/cisco/aci/tests/integration/targets/aci_bd_rogue_exception_mac/aliases new file mode 100644 index 000000000..209b793f9 --- /dev/null +++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_bd_rogue_exception_mac/aliases @@ -0,0 +1,2 @@ +# No ACI simulator yet, so not enabled +# unsupported diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_bd_rogue_exception_mac/tasks/main.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_bd_rogue_exception_mac/tasks/main.yml new file mode 100644 index 000000000..7aebbb44d --- /dev/null +++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_bd_rogue_exception_mac/tasks/main.yml @@ -0,0 +1,186 @@ +# Test code for the ACI modules +# Copyright: (c) 2024, Samita Bhattacharjee (@samitab) + +# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) + +- name: Test that we have an ACI APIC host, ACI username and ACI password + ansible.builtin.fail: + msg: 'Please define the following variables: aci_hostname, aci_username and aci_password.' + when: aci_hostname is not defined or aci_username is not defined or aci_password is not defined + +- name: Set vars + ansible.builtin.set_fact: + aci_info: &aci_info + host: "{{ aci_hostname }}" + username: "{{ aci_username }}" + password: "{{ aci_password }}" + validate_certs: '{{ aci_validate_certs | default(false) }}' + use_ssl: '{{ aci_use_ssl | default(true) }}' + use_proxy: '{{ aci_use_proxy | default(true) }}' + output_level: '{{ aci_output_level | default("info") }}' + +- name: Query system information + cisco.aci.aci_system: + <<: *aci_info + id: 1 + state: query + register: version + +# CLEAN ENVIRONMENT +- name: Remove the ansible_tenant + cisco.aci.aci_tenant: &aci_tenant_absent + <<: *aci_info + state: absent + tenant: ansible_test + +- name: Verify Cloud and Non-Cloud Sites in use. + ansible.builtin.include_tasks: ../../../../../../integration/targets/aci_cloud_provider/tasks/main.yml + +- name: Execute tasks only for non-cloud sites and APIC version >= 5.2 + when: query_cloud.current == [] and version.current.0.topSystem.attributes.version is version('5.2', '>=') + block: + - name: Create tenant + cisco.aci.aci_tenant: &aci_tenant_present + <<: *aci_tenant_absent + state: present + 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 rogue exception mac does not exist for tests to kick off + cisco.aci.aci_bd_rogue_exception_mac: &aci_rogue_exception_mac_absent + <<: *aci_bd_present + state: absent + mac: "AA:BB:CC:DD:EE:11" + description: 1st MAC + + - name: Ensure second rogue exception mac does not exist for tests to kick off + cisco.aci.aci_bd_rogue_exception_mac: &aci_rogue_exception_mac_absent_2 + <<: *aci_rogue_exception_mac_absent + mac: "AA-BB-CC-DD-EE-22" + description: 2nd MAC + + + - name: Create first rogue exception mac in bd (check_mode) + cisco.aci.aci_bd_rogue_exception_mac: &aci_bd_rogue_exception_mac_present + <<: *aci_rogue_exception_mac_absent + state: present + check_mode: true + register: cm_bd_rogue_exception_mac + + - name: Create first rogue exception mac in bd (normal_mode) + cisco.aci.aci_bd_rogue_exception_mac: + <<: *aci_bd_rogue_exception_mac_present + register: nm_bd_rogue_exception_mac + + - name: Create first rogue exception mac in bd again - testing idempotency + cisco.aci.aci_bd_rogue_exception_mac: + <<: *aci_bd_rogue_exception_mac_present + register: bd_rogue_exception_mac_idempotency + + - name: Create second rogue exception mac in bd + cisco.aci.aci_bd_rogue_exception_mac: &aci_bd_rogue_exception_mac_present_2 + <<: *aci_rogue_exception_mac_absent_2 + state: present + register: nm_bd_rogue_exception_mac_2 + + - name: Asserts for creation tasks + ansible.builtin.assert: + that: + - cm_bd_rogue_exception_mac is changed + - cm_bd_rogue_exception_mac.previous == [] + - cm_bd_rogue_exception_mac.current == [] + - cm_bd_rogue_exception_mac.proposed.fvRogueExceptionMac.attributes.dn == "uni/tn-ansible_test/BD-anstest/rgexpmac-AA:BB:CC:DD:EE:11" + - cm_bd_rogue_exception_mac.proposed.fvRogueExceptionMac.attributes.mac == "AA:BB:CC:DD:EE:11" + - cm_bd_rogue_exception_mac.proposed.fvRogueExceptionMac.attributes.descr == "1st MAC" + - nm_bd_rogue_exception_mac is changed + - nm_bd_rogue_exception_mac.current.0.fvRogueExceptionMac.attributes.dn == "uni/tn-ansible_test/BD-anstest/rgexpmac-AA:BB:CC:DD:EE:11" + - nm_bd_rogue_exception_mac.current.0.fvRogueExceptionMac.attributes.mac == "AA:BB:CC:DD:EE:11" + - nm_bd_rogue_exception_mac.current.0.fvRogueExceptionMac.attributes.descr == "1st MAC" + - bd_rogue_exception_mac_idempotency is not changed + - bd_rogue_exception_mac_idempotency.current == bd_rogue_exception_mac_idempotency.previous + - bd_rogue_exception_mac_idempotency.sent == {} + - nm_bd_rogue_exception_mac_2 is changed + - nm_bd_rogue_exception_mac_2.current.0.fvRogueExceptionMac.attributes.dn == "uni/tn-ansible_test/BD-anstest/rgexpmac-AA:BB:CC:DD:EE:22" + - nm_bd_rogue_exception_mac_2.current.0.fvRogueExceptionMac.attributes.mac == "AA:BB:CC:DD:EE:22" + - nm_bd_rogue_exception_mac_2.current.0.fvRogueExceptionMac.attributes.descr == "2nd MAC" + + - name: Query all bds bound to rogue exception mac + cisco.aci.aci_bd_rogue_exception_mac: + <<: *aci_tenant_present + state: query + output_level: debug + register: query_all_bd_to_rogue_exception_mac + + - name: Query first bd with first rogue exception mac + cisco.aci.aci_bd_rogue_exception_mac: + <<: *aci_bd_rogue_exception_mac_present + state: query + output_level: debug + register: query_first_bd_to_rogue_exception_mac + + - name: Asserts query tasks + ansible.builtin.assert: + that: + - query_all_bd_to_rogue_exception_mac is not changed + - '"fvRogueExceptionMac" in query_all_bd_to_rogue_exception_mac.filter_string' + - query_all_bd_to_rogue_exception_mac.current.0.fvTenant.children.0.fvBD.children | length == 2 + - query_all_bd_to_rogue_exception_mac.current.0.fvTenant.children.0.fvBD.attributes.name == "anstest" + - query_all_bd_to_rogue_exception_mac.current.0.fvTenant.children.0.fvBD.children.0.fvRogueExceptionMac.attributes.rn == "rgexpmac-AA:BB:CC:DD:EE:22" + - query_all_bd_to_rogue_exception_mac.current.0.fvTenant.children.0.fvBD.children.1.fvRogueExceptionMac.attributes.rn == "rgexpmac-AA:BB:CC:DD:EE:11" + - query_first_bd_to_rogue_exception_mac is not changed + - '"tn-ansible_test/BD-anstest/rgexpmac-AA:BB:CC:DD:EE:11.json" in query_first_bd_to_rogue_exception_mac.url' + + - name: Delete first rogue exception mac (check_mode) + cisco.aci.aci_bd_rogue_exception_mac: + <<: *aci_bd_rogue_exception_mac_present + state: absent + check_mode: true + register: cm_unbind_bd_to_rogue_exception_mac + + - name: Delete first rogue exception mac (normal_mode) + cisco.aci.aci_bd_rogue_exception_mac: + <<: *aci_bd_rogue_exception_mac_present + state: absent + register: nm_unbind_bd_to_rogue_exception_mac + + - name: Delete first rogue exception mac again - testing idempotency + cisco.aci.aci_bd_rogue_exception_mac: + <<: *aci_bd_rogue_exception_mac_present + state: absent + register: unbind_bd_to_rogue_exception_mac_idempotency + + - name: Delete second rogue exception mac + cisco.aci.aci_bd_rogue_exception_mac: + <<: *aci_bd_rogue_exception_mac_present_2 + state: absent + register: nm_unbind_bd_to_rogue_exception_mac_2 + + - name: Asserts for deletion tasks + ansible.builtin.assert: + that: + - cm_unbind_bd_to_rogue_exception_mac is changed + - cm_unbind_bd_to_rogue_exception_mac.current == cm_unbind_bd_to_rogue_exception_mac.previous + - cm_unbind_bd_to_rogue_exception_mac.proposed == {} + - nm_unbind_bd_to_rogue_exception_mac is changed + - nm_unbind_bd_to_rogue_exception_mac.previous != [] + - nm_unbind_bd_to_rogue_exception_mac.proposed == {} + - nm_unbind_bd_to_rogue_exception_mac.current == [] + - nm_unbind_bd_to_rogue_exception_mac.previous == cm_unbind_bd_to_rogue_exception_mac.current + - unbind_bd_to_rogue_exception_mac_idempotency is not changed + - unbind_bd_to_rogue_exception_mac_idempotency.previous == [] + - unbind_bd_to_rogue_exception_mac_idempotency.current == [] + - unbind_bd_to_rogue_exception_mac_idempotency.previous == [] + - nm_unbind_bd_to_rogue_exception_mac_2 is changed + - nm_unbind_bd_to_rogue_exception_mac_2.previous != [] + - nm_unbind_bd_to_rogue_exception_mac_2.current == [] + + - name: Delete tenant - cleanup before ending tests + cisco.aci.aci_tenant: + <<: *aci_tenant_present + state: absent + when: tenant_present is changed diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_bd_subnet/tasks/main.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_bd_subnet/tasks/main.yml index 4bc8e26c4..8d05b2e16 100644 --- a/ansible_collections/cisco/aci/tests/integration/targets/aci_bd_subnet/tasks/main.yml +++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_bd_subnet/tasks/main.yml @@ -4,12 +4,12 @@ # GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) - name: Test that we have an ACI APIC host, ACI username and ACI password - fail: + ansible.builtin.fail: msg: 'Please define the following variables: aci_hostname, aci_username and aci_password.' when: aci_hostname is not defined or aci_username is not defined or aci_password is not defined - name: Set vars - set_fact: + ansible.builtin.set_fact: aci_info: &aci_info host: "{{ aci_hostname }}" username: "{{ aci_username }}" @@ -27,7 +27,7 @@ register: version - name: Verify Cloud and Non-Cloud Sites in use. - include_tasks: ../../../../../../integration/targets/aci_cloud_provider/tasks/main.yml + ansible.builtin.include_tasks: ../../../../../../integration/targets/aci_cloud_provider/tasks/main.yml - name: Execute tasks only for non-cloud sites when: query_cloud.current == [] # This condition will execute only non-cloud sites @@ -128,7 +128,7 @@ ignore_errors: true - name: assert for subnet creation tasks - assert: + ansible.builtin.assert: that: - create_check_mode is changed - create_check_mode.sent.fvSubnet.attributes.descr == create_subnet.sent.fvSubnet.attributes.descr == 'Ansible Test' @@ -150,7 +150,7 @@ - 'create_incomplete_data.msg == "state is present but all of the following are missing: bd"' - name: assert for subnet for task with version < 5 - assert: + ansible.builtin.assert: that: - create_subnet2 is changed - create_subnet2.sent == create_subnet2.proposed @@ -160,7 +160,7 @@ when: version.current.0.topSystem.attributes.version is version('5', '<') - name: assert for subnet ip_data_learning for task with version >=5 - assert: + ansible.builtin.assert: that: - create_subnet.current.0.fvSubnet.attributes.ipDPLearning == 'enabled' - create_subnet2_5 is changed @@ -225,7 +225,7 @@ register: get_subnets_gateway - name: asserts for query tasks - assert: + ansible.builtin.assert: that: - get_all is not changed - get_all.current | length > 1 @@ -268,7 +268,7 @@ register: error_mask_ipv6 - name: asserts for mask error handling - assert: + ansible.builtin.assert: that: - error_mask_ipv4.msg == "Valid Subnet Masks are 0 to 32 for IPv4 Addresses" - error_mask_ipv6.msg == "Valid Subnet Masks are 0 to 128 for IPv6 Addresses" @@ -294,7 +294,7 @@ register: delete_idempotency - name: asserts for deletion task - assert: + ansible.builtin.assert: that: - delete_check_mode is changed - delete_check_mode.proposed == {} diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_bd_to_l3out/tasks/main.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_bd_to_l3out/tasks/main.yml index 7d1313fb2..94e7b6db4 100644 --- a/ansible_collections/cisco/aci/tests/integration/targets/aci_bd_to_l3out/tasks/main.yml +++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_bd_to_l3out/tasks/main.yml @@ -4,12 +4,12 @@ # GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) - name: Test that we have an ACI APIC host, ACI username and ACI password - fail: + ansible.builtin.fail: msg: 'Please define the following variables: aci_hostname, aci_username and aci_password.' when: aci_hostname is not defined or aci_username is not defined or aci_password is not defined - name: Set vars - set_fact: + ansible.builtin.set_fact: aci_info: &aci_info host: "{{ aci_hostname }}" username: "{{ aci_username }}" @@ -27,7 +27,7 @@ tenant: ansible_test - name: Verify Cloud and Non-Cloud Sites in use. - include_tasks: ../../../../../../integration/targets/aci_cloud_provider/tasks/main.yml + ansible.builtin.include_tasks: ../../../../../../integration/targets/aci_cloud_provider/tasks/main.yml - name: Execute tasks only for non-cloud sites when: query_cloud.current == [] # This condition will execute only non-cloud sites @@ -104,7 +104,7 @@ register: nm_bd_to_l3out_2 - name: asserts for creation tasks - assert: + ansible.builtin.assert: that: - cm_bd_to_l3out is changed - cm_bd_to_l3out.previous == [] @@ -130,7 +130,7 @@ register: query_first_bd_to_l3out - name: asserts query tasks - assert: + ansible.builtin.assert: that: - query_all_bd_to_l3out is not changed - '"fvRsBDToOut" in query_all_bd_to_l3out.filter_string' @@ -168,7 +168,7 @@ register: nm_unbind_bd_to_l3out_2 - name: asserts for deletion tasks - assert: + ansible.builtin.assert: that: - cm_unbind_bd_to_l3out is changed - cm_unbind_bd_to_l3out.proposed == {} @@ -186,11 +186,21 @@ <<: *aci_bd_present state: absent + - name: delete bd_2 - cleanup before ending tests + cisco.aci.aci_bd: + <<: *aci_bd_present_2 + state: absent + - name: delete l3out - cleanup before ending tests cisco.aci.aci_l3out: <<: *aci_l3_out_present state: absent + - name: delete l3out_2 - cleanup before ending tests + cisco.aci.aci_l3out: + <<: *aci_l3_out_present_2 + state: absent + - name: delete vrf - cleanup before ending tests cisco.aci.aci_vrf: <<: *aci_vrf_present diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_bd_to_netflow_monitor_policy/aliases b/ansible_collections/cisco/aci/tests/integration/targets/aci_bd_to_netflow_monitor_policy/aliases new file mode 100644 index 000000000..209b793f9 --- /dev/null +++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_bd_to_netflow_monitor_policy/aliases @@ -0,0 +1,2 @@ +# No ACI simulator yet, so not enabled +# unsupported diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_bd_to_netflow_monitor_policy/tasks/main.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_bd_to_netflow_monitor_policy/tasks/main.yml new file mode 100644 index 000000000..9a7a44d16 --- /dev/null +++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_bd_to_netflow_monitor_policy/tasks/main.yml @@ -0,0 +1,191 @@ +# Test code for the ACI modules +# Copyright: (c) 2024, Samita Bhattacharjee (@samitab) + +# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) + +- name: Test that we have an ACI APIC host, ACI username and ACI password + ansible.builtin.fail: + msg: 'Please define the following variables: aci_hostname, aci_username and aci_password.' + when: aci_hostname is not defined or aci_username is not defined or aci_password is not defined + +- name: Set vars + ansible.builtin.set_fact: + aci_info: &aci_info + host: "{{ aci_hostname }}" + username: "{{ aci_username }}" + password: "{{ aci_password }}" + validate_certs: '{{ aci_validate_certs | default(false) }}' + use_ssl: '{{ aci_use_ssl | default(true) }}' + use_proxy: '{{ aci_use_proxy | default(true) }}' + output_level: '{{ aci_output_level | default("info") }}' + +# CLEAN ENVIRONMENT +- name: Remove the ansible_tenant + cisco.aci.aci_tenant: &aci_tenant_absent + <<: *aci_info + state: absent + tenant: ansible_test + +- name: Verify Cloud and Non-Cloud Sites in use. + ansible.builtin.include_tasks: ../../../../../../integration/targets/aci_cloud_provider/tasks/main.yml + +- name: Execute tasks only for non-cloud sites + when: query_cloud.current == [] # This condition will execute only non-cloud sites + block: # block specifies execution of tasks within, based on conditions + - name: Create tenant + cisco.aci.aci_tenant: &aci_tenant_present + <<: *aci_tenant_absent + state: present + + - name: Create first netflow monitor policy + cisco.aci.aci_netflow_monitor_policy: + <<: *aci_tenant_absent + netflow_monitor_policy: ansible_netflow_monitor_policy + state: present + + - name: Create second netflow monitor policy + cisco.aci.aci_netflow_monitor_policy: + <<: *aci_tenant_absent + netflow_monitor_policy: ansible_netflow_monitor_policy_2 + state: present + + - name: Create first bd + cisco.aci.aci_bd: &aci_bd_present + <<: *aci_tenant_present + bd: anstest + + - name: Create second bd + cisco.aci.aci_bd: &aci_bd_present_2 + <<: *aci_tenant_present + bd: anstest_2 + + - name: Ensure first binding bd to netflow monitor policy does not exist + cisco.aci.aci_bd_to_netflow_monitor_policy: &aci_bd_to_netflow_monitor_policy_absent + <<: *aci_bd_present + netflow_monitor_policy: ansible_netflow_monitor_policy + filter_type: ipv4 + state: absent + + - name: Ensure second binding bd to netflow monitor policy does not exist + cisco.aci.aci_bd_to_netflow_monitor_policy: &aci_bd_to_netflow_monitor_policy_absent_2 + <<: *aci_bd_present_2 + netflow_monitor_policy: ansible_netflow_monitor_policy_2 + filter_type: ipv6 + state: absent + + - name: Bind bd to netflow monitor policy - first binding (check_mode) + cisco.aci.aci_bd_to_netflow_monitor_policy: &aci_bd_to_netflow_monitor_policy_present + <<: *aci_bd_to_netflow_monitor_policy_absent + state: present + check_mode: true + register: cm_bd_to_netflow_monitor_policy + + - name: Bind bd to netflow monitor policy - first binding (normal_mode) + cisco.aci.aci_bd_to_netflow_monitor_policy: + <<: *aci_bd_to_netflow_monitor_policy_present + register: nm_bd_to_netflow_monitor_policy + + - name: Bind bd to netflow monitor policy again - testing idempotency + cisco.aci.aci_bd_to_netflow_monitor_policy: + <<: *aci_bd_to_netflow_monitor_policy_present + register: bd_to_netflow_monitor_policy_idempotency + + - name: Bind bd to netflow monitor policy again - second binding + cisco.aci.aci_bd_to_netflow_monitor_policy: &aci_bd_to_netflow_monitor_policy_present_2 + <<: *aci_bd_to_netflow_monitor_policy_absent_2 + state: present + register: nm_bd_to_netflow_monitor_policy_2 + + - name: Asserts for creation tasks + ansible.builtin.assert: + that: + - cm_bd_to_netflow_monitor_policy is changed + - cm_bd_to_netflow_monitor_policy.previous == [] + - cm_bd_to_netflow_monitor_policy.current == [] + - cm_bd_to_netflow_monitor_policy.proposed.fvRsBDToNetflowMonitorPol.attributes.dn == "uni/tn-ansible_test/BD-anstest/rsBDToNetflowMonitorPol-[ansible_netflow_monitor_policy]-ipv4" + - cm_bd_to_netflow_monitor_policy.proposed.fvRsBDToNetflowMonitorPol.attributes.tnNetflowMonitorPolName == "ansible_netflow_monitor_policy" + - nm_bd_to_netflow_monitor_policy is changed + - nm_bd_to_netflow_monitor_policy.current.0.fvRsBDToNetflowMonitorPol.attributes.dn == "uni/tn-ansible_test/BD-anstest/rsBDToNetflowMonitorPol-[ansible_netflow_monitor_policy]-ipv4" + - nm_bd_to_netflow_monitor_policy.current.0.fvRsBDToNetflowMonitorPol.attributes.tnNetflowMonitorPolName == "ansible_netflow_monitor_policy" + - bd_to_netflow_monitor_policy_idempotency is not changed + - bd_to_netflow_monitor_policy_idempotency.current == bd_to_netflow_monitor_policy_idempotency.previous + - bd_to_netflow_monitor_policy_idempotency.sent == {} + - nm_bd_to_netflow_monitor_policy_2 is changed + - nm_bd_to_netflow_monitor_policy_2.current.0.fvRsBDToNetflowMonitorPol.attributes.dn == "uni/tn-ansible_test/BD-anstest_2/rsBDToNetflowMonitorPol-[ansible_netflow_monitor_policy_2]-ipv6" + - nm_bd_to_netflow_monitor_policy_2.current.0.fvRsBDToNetflowMonitorPol.attributes.tnNetflowMonitorPolName == "ansible_netflow_monitor_policy_2" + + - name: Query all bds bound to netflow monitor policies + cisco.aci.aci_bd_to_netflow_monitor_policy: + <<: *aci_tenant_present + state: query + output_level: debug + register: query_all_bd_to_netflow_monitor_policy + + - name: Query first bd bound to first netflow monitor policy + cisco.aci.aci_bd_to_netflow_monitor_policy: + <<: *aci_bd_to_netflow_monitor_policy_present + state: query + output_level: debug + register: query_first_bd_to_netflow_monitor_policy + + - name: Asserts query tasks + ansible.builtin.assert: + that: + - query_all_bd_to_netflow_monitor_policy is not changed + - '"fvRsBDToNetflowMonitorPol" in query_all_bd_to_netflow_monitor_policy.filter_string' + - query_all_bd_to_netflow_monitor_policy.current.0.fvTenant.children | length >= 2 + - query_all_bd_to_netflow_monitor_policy.current.0.fvTenant.children.0.fvBD.attributes.name == "anstest_2" + - query_all_bd_to_netflow_monitor_policy.current.0.fvTenant.children.0.fvBD.children.0.fvRsBDToNetflowMonitorPol.attributes.tRn == "monitorpol-ansible_netflow_monitor_policy_2" + - query_all_bd_to_netflow_monitor_policy.current.0.fvTenant.children.1.fvBD.attributes.name == "anstest" + - query_all_bd_to_netflow_monitor_policy.current.0.fvTenant.children.1.fvBD.children.0.fvRsBDToNetflowMonitorPol.attributes.tRn == "monitorpol-ansible_netflow_monitor_policy" + - query_first_bd_to_netflow_monitor_policy is not changed + - '"tn-ansible_test/BD-anstest/rsBDToNetflowMonitorPol-[ansible_netflow_monitor_policy]-ipv4.json" in query_first_bd_to_netflow_monitor_policy.url' + + - name: Unbind bd to netflow monitor policy - first binding (check_mode) + cisco.aci.aci_bd_to_netflow_monitor_policy: + <<: *aci_bd_to_netflow_monitor_policy_present + state: absent + check_mode: true + register: cm_unbind_bd_to_netflow_monitor_policy + + - name: Unbind bd to netflow_monitor_policy - first binding (normal_mode) + cisco.aci.aci_bd_to_netflow_monitor_policy: + <<: *aci_bd_to_netflow_monitor_policy_present + state: absent + register: nm_unbind_bd_to_netflow_monitor_policy + + - name: Unbind bd to netflow_monitor_policy again - testing idempotency + cisco.aci.aci_bd_to_netflow_monitor_policy: + <<: *aci_bd_to_netflow_monitor_policy_present + state: absent + register: unbind_bd_to_netflow_monitor_policy_idempotency + + - name: Unbind bd to netflow_monitor_policy - second binding + cisco.aci.aci_bd_to_netflow_monitor_policy: + <<: *aci_bd_to_netflow_monitor_policy_present_2 + state: absent + register: nm_unbind_bd_to_netflow_monitor_policy_2 + + - name: Asserts for deletion tasks + ansible.builtin.assert: + that: + - cm_unbind_bd_to_netflow_monitor_policy is changed + - cm_unbind_bd_to_netflow_monitor_policy.current == cm_unbind_bd_to_netflow_monitor_policy.previous + - cm_unbind_bd_to_netflow_monitor_policy.proposed == {} + - nm_unbind_bd_to_netflow_monitor_policy is changed + - nm_unbind_bd_to_netflow_monitor_policy.previous != [] + - nm_unbind_bd_to_netflow_monitor_policy.proposed == {} + - nm_unbind_bd_to_netflow_monitor_policy.current == [] + - nm_unbind_bd_to_netflow_monitor_policy.previous == cm_unbind_bd_to_netflow_monitor_policy.current + - unbind_bd_to_netflow_monitor_policy_idempotency is not changed + - unbind_bd_to_netflow_monitor_policy_idempotency.proposed == {} + - unbind_bd_to_netflow_monitor_policy_idempotency.current == [] + - unbind_bd_to_netflow_monitor_policy_idempotency.previous == [] + - nm_unbind_bd_to_netflow_monitor_policy_2 is changed + - nm_unbind_bd_to_netflow_monitor_policy_2.previous != [] + - nm_unbind_bd_to_netflow_monitor_policy_2.current == [] + + - name: Delete tenant - cleanup before ending tests + cisco.aci.aci_tenant: + <<: *aci_tenant_present + state: absent diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_bfd_multihop_node_policy/aliases b/ansible_collections/cisco/aci/tests/integration/targets/aci_bfd_multihop_node_policy/aliases new file mode 100644 index 000000000..209b793f9 --- /dev/null +++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_bfd_multihop_node_policy/aliases @@ -0,0 +1,2 @@ +# No ACI simulator yet, so not enabled +# unsupported diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_bfd_multihop_node_policy/tasks/main.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_bfd_multihop_node_policy/tasks/main.yml new file mode 100644 index 000000000..99f853680 --- /dev/null +++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_bfd_multihop_node_policy/tasks/main.yml @@ -0,0 +1,245 @@ +# Test code for the ACI modules +# Copyright: (c) 2023, Anvitha Jain (@anvjain) + +# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) + +- name: Test that we have an ACI APIC host, ACI username and ACI password + fail: + msg: 'Please define the following variables: aci_hostname, aci_username and aci_password.' + when: aci_hostname is not defined or aci_username is not defined or aci_password is not defined + +- name: Set vars + ansible.builtin.set_fact: + aci_info: &aci_info + host: "{{ aci_hostname }}" + username: "{{ aci_username }}" + password: "{{ aci_password }}" + validate_certs: '{{ aci_validate_certs | default(false) }}' + use_ssl: '{{ aci_use_ssl | default(true) }}' + use_proxy: '{{ aci_use_proxy | default(true) }}' + output_level: debug + +- name: Query system information + cisco.aci.aci_system: + <<: *aci_info + id: 1 + state: query + register: version + +- name: Execute tasks only for non-cloud sites + when: version.current.0.topSystem.attributes.version is version('5.2', '>=') # This condition will execute only when APIC version >= 5.2 + block: # block specifies execution of tasks within, based on conditions + + # CLEAN ENVIRONMENT + - name: Remove the ansible_tenant + aci_tenant: + <<: *aci_info + tenant: ansible_tenant + state: absent + + - name: Add a new tenant + aci_tenant: + <<: *aci_info + tenant: ansible_tenant + description: Ansible tenant + state: present + + # CREATE BFD Multihop Node policy + - name: Add a new BFD Multihop Node policy - check mode + cisco.aci.aci_bfd_multihop_node_policy: &add_bfd_multihop_node_pol + <<: *aci_info + tenant: ansible_tenant + name: ansible_bfd_multihop_node_policy + description: Ansible BFD Multihop Node Policy + state: present + check_mode: true + register: cm_add_bfd_multihop_node_pol + + - name: Add a new BFD Multihop Node policy - normal mode + cisco.aci.aci_bfd_multihop_node_policy: + <<: *add_bfd_multihop_node_pol + state: present + register: nm_add_bfd_multihop_node_pol + + - name: Verify BFD Multihop Node Policy creation + assert: + that: + - cm_add_bfd_multihop_node_pol is changed + - nm_add_bfd_multihop_node_pol is changed + - cm_add_bfd_multihop_node_pol.previous == nm_add_bfd_multihop_node_pol.previous == [] + - cm_add_bfd_multihop_node_pol.proposed.bfdMhNodePol.attributes.dn == nm_add_bfd_multihop_node_pol.current.0.bfdMhNodePol.attributes.dn == "uni/tn-ansible_tenant/bfdMhNodePol-ansible_bfd_multihop_node_policy" + - cm_add_bfd_multihop_node_pol.proposed.bfdMhNodePol.attributes.name == nm_add_bfd_multihop_node_pol.current.0.bfdMhNodePol.attributes.name == "ansible_bfd_multihop_node_policy" + - cm_add_bfd_multihop_node_pol.proposed.bfdMhNodePol.attributes.descr == nm_add_bfd_multihop_node_pol.current.0.bfdMhNodePol.attributes.descr == "Ansible BFD Multihop Node Policy" + + - name: Add a new BFD Multihop Node policy again - idempotency + cisco.aci.aci_bfd_multihop_node_policy: + <<: *add_bfd_multihop_node_pol + state: present + register: add_bfd_multihop_node_pol_again + + - name: Verify BFD Multihop Node Policy creation again - idempotency + assert: + that: + - add_bfd_multihop_node_pol_again is not changed + - add_bfd_multihop_node_pol_again.previous != [] + - add_bfd_multihop_node_pol_again.current | length == 1 + - add_bfd_multihop_node_pol_again.previous | length == 1 + + - name: Modify a BFD Multihop Node policy + cisco.aci.aci_bfd_multihop_node_policy: + <<: *add_bfd_multihop_node_pol + admin_state: disabled + detection_multiplier: 5 + min_transmit_interval: 270 + min_receive_interval: 500 + state: present + register: update_bfd_multihop_node_pol + + - name: Verify modifying BFD Multihop Node Policy + assert: + that: + - update_bfd_multihop_node_pol is changed + - update_bfd_multihop_node_pol.previous != update_bfd_multihop_node_pol.current + - update_bfd_multihop_node_pol.current.0.bfdMhNodePol.attributes.dn == "uni/tn-ansible_tenant/bfdMhNodePol-ansible_bfd_multihop_node_policy" + - update_bfd_multihop_node_pol.current.0.bfdMhNodePol.attributes.name == "ansible_bfd_multihop_node_policy" + - update_bfd_multihop_node_pol.current.0.bfdMhNodePol.attributes.descr == "Ansible BFD Multihop Node Policy" + - update_bfd_multihop_node_pol.current.0.bfdMhNodePol.attributes.adminSt == "disabled" + - update_bfd_multihop_node_pol.current.0.bfdMhNodePol.attributes.detectMult == "5" + - update_bfd_multihop_node_pol.current.0.bfdMhNodePol.attributes.minRxIntvl == "500" + - update_bfd_multihop_node_pol.current.0.bfdMhNodePol.attributes.minTxIntvl == "270" + + # Added another BFD Multihop Node policy + - name: Add a new BFD Multihop Node policy - normal mode + cisco.aci.aci_bfd_multihop_node_policy: + <<: *add_bfd_multihop_node_pol + name: ansible_bfd_multihop_node_policy_2 + state: present + register: add_bfd_multihop_node_pol_2 + + - name: Verify BFD Multihop Node Policy creation + assert: + that: + - add_bfd_multihop_node_pol_2 is changed + - add_bfd_multihop_node_pol_2.previous == [] + - add_bfd_multihop_node_pol_2.current.0.bfdMhNodePol.attributes.dn == "uni/tn-ansible_tenant/bfdMhNodePol-ansible_bfd_multihop_node_policy_2" + - add_bfd_multihop_node_pol_2.current.0.bfdMhNodePol.attributes.name == "ansible_bfd_multihop_node_policy_2" + - add_bfd_multihop_node_pol_2.current.0.bfdMhNodePol.attributes.descr == "Ansible BFD Multihop Node Policy" + - add_bfd_multihop_node_pol_2.current.0.bfdMhNodePol.attributes.adminSt == "enabled" + - add_bfd_multihop_node_pol_2.current.0.bfdMhNodePol.attributes.detectMult == "3" + - add_bfd_multihop_node_pol_2.current.0.bfdMhNodePol.attributes.minRxIntvl == "250" + - add_bfd_multihop_node_pol_2.current.0.bfdMhNodePol.attributes.minTxIntvl == "250" + + - name: Query all BFD Multihop Node policies in a specific tenant + cisco.aci.aci_bfd_multihop_node_policy: + <<: *aci_info + tenant: ansible_tenant + state: query + register: query_all_result + + - name: Verify querying all BFD Multihop Node Policies + assert: + that: + - query_all_result is not changed + - query_all_result.current.0.fvTenant.children | length == 2 + - query_all_result.current.0.fvTenant.children[0].bfdMhNodePol.attributes.name == "ansible_bfd_multihop_node_policy_2" + - query_all_result.current.0.fvTenant.children[1].bfdMhNodePol.attributes.name == "ansible_bfd_multihop_node_policy" + + - name: Query 'ansible_bfd_multihop_node_policy' BFD Multihop Node policies in a specific tenant + cisco.aci.aci_bfd_multihop_node_policy: + <<: *aci_info + tenant: ansible_tenant + name: ansible_bfd_multihop_node_policy + state: query + register: query_result + + - name: Verify querying'ansible_bfd_multihop_node_policy BFD' Multihop Node Policy + assert: + that: + - query_result is not changed + - query_result.current.0.bfdMhNodePol.attributes.dn == "uni/tn-ansible_tenant/bfdMhNodePol-ansible_bfd_multihop_node_policy" + - query_result.current.0.bfdMhNodePol.attributes.name == "ansible_bfd_multihop_node_policy" + + - name: Remove a BFD Multihop Node policy - check mode + cisco.aci.aci_bfd_multihop_node_policy: + <<: *aci_info + tenant: ansible_tenant + name: ansible_bfd_multihop_node_policy + state: absent + check_mode: true + register: cm_remove_bfd_multihop_node_pol + + - name: Remove a BFD Multihop Node policy - normal mode + cisco.aci.aci_bfd_multihop_node_policy: + <<: *aci_info + tenant: ansible_tenant + name: ansible_bfd_multihop_node_policy + state: absent + register: nm_remove_bfd_multihop_node_pol + + - name: Remove a BFD Multihop Node policy again + cisco.aci.aci_bfd_multihop_node_policy: + <<: *aci_info + tenant: ansible_tenant + name: ansible_bfd_multihop_node_policy + state: absent + register: remove_bfd_multihop_node_pol_again + + - name: Verify removing BFD Multihop Node Policies + assert: + that: + - nm_remove_bfd_multihop_node_pol is changed + - cm_remove_bfd_multihop_node_pol is changed + - cm_remove_bfd_multihop_node_pol.proposed == {} + - nm_remove_bfd_multihop_node_pol.previous != [] + - remove_bfd_multihop_node_pol_again is not changed + - remove_bfd_multihop_node_pol_again.current == nm_remove_bfd_multihop_node_pol.current == [] + +# Validating out of rage parameters. + +# Added BFD Multihop Node policy with out of the range detection_multiplier + - name: Add a new BFD Multihop Node policy - out of the range detection_multiplier + cisco.aci.aci_bfd_multihop_node_policy: + <<: *add_bfd_multihop_node_pol + name: ansible_bfd_multihop_node_policy_3 + detection_multiplier: 256 + state: present + ignore_errors: true + register: add_bfd_multihop_node_pol_3 + + - name: Verify BFD Multihop Node Policy creation + assert: + that: + - add_bfd_multihop_node_pol_3 is not changed + - add_bfd_multihop_node_pol_3.msg == "The \"detection_multiplier\" must be a value between 1 and 50" + +# Added BFD Multihop Node policy with out of the range min_transmit_interval + - name: Add a new BFD Multihop Node policy - out of the range min_transmit_interval + cisco.aci.aci_bfd_multihop_node_policy: + <<: *add_bfd_multihop_node_pol + name: ansible_bfd_multihop_node_policy_3 + min_transmit_interval: 50 + state: present + ignore_errors: true + register: add_bfd_multihop_node_pol_3 + + - name: Verify BFD Multihop Node Policy creation + assert: + that: + - add_bfd_multihop_node_pol_3 is not changed + - add_bfd_multihop_node_pol_3.msg == "The \"min_transmit_interval\" must be a value between 250 and 999" + +# Added BFD Multihop Node policy with out of the range min_receive_interval + - name: Add a new BFD Multihop Node policy - out of the range min_receive_interval + cisco.aci.aci_bfd_multihop_node_policy: + <<: *add_bfd_multihop_node_pol + name: ansible_bfd_multihop_node_policy_3 + min_receive_interval: 1000 + state: present + ignore_errors: true + register: add_bfd_multihop_node_pol_3 + + - name: Verify BFD Multihop Node Policy creation + assert: + that: + - add_bfd_multihop_node_pol_3 is not changed + - add_bfd_multihop_node_pol_3.msg == "The \"min_receive_interval\" must be a value between 250 and 999" diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_bgp_address_family_context_policy/aliases b/ansible_collections/cisco/aci/tests/integration/targets/aci_bgp_address_family_context_policy/aliases new file mode 100644 index 000000000..209b793f9 --- /dev/null +++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_bgp_address_family_context_policy/aliases @@ -0,0 +1,2 @@ +# No ACI simulator yet, so not enabled +# unsupported diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_bgp_address_family_context_policy/tasks/main.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_bgp_address_family_context_policy/tasks/main.yml new file mode 100644 index 000000000..17164af12 --- /dev/null +++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_bgp_address_family_context_policy/tasks/main.yml @@ -0,0 +1,244 @@ +# Test code for the ACI modules +# Copyright: (c) 2023, Gaspard Micol (@gmicol) + +# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) + +- name: Test that we have an ACI APIC host, ACI username and ACI password + ansible.builtin.fail: + msg: 'Please define the following variables: aci_hostname, aci_username and aci_password.' + when: aci_hostname is not defined or aci_username is not defined or aci_password is not defined + +- name: Set vars + ansible.builtin.set_fact: + aci_info: &aci_info + host: "{{ aci_hostname }}" + username: "{{ aci_username }}" + password: "{{ aci_password }}" + validate_certs: '{{ aci_validate_certs | default(false) }}' + use_ssl: '{{ aci_use_ssl | default(true) }}' + use_proxy: '{{ aci_use_proxy | default(true) }}' + output_level: debug + +# CLEAN ENVIRONMENT +- name: Remove the ansible_tenant + cisco.aci.aci_tenant: &aci_tenant_absent + <<: *aci_info + tenant: ansible_tenant + state: absent + +- name: Verify Cloud and Non-Cloud Sites in use. + ansible.builtin.include_tasks: ../../../../../../integration/targets/aci_cloud_provider/tasks/main.yml + +- name: Execute tasks only for non-cloud sites + when: query_cloud.current == [] # This condition will execute only non-cloud sites + block: # block specifies execution of tasks within, based on conditions + - name: Add a new tenant + cisco.aci.aci_tenant: &aci_tenant_present + <<: *aci_info + tenant: ansible_tenant + description: Ansible tenant + state: present + + - name: Add a BGP address family context policy (check_mode) + cisco.aci.aci_bgp_address_family_context_policy: &aci_bgp_address_family_context_policy_present + <<: *aci_info + tenant: ansible_tenant + address_family_context_policy: ansible_bgp_address_family_context_policy_1 + description: BGP address family context policy 1 for ansible_tenant tenant + host_route_leak: true + ebgp_distance: 40 + ibgp_distance: 210 + local_distance: 215 + ebgp_max_ecmp: 32 + ibgp_max_ecmp: 32 + state: present + check_mode: true + register: cm_add_bgp_address_family_context_policy + + - name: Add a BGP address family context policy (normal_mode) + cisco.aci.aci_bgp_address_family_context_policy: + <<: *aci_bgp_address_family_context_policy_present + register: nm_add_bgp_address_family_context_policy + + - name: Add the first BGP address family context policy again - testing idempotency + cisco.aci.aci_bgp_address_family_context_policy: + <<: *aci_bgp_address_family_context_policy_present + register: nm_add_bgp_address_family_context_policy_idempotency + + - name: Add Local max ECMP to BGP address family context policy - APIC version >= 5.0 + when: version.current.0.topSystem.attributes.version is version('5.0', '>=') + cisco.aci.aci_bgp_address_family_context_policy: &aci_bgp_address_family_context_policy_present_maxLocalEcmp + <<: *aci_bgp_address_family_context_policy_present + local_max_ecmp: 1 + register: nm_add_maxLocalEcmp_bgp_address_family_context_policy + + - name: Add Path Capability to BGP address family context policy - APIC version >= 6.0(2h) + when: version.current.0.topSystem.attributes.version is version('6.0(2h)', '>=') + cisco.aci.aci_bgp_address_family_context_policy: &aci_bgp_address_family_context_policy_present_bgpCtxAddlPathPol + <<: *aci_bgp_address_family_context_policy_present_maxLocalEcmp + bgp_add_path_capability: receive + register: nm_add_path_capability_bgp_address_family_context_policy + + - name: Add a second BGP address family context policy (normal_mode) + cisco.aci.aci_bgp_address_family_context_policy: + <<: *aci_info + tenant: ansible_tenant + address_family_context_policy: ansible_bgp_address_family_context_policy_2 + description: BGP address family context policy 2 for ansible_tenant tenant + state: present + register: nm_add_bgp_address_family_context_policy_2 + + - name: Asserts for BGP address family context policys creation tasks + ansible.builtin.assert: + that: + - cm_add_bgp_address_family_context_policy is changed + - cm_add_bgp_address_family_context_policy.previous == [] + - cm_add_bgp_address_family_context_policy.current == [] + - nm_add_bgp_address_family_context_policy is changed + - nm_add_bgp_address_family_context_policy.current.0.bgpCtxAfPol.attributes.name == "ansible_bgp_address_family_context_policy_1" + - nm_add_bgp_address_family_context_policy.current.0.bgpCtxAfPol.attributes.eDist == "40" + - nm_add_bgp_address_family_context_policy.current.0.bgpCtxAfPol.attributes.iDist == "210" + - nm_add_bgp_address_family_context_policy.current.0.bgpCtxAfPol.attributes.localDist == "215" + - nm_add_bgp_address_family_context_policy.current.0.bgpCtxAfPol.attributes.maxEcmp == "32" + - nm_add_bgp_address_family_context_policy.current.0.bgpCtxAfPol.attributes.maxEcmpIbgp == "32" + - nm_add_bgp_address_family_context_policy.current.0.bgpCtxAfPol.attributes.ctrl == "host-rt-leak" + - nm_add_bgp_address_family_context_policy_idempotency is not changed + - nm_add_bgp_address_family_context_policy_2 is changed + - nm_add_bgp_address_family_context_policy_2.previous == [] + - nm_add_bgp_address_family_context_policy_2.current.0.bgpCtxAfPol.attributes.name == "ansible_bgp_address_family_context_policy_2" + - nm_add_bgp_address_family_context_policy_2.current.0.bgpCtxAfPol.attributes.eDist == "20" + - nm_add_bgp_address_family_context_policy_2.current.0.bgpCtxAfPol.attributes.iDist == "200" + - nm_add_bgp_address_family_context_policy_2.current.0.bgpCtxAfPol.attributes.localDist == "220" + - nm_add_bgp_address_family_context_policy_2.current.0.bgpCtxAfPol.attributes.maxEcmp == "16" + - nm_add_bgp_address_family_context_policy_2.current.0.bgpCtxAfPol.attributes.maxEcmpIbgp == "16" + - nm_add_bgp_address_family_context_policy_2.current.0.bgpCtxAfPol.attributes.ctrl == "" + + - name: Asserts adding Local max ECMP for BGP address family context policys creation tasks - APIC version >= 5.0 + when: version.current.0.topSystem.attributes.version is version('5.0', '>=') + ansible.builtin.assert: + that: + - nm_add_maxLocalEcmp_bgp_address_family_context_policy is changed + - nm_add_maxLocalEcmp_bgp_address_family_context_policy.current.0.bgpCtxAfPol.attributes.maxLocalEcmp == "1" + - nm_add_bgp_address_family_context_policy_2.current.0.bgpCtxAfPol.attributes.maxLocalEcmp == "0" + + - name: Asserts adding path capability for BGP address family context policys creation tasks - APIC version >= 6.0(2h) + when: version.current.0.topSystem.attributes.version is version('6.0(2h)', '>=') + ansible.builtin.assert: + that: + - nm_add_path_capability_bgp_address_family_context_policy is changed + - nm_add_path_capability_bgp_address_family_context_policy.current.0.bgpCtxAfPol.children.0.bgpCtxAddlPathPol.attributes.capability == "receive" + + - name: Query all BGP address family context policies + cisco.aci.aci_bgp_address_family_context_policy: + <<: *aci_info + state: query + register: query_all_bgp_address_family_context_policy + + - name: Query ansible_bgp_address_family_context_policy_1 + cisco.aci.aci_bgp_address_family_context_policy: + <<: *aci_bgp_address_family_context_policy_present + state: query + register: query_ansible_bgp_address_family_context_policy_1 + + - name: Asserts query tasks + ansible.builtin.assert: + that: + - query_all_bgp_address_family_context_policy is not changed + - query_all_bgp_address_family_context_policy.current|length >= 2 + - query_ansible_bgp_address_family_context_policy_1 is not changed + - query_ansible_bgp_address_family_context_policy_1.current.0.bgpCtxAfPol.attributes.name == "ansible_bgp_address_family_context_policy_1" + - query_ansible_bgp_address_family_context_policy_1.current.0.bgpCtxAfPol.attributes.eDist == "40" + - query_ansible_bgp_address_family_context_policy_1.current.0.bgpCtxAfPol.attributes.iDist == "210" + - query_ansible_bgp_address_family_context_policy_1.current.0.bgpCtxAfPol.attributes.localDist == "215" + - query_ansible_bgp_address_family_context_policy_1.current.0.bgpCtxAfPol.attributes.maxEcmp == "32" + - query_ansible_bgp_address_family_context_policy_1.current.0.bgpCtxAfPol.attributes.maxEcmpIbgp == "32" + - query_ansible_bgp_address_family_context_policy_1.current.0.bgpCtxAfPol.attributes.ctrl == "host-rt-leak" + + - name: Query ansible_bgp_address_family_context_policy_1 with updated Local Max ECMP - APIC version >= 5.0 + when: version.current.0.topSystem.attributes.version is version('5.0', '>=') + cisco.aci.aci_bgp_address_family_context_policy: + <<: *aci_bgp_address_family_context_policy_present_maxLocalEcmp + state: query + register: query_ansible_bgp_address_family_context_policy_maxLocalEcmp + + - name: Asserts path capability - APIC version >= 5.0 + when: version.current.0.topSystem.attributes.version is version('5.0', '>=') + ansible.builtin.assert: + that: + - query_ansible_bgp_address_family_context_policy_maxLocalEcmp.current.0.bgpCtxAfPol.attributes.maxLocalEcmp == "1" + + - name: Query ansible_bgp_address_family_context_policy_1 with added path capability - APIC version >= 6.0(2h) + when: version.current.0.topSystem.attributes.version is version('6.0(2h)', '>=') + cisco.aci.aci_bgp_address_family_context_policy: + <<: *aci_bgp_address_family_context_policy_present_bgpCtxAddlPathPol + state: query + register: query_ansible_bgp_address_family_context_policy_bgpCtxAddlPathPol + + - name: Asserts path capability - APIC version >= 6.0(2h) + when: version.current.0.topSystem.attributes.version is version('6.0(2h)', '>=') + ansible.builtin.assert: + that: + - query_ansible_bgp_address_family_context_policy_bgpCtxAddlPathPol.current.0.bgpCtxAfPol.children.0.bgpCtxAddlPathPol.attributes.capability == "receive" + + - name: Remove children from BGP address family context policy (check_mode) - APIC version >= 6.0(2h) + when: version.current.0.topSystem.attributes.version is version('6.0(2h)', '>=') + cisco.aci.aci_bgp_address_family_context_policy: &bgp_address_family_context_policy_delet_children + <<: *aci_bgp_address_family_context_policy_present_bgpCtxAddlPathPol + bgp_add_path_capability: "" + check_mode: true + register: cm_remove_children_bgp_address_family_context_policy + + - name: Remove children from BGP address family context policy (normal_mode) - APIC version >= 6.0(2h) + when: version.current.0.topSystem.attributes.version is version('6.0(2h)', '>=') + cisco.aci.aci_bgp_address_family_context_policy: + <<: *bgp_address_family_context_policy_delet_children + register: nm_remove_children_bgp_address_family_context_policy + + - name: Remove children from BGP address family context policy (testing idempotency) - APIC version >= 6.0(2h) + when: version.current.0.topSystem.attributes.version is version('6.0(2h)', '>=') + cisco.aci.aci_bgp_address_family_context_policy: + <<: *bgp_address_family_context_policy_delet_children + register: nm_remove_children_bgp_address_family_context_policy_idempotency + + - name: Asserts for children removal tasks for the first address family context policy - APIC version >= 6.0(2h) + when: version.current.0.topSystem.attributes.version is version('6.0(2h)', '>=') + ansible.builtin.assert: + that: + - cm_remove_children_bgp_address_family_context_policy is changed + - cm_remove_children_bgp_address_family_context_policy.current == cm_remove_children_bgp_address_family_context_policy.previous + - nm_remove_children_bgp_address_family_context_policy is changed + - nm_remove_children_bgp_address_family_context_policy.current.0.bgpCtxAfPol | length == 1 + - nm_remove_children_bgp_address_family_context_policy_idempotency is not changed + + - name: Remove BGP address family context policy (check_mode) + cisco.aci.aci_bgp_address_family_context_policy: &bgp_address_family_context_policy_absent + <<: *aci_bgp_address_family_context_policy_present + state: absent + check_mode: true + register: cm_remove_bgp_address_family_context_policy + + - name: Remove BGP address family context policy (normal_mode) + cisco.aci.aci_bgp_address_family_context_policy: + <<: *bgp_address_family_context_policy_absent + register: nm_remove_bgp_address_family_context_policy + + - name: Remove BGP address family context policy - testing idempotency + cisco.aci.aci_bgp_address_family_context_policy: + <<: *bgp_address_family_context_policy_absent + register: nm_remove_bgp_address_family_context_policy_idempotency + + - name: Asserts deletion tasks + ansible.builtin.assert: + that: + - cm_remove_bgp_address_family_context_policy is changed + - cm_remove_bgp_address_family_context_policy.proposed == {} + - nm_remove_bgp_address_family_context_policy is changed + - nm_remove_bgp_address_family_context_policy.previous != [] + - nm_remove_bgp_address_family_context_policy.method == "DELETE" + - nm_remove_bgp_address_family_context_policy_idempotency is not changed + - nm_remove_bgp_address_family_context_policy_idempotency.previous == [] + + - name: Remove the ansible_tenant - cleanup before ending tests + cisco.aci.aci_tenant: + <<: *aci_tenant_present + state: absent diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_bgp_best_path_policy/tasks/main.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_bgp_best_path_policy/tasks/main.yml index d0eae2666..3c9176cd5 100644 --- a/ansible_collections/cisco/aci/tests/integration/targets/aci_bgp_best_path_policy/tasks/main.yml +++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_bgp_best_path_policy/tasks/main.yml @@ -4,12 +4,12 @@ # GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) - name: Test that we have an ACI APIC host, ACI username and ACI password - fail: + ansible.builtin.fail: msg: 'Please define the following variables: aci_hostname, aci_username and aci_password.' when: aci_hostname is not defined or aci_username is not defined or aci_password is not defined - name: Set vars - set_fact: + ansible.builtin.set_fact: aci_info: &aci_info host: "{{ aci_hostname }}" username: "{{ aci_username }}" @@ -21,26 +21,26 @@ # CLEAN ENVIRONMENT - name: Remove the ansible_tenant - aci_tenant: &aci_tenant_absent + cisco.aci.aci_tenant: &aci_tenant_absent <<: *aci_info tenant: ansible_tenant state: absent - name: Verify Cloud and Non-Cloud Sites in use. - include_tasks: ../../../../../../integration/targets/aci_cloud_provider/tasks/main.yml + ansible.builtin.include_tasks: ../../../../../../integration/targets/aci_cloud_provider/tasks/main.yml - name: Execute tasks only for non-cloud sites when: query_cloud.current == [] # This condition will execute only non-cloud sites block: # block specifies execution of tasks within, based on conditions - name: Add a new tenant - aci_tenant: &aci_tenant_present + cisco.aci.aci_tenant: &aci_tenant_present <<: *aci_info tenant: ansible_tenant description: Ansible tenant state: present - name: Add a BGP best path policy (check_mode) - aci_bgp_best_path_policy: &aci_bgp_best_path_policy_present + cisco.aci.aci_bgp_best_path_policy: &aci_bgp_best_path_policy_present <<: *aci_info tenant: ansible_tenant bgp_best_path_policy: ansible_bgp_best_path_policy_1 @@ -51,17 +51,17 @@ register: cm_add_bgp_best_path_policy - name: Add a BGP best path policy (normal_mode) - aci_bgp_best_path_policy: + cisco.aci.aci_bgp_best_path_policy: <<: *aci_bgp_best_path_policy_present register: nm_add_bgp_best_path_policy - name: Add the first BGP best path policy again - testing idempotency - aci_bgp_best_path_policy: + cisco.aci.aci_bgp_best_path_policy: <<: *aci_bgp_best_path_policy_present register: nm_add_bgp_best_path_policy_idempotency - name: Add a second BGP best path policy (normal_mode) - aci_bgp_best_path_policy: + cisco.aci.aci_bgp_best_path_policy: <<: *aci_info tenant: ansible_tenant bgp_best_path_policy: ansible_bgp_best_path_policy_2 @@ -71,7 +71,7 @@ register: nm_add_bgp_best_path_policy_2 - name: Asserts for BGP best path policys creation tasks - assert: + ansible.builtin.assert: that: - cm_add_bgp_best_path_policy is changed - cm_add_bgp_best_path_policy.previous == [] @@ -86,19 +86,19 @@ - nm_add_bgp_best_path_policy_2.current.0.bgpBestPathCtrlPol.attributes.ctrl == "" - name: Query all BGP best path policies - aci_bgp_best_path_policy: + cisco.aci.aci_bgp_best_path_policy: <<: *aci_info state: query register: query_all_bgp_best_path_policy - name: Query ansible_bgp_best_path_policy_1 - aci_bgp_best_path_policy: + cisco.aci.aci_bgp_best_path_policy: <<: *aci_bgp_best_path_policy_present state: query register: query_ansible_bgp_best_path_policy_1 - name: Asserts query tasks - assert: + ansible.builtin.assert: that: - query_all_bgp_best_path_policy is not changed - query_all_bgp_best_path_policy.current|length >= 2 @@ -107,24 +107,24 @@ - query_ansible_bgp_best_path_policy_1.current.0.bgpBestPathCtrlPol.attributes.ctrl == "asPathMultipathRelax" - name: Remove BGP best path policy (check_mode) - aci_bgp_best_path_policy: &bgp_best_path_policy_absent + cisco.aci.aci_bgp_best_path_policy: &bgp_best_path_policy_absent <<: *aci_bgp_best_path_policy_present state: absent check_mode: true register: cm_remove_bgp_best_path_policy - name: Remove BGP best path policy (normal_mode) - aci_bgp_best_path_policy: + cisco.aci.aci_bgp_best_path_policy: <<: *bgp_best_path_policy_absent register: nm_remove_bgp_best_path_policy - name: Remove BGP best path policy - testing idempotency - aci_bgp_best_path_policy: + cisco.aci.aci_bgp_best_path_policy: <<: *bgp_best_path_policy_absent register: nm_remove_bgp_best_path_policy_idempotency - name: Asserts deletion tasks - assert: + ansible.builtin.assert: that: - cm_remove_bgp_best_path_policy is changed - cm_remove_bgp_best_path_policy.proposed == {} @@ -135,6 +135,6 @@ - nm_remove_bgp_best_path_policy_idempotency.previous == [] - name: Remove the ansible_tenant - cleanup before ending tests - aci_tenant: + cisco.aci.aci_tenant: <<: *aci_tenant_present state: absent \ No newline at end of file diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_bgp_peer_prefix_policy/aliases b/ansible_collections/cisco/aci/tests/integration/targets/aci_bgp_peer_prefix_policy/aliases new file mode 100644 index 000000000..209b793f9 --- /dev/null +++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_bgp_peer_prefix_policy/aliases @@ -0,0 +1,2 @@ +# No ACI simulator yet, so not enabled +# unsupported diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_bgp_peer_prefix_policy/tasks/main.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_bgp_peer_prefix_policy/tasks/main.yml new file mode 100644 index 000000000..a0a3c2b15 --- /dev/null +++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_bgp_peer_prefix_policy/tasks/main.yml @@ -0,0 +1,151 @@ +# Test code for the ACI modules +# Copyright: (c) 2023, Gaspard Micol (@gmicol) + +# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) + +- name: Test that we have an ACI APIC host, ACI username and ACI password + ansible.builtin.fail: + msg: 'Please define the following variables: aci_hostname, aci_username and aci_password.' + when: aci_hostname is not defined or aci_username is not defined or aci_password is not defined + +- name: Set vars + ansible.builtin.set_fact: + aci_info: &aci_info + host: "{{ aci_hostname }}" + username: "{{ aci_username }}" + password: "{{ aci_password }}" + validate_certs: '{{ aci_validate_certs | default(false) }}' + use_ssl: '{{ aci_use_ssl | default(true) }}' + use_proxy: '{{ aci_use_proxy | default(true) }}' + output_level: debug + +# CLEAN ENVIRONMENT +- name: Remove the ansible_tenant + cisco.aci.aci_tenant: &aci_tenant_absent + <<: *aci_info + tenant: ansible_tenant + state: absent + +- name: Verify Cloud and Non-Cloud Sites in use. + ansible.builtin.include_tasks: ../../../../../../integration/targets/aci_cloud_provider/tasks/main.yml + +- name: Execute tasks only for non-cloud sites + when: query_cloud.current == [] # This condition will execute only non-cloud sites + block: # block specifies execution of tasks within, based on conditions + - name: Add a new tenant + cisco.aci.aci_tenant: &aci_tenant_present + <<: *aci_info + tenant: ansible_tenant + description: Ansible tenant + state: present + + - name: Add a BGP peer prefix policy (check_mode) + cisco.aci.aci_bgp_peer_prefix_policy: &aci_bgp_peer_prefix_policy_present + <<: *aci_info + tenant: ansible_tenant + peer_prefix_policy: ansible_bgp_peer_prefix_policy_1 + description: BGP peer prefix policy 1 for ansible_tenant tenant + action: restart + restart_time: 10 + max_prefix: 10000 + threshold: 80 + state: present + check_mode: true + register: cm_add_bgp_peer_prefix_policy + + - name: Add a BGP peer prefix policy (normal_mode) + cisco.aci.aci_bgp_peer_prefix_policy: + <<: *aci_bgp_peer_prefix_policy_present + register: nm_add_bgp_peer_prefix_policy + + - name: Add the first BGP peer prefix policy again - testing idempotency + cisco.aci.aci_bgp_peer_prefix_policy: + <<: *aci_bgp_peer_prefix_policy_present + register: nm_add_bgp_peer_prefix_policy_idempotency + + - name: Add a second BGP peer prefix policy (normal_mode) + cisco.aci.aci_bgp_peer_prefix_policy: + <<: *aci_info + tenant: ansible_tenant + peer_prefix_policy: ansible_bgp_peer_prefix_policy_2 + description: BGP peer prefix policy 2 for ansible_tenant tenant + state: present + register: nm_add_bgp_peer_prefix_policy_2 + + - name: Asserts for BGP peer prefix policys creation tasks + ansible.builtin.assert: + that: + - cm_add_bgp_peer_prefix_policy is changed + - cm_add_bgp_peer_prefix_policy.previous == [] + - cm_add_bgp_peer_prefix_policy.current == [] + - nm_add_bgp_peer_prefix_policy is changed + - nm_add_bgp_peer_prefix_policy.current.0.bgpPeerPfxPol.attributes.name == "ansible_bgp_peer_prefix_policy_1" + - nm_add_bgp_peer_prefix_policy.current.0.bgpPeerPfxPol.attributes.action == "restart" + - nm_add_bgp_peer_prefix_policy.current.0.bgpPeerPfxPol.attributes.maxPfx == "10000" + - nm_add_bgp_peer_prefix_policy.current.0.bgpPeerPfxPol.attributes.restartTime == "10" + - nm_add_bgp_peer_prefix_policy.current.0.bgpPeerPfxPol.attributes.thresh == "80" + - nm_add_bgp_peer_prefix_policy_idempotency is not changed + - nm_add_bgp_peer_prefix_policy_2 is changed + - nm_add_bgp_peer_prefix_policy_2.previous == [] + - nm_add_bgp_peer_prefix_policy_2.current.0.bgpPeerPfxPol.attributes.name == "ansible_bgp_peer_prefix_policy_2" + - nm_add_bgp_peer_prefix_policy_2.current.0.bgpPeerPfxPol.attributes.action == "reject" + - nm_add_bgp_peer_prefix_policy_2.current.0.bgpPeerPfxPol.attributes.maxPfx == "20000" + - nm_add_bgp_peer_prefix_policy_2.current.0.bgpPeerPfxPol.attributes.restartTime == "infinite" + - nm_add_bgp_peer_prefix_policy_2.current.0.bgpPeerPfxPol.attributes.thresh == "75" + + - name: Query all BGP peer prefix policies + cisco.aci.aci_bgp_peer_prefix_policy: + <<: *aci_info + state: query + register: query_all_bgp_peer_prefix_policy + + - name: Query ansible_bgp_peer_prefix_policy_1 + cisco.aci.aci_bgp_peer_prefix_policy: + <<: *aci_bgp_peer_prefix_policy_present + state: query + register: query_ansible_bgp_peer_prefix_policy_1 + + - name: Asserts query tasks + ansible.builtin.assert: + that: + - query_all_bgp_peer_prefix_policy is not changed + - query_all_bgp_peer_prefix_policy.current|length >= 2 + - query_ansible_bgp_peer_prefix_policy_1 is not changed + - query_ansible_bgp_peer_prefix_policy_1.current.0.bgpPeerPfxPol.attributes.name == "ansible_bgp_peer_prefix_policy_1" + - query_ansible_bgp_peer_prefix_policy_1.current.0.bgpPeerPfxPol.attributes.action == "restart" + - query_ansible_bgp_peer_prefix_policy_1.current.0.bgpPeerPfxPol.attributes.maxPfx == "10000" + - query_ansible_bgp_peer_prefix_policy_1.current.0.bgpPeerPfxPol.attributes.restartTime == "10" + - query_ansible_bgp_peer_prefix_policy_1.current.0.bgpPeerPfxPol.attributes.thresh == "80" + + - name: Remove BGP peer prefix policy (check_mode) + cisco.aci.aci_bgp_peer_prefix_policy: &bgp_peer_prefix_policy_absent + <<: *aci_bgp_peer_prefix_policy_present + state: absent + check_mode: true + register: cm_remove_bgp_peer_prefix_policy + + - name: Remove BGP peer prefix policy (normal_mode) + cisco.aci.aci_bgp_peer_prefix_policy: + <<: *bgp_peer_prefix_policy_absent + register: nm_remove_bgp_peer_prefix_policy + + - name: Remove BGP peer prefix policy - testing idempotency + cisco.aci.aci_bgp_peer_prefix_policy: + <<: *bgp_peer_prefix_policy_absent + register: nm_remove_bgp_peer_prefix_policy_idempotency + + - name: Asserts deletion tasks + ansible.builtin.assert: + that: + - cm_remove_bgp_peer_prefix_policy is changed + - cm_remove_bgp_peer_prefix_policy.proposed == {} + - nm_remove_bgp_peer_prefix_policy is changed + - nm_remove_bgp_peer_prefix_policy.previous != [] + - nm_remove_bgp_peer_prefix_policy.method == "DELETE" + - nm_remove_bgp_peer_prefix_policy_idempotency is not changed + - nm_remove_bgp_peer_prefix_policy_idempotency.previous == [] + + - name: Remove the ansible_tenant - cleanup before ending tests + cisco.aci.aci_tenant: + <<: *aci_tenant_present + state: absent diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_bgp_route_summarization_policy/aliases b/ansible_collections/cisco/aci/tests/integration/targets/aci_bgp_route_summarization_policy/aliases new file mode 100644 index 000000000..209b793f9 --- /dev/null +++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_bgp_route_summarization_policy/aliases @@ -0,0 +1,2 @@ +# No ACI simulator yet, so not enabled +# unsupported diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_bgp_route_summarization_policy/tasks/main.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_bgp_route_summarization_policy/tasks/main.yml new file mode 100644 index 000000000..b43cc8330 --- /dev/null +++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_bgp_route_summarization_policy/tasks/main.yml @@ -0,0 +1,255 @@ +# Test code for the ACI modules +# Copyright: (c) 2023, Gaspard Micol (@gmicol) + +# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) + +- name: Test that we have an ACI APIC host, ACI username and ACI password + ansible.builtin.fail: + msg: 'Please define the following variables: aci_hostname, aci_username and aci_password.' + when: aci_hostname is not defined or aci_username is not defined or aci_password is not defined + +- name: Set vars + ansible.builtin.set_fact: + aci_info: &aci_info + host: "{{ aci_hostname }}" + username: "{{ aci_username }}" + password: "{{ aci_password }}" + validate_certs: '{{ aci_validate_certs | default(false) }}' + use_ssl: '{{ aci_use_ssl | default(true) }}' + use_proxy: '{{ aci_use_proxy | default(true) }}' + output_level: debug + +# CLEAN ENVIRONMENT +- name: Remove the ansible_tenant + cisco.aci.aci_tenant: &aci_tenant_absent + <<: *aci_info + tenant: ansible_tenant + state: absent + +- name: Verify Cloud and Non-Cloud Sites in use. + ansible.builtin.include_tasks: ../../../../../../integration/targets/aci_cloud_provider/tasks/main.yml + +- name: Execute tasks only for non-cloud sites + when: query_cloud.current == [] # This condition will execute only non-cloud sites + block: # block specifies execution of tasks within, based on conditions + - name: Add a new tenant + cisco.aci.aci_tenant: &aci_tenant_present + <<: *aci_info + tenant: ansible_tenant + description: Ansible tenant + state: present + + - name: Add a BGP route summarization policy (check_mode) - APIC version >= 5.0 + when: version.current.0.topSystem.attributes.version is version('5', '>=') + cisco.aci.aci_bgp_route_summarization_policy: &aci_bgp_route_summarization_policy_present + <<: *aci_info + tenant: ansible_tenant + route_summarization_policy: ansible_bgp_route_summarization_policy_1 + description: BGP route summarization policy 1 for ansible_tenant tenant + address_type_af_control: [af-mcast, af-ucast] + control_state: [as-set, summary-only] + state: present + check_mode: true + register: cm_add_bgp_route_summarization_policy + + - name: Add a BGP route summarization policy (normal_mode)- APIC version >= 5.0 + when: version.current.0.topSystem.attributes.version is version('5', '>=') + cisco.aci.aci_bgp_route_summarization_policy: + <<: *aci_bgp_route_summarization_policy_present + register: nm_add_bgp_route_summarization_policy + + - name: Add the first BGP route summarization policy again (testing idempotency) - APIC version >= 5.0 + when: version.current.0.topSystem.attributes.version is version('5', '>=') + cisco.aci.aci_bgp_route_summarization_policy: + <<: *aci_bgp_route_summarization_policy_present + register: nm_add_bgp_route_summarization_policy_idempotency + + - name: Add a second BGP route summarization policy (normal_mode) - APIC version >= 5.0 + when: version.current.0.topSystem.attributes.version is version('5', '>=') + cisco.aci.aci_bgp_route_summarization_policy: + <<: *aci_info + tenant: ansible_tenant + route_summarization_policy: ansible_bgp_route_summarization_policy_2 + description: BGP route summarization policy 2 for ansible_tenant tenant + state: present + register: nm_add_bgp_route_summarization_policy_2 + + - name: Asserts for BGP route summarization policys creation tasks - APIC version >= 5.0 + when: version.current.0.topSystem.attributes.version is version('5', '>=') + ansible.builtin.assert: + that: + - cm_add_bgp_route_summarization_policy is changed + - cm_add_bgp_route_summarization_policy.previous == [] + - cm_add_bgp_route_summarization_policy.current == [] + - nm_add_bgp_route_summarization_policy is changed + - nm_add_bgp_route_summarization_policy.current.0.bgpRtSummPol.attributes.name == "ansible_bgp_route_summarization_policy_1" + - nm_add_bgp_route_summarization_policy.current.0.bgpRtSummPol.attributes.addrTCtrl == "af-mcast,af-ucast" + - nm_add_bgp_route_summarization_policy.current.0.bgpRtSummPol.attributes.ctrl == "as-set,summary-only" + - nm_add_bgp_route_summarization_policy_idempotency is not changed + - nm_add_bgp_route_summarization_policy_2 is changed + - nm_add_bgp_route_summarization_policy_2.previous == [] + - nm_add_bgp_route_summarization_policy_2.current.0.bgpRtSummPol.attributes.name == "ansible_bgp_route_summarization_policy_2" + - nm_add_bgp_route_summarization_policy_2.current.0.bgpRtSummPol.attributes.addrTCtrl == "af-ucast" + - nm_add_bgp_route_summarization_policy_2.current.0.bgpRtSummPol.attributes.ctrl == "" + + - name: Add a BGP route summarization policy (check_mode) - APIC version < 5.0 + when: version.current.0.topSystem.attributes.version is version('5', '<') + cisco.aci.aci_bgp_route_summarization_policy: &aci_bgp_route_summarization_policy_present_prior + <<: *aci_info + tenant: ansible_tenant + route_summarization_policy: ansible_bgp_route_summarization_policy_1 + description: BGP route summarization policy 1 for ansible_tenant tenant + control_state: as-set + state: present + check_mode: true + register: cm_add_bgp_route_summarization_policy_prior + + - name: Add a BGP route summarization policy (normal_mode) - APIC version < 5.0 + when: version.current.0.topSystem.attributes.version is version('5', '<') + cisco.aci.aci_bgp_route_summarization_policy: + <<: *aci_bgp_route_summarization_policy_present_prior + register: nm_add_bgp_route_summarization_policy_prior + + - name: Add the first BGP route summarization policy again (testing idempotency) - APIC version < 5.0 + when: version.current.0.topSystem.attributes.version is version('5', '<') + cisco.aci.aci_bgp_route_summarization_policy: + <<: *aci_bgp_route_summarization_policy_present_prior + register: nm_add_bgp_route_summarization_policy_idempotency_prior + + - name: Add a second BGP route summarization policy (normal_mode) - APIC version < 5.0 + when: version.current.0.topSystem.attributes.version is version('5', '<') + cisco.aci.aci_bgp_route_summarization_policy: + <<: *aci_info + tenant: ansible_tenant + route_summarization_policy: ansible_bgp_route_summarization_policy_2 + description: BGP route summarization policy 2 for ansible_tenant tenant + state: present + register: nm_add_bgp_route_summarization_policy_2_prior + + - name: Asserts for BGP route summarization policys creation tasks - APIC version < 5.0 + when: version.current.0.topSystem.attributes.version is version('5', '<') + ansible.builtin.assert: + that: + - cm_add_bgp_route_summarization_policy_prior is changed + - cm_add_bgp_route_summarization_policy_prior.previous == [] + - cm_add_bgp_route_summarization_policy_prior.current == [] + - nm_add_bgp_route_summarization_policy_prior is changed + - nm_add_bgp_route_summarization_policy_prior.current.0.bgpRtSummPol.attributes.name == "ansible_bgp_route_summarization_policy_1" + - nm_add_bgp_route_summarization_policy_prior.current.0.bgpRtSummPol.attributes.ctrl == "as-set" + - nm_add_bgp_route_summarization_policy_idempotency_prior is not changed + - nm_add_bgp_route_summarization_policy_2_prior is changed + - nm_add_bgp_route_summarization_policy_2_prior.previous == [] + - nm_add_bgp_route_summarization_policy_2_prior.current.0.bgpRtSummPol.attributes.name == "ansible_bgp_route_summarization_policy_2" + - nm_add_bgp_route_summarization_policy_2_prior.current.0.bgpRtSummPol.attributes.ctrl == "" + + - name: Query all BGP route summarization policies + cisco.aci.aci_bgp_route_summarization_policy: + <<: *aci_info + state: query + register: query_all_bgp_route_summarization_policy + + - name: Asserts query all tasks + ansible.builtin.assert: + that: + - query_all_bgp_route_summarization_policy is not changed + - query_all_bgp_route_summarization_policy.current|length >= 2 + + - name: Query ansible_bgp_route_summarization_policy_1 - APIC version >= 5.0 + when: version.current.0.topSystem.attributes.version is version('5', '>=') + cisco.aci.aci_bgp_route_summarization_policy: + <<: *aci_bgp_route_summarization_policy_present + state: query + register: query_ansible_bgp_route_summarization_policy_1 + + - name: Asserts individual query tasks - APIC version >= 5.0 + when: version.current.0.topSystem.attributes.version is version('5', '>=') + ansible.builtin.assert: + that: + - query_ansible_bgp_route_summarization_policy_1 is not changed + - query_ansible_bgp_route_summarization_policy_1.current.0.bgpRtSummPol.attributes.name == "ansible_bgp_route_summarization_policy_1" + - query_ansible_bgp_route_summarization_policy_1.current.0.bgpRtSummPol.attributes.addrTCtrl == "af-mcast,af-ucast" + - query_ansible_bgp_route_summarization_policy_1.current.0.bgpRtSummPol.attributes.ctrl == "as-set,summary-only" + + - name: Query ansible_bgp_route_summarization_policy_1 - APIC version < 5.0 + when: version.current.0.topSystem.attributes.version is version('5', '<') + cisco.aci.aci_bgp_route_summarization_policy: + <<: *aci_bgp_route_summarization_policy_present_prior + state: query + register: query_ansible_bgp_route_summarization_policy_1_prior + + - name: Asserts individual query tasks - APIC version < 5.0 + when: version.current.0.topSystem.attributes.version is version('5', '<') + ansible.builtin.assert: + that: + - query_ansible_bgp_route_summarization_policy_1_prior is not changed + - query_ansible_bgp_route_summarization_policy_1_prior.current.0.bgpRtSummPol.attributes.name == "ansible_bgp_route_summarization_policy_1" + - query_ansible_bgp_route_summarization_policy_1_prior.current.0.bgpRtSummPol.attributes.ctrl == "as-set" + + - name: Remove BGP route summarization policy (check_mode) - APIC version >= 5.0 + when: version.current.0.topSystem.attributes.version is version('5', '>=') + cisco.aci.aci_bgp_route_summarization_policy: &bgp_route_summarization_policy_absent + <<: *aci_bgp_route_summarization_policy_present + state: absent + check_mode: true + register: cm_remove_bgp_route_summarization_policy + + - name: Remove BGP route summarization policy (normal_mode) - APIC version >= 5.0 + when: version.current.0.topSystem.attributes.version is version('5', '>=') + cisco.aci.aci_bgp_route_summarization_policy: + <<: *bgp_route_summarization_policy_absent + register: nm_remove_bgp_route_summarization_policy + + - name: Remove BGP route summarization policy (testing idempotency) - APIC version >= 5.0 + when: version.current.0.topSystem.attributes.version is version('5', '>=') + cisco.aci.aci_bgp_route_summarization_policy: + <<: *bgp_route_summarization_policy_absent + register: nm_remove_bgp_route_summarization_policy_idempotency + + - name: Asserts deletion tasks- APIC version >= 5.0 + when: version.current.0.topSystem.attributes.version is version('5', '>=') + ansible.builtin.assert: + that: + - cm_remove_bgp_route_summarization_policy is changed + - cm_remove_bgp_route_summarization_policy.proposed == {} + - nm_remove_bgp_route_summarization_policy is changed + - nm_remove_bgp_route_summarization_policy.previous != [] + - nm_remove_bgp_route_summarization_policy.method == "DELETE" + - nm_remove_bgp_route_summarization_policy_idempotency is not changed + - nm_remove_bgp_route_summarization_policy_idempotency.previous == [] + + - name: Remove BGP route summarization policy (check_mode) - APIC version < 5.0 + when: version.current.0.topSystem.attributes.version is version('5', '<') + cisco.aci.aci_bgp_route_summarization_policy: &bgp_route_summarization_policy_absent_prior + <<: *aci_bgp_route_summarization_policy_present_prior + state: absent + check_mode: true + register: cm_remove_bgp_route_summarization_policy_prior + + - name: Remove BGP route summarization policy (normal_mode) - APIC version < 5.0 + when: version.current.0.topSystem.attributes.version is version('5', '<') + cisco.aci.aci_bgp_route_summarization_policy: + <<: *bgp_route_summarization_policy_absent_prior + register: nm_remove_bgp_route_summarization_policy_prior + + - name: Remove BGP route summarization policy (testing idempotency) - APIC version < 5.0 + when: version.current.0.topSystem.attributes.version is version('5', '<') + cisco.aci.aci_bgp_route_summarization_policy: + <<: *bgp_route_summarization_policy_absent_prior + register: nm_remove_bgp_route_summarization_policy_idempotency_prior + + - name: Asserts deletion tasks - APIC version < 5.0 + when: version.current.0.topSystem.attributes.version is version('5', '<') + ansible.builtin.assert: + that: + - cm_remove_bgp_route_summarization_policy_prior is changed + - cm_remove_bgp_route_summarization_policy_prior.proposed == {} + - nm_remove_bgp_route_summarization_policy_prior is changed + - nm_remove_bgp_route_summarization_policy_prior.previous != [] + - nm_remove_bgp_route_summarization_policy_prior.method == "DELETE" + - nm_remove_bgp_route_summarization_policy_idempotency_prior is not changed + - nm_remove_bgp_route_summarization_policy_idempotency_prior.previous == [] + + - name: Remove the ansible_tenant - cleanup before ending tests + cisco.aci.aci_tenant: + <<: *aci_tenant_present + state: absent diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_bgp_rr_asn/tasks/main.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_bgp_rr_asn/tasks/main.yml index 3b65520bc..cead2ac6c 100644 --- a/ansible_collections/cisco/aci/tests/integration/targets/aci_bgp_rr_asn/tasks/main.yml +++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_bgp_rr_asn/tasks/main.yml @@ -4,13 +4,13 @@ # GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) - name: Test that we have an ACI APIC host, ACI username and ACI password - fail: + ansible.builtin.fail: msg: 'Please define the following variables: aci_hostname, aci_username and aci_password.' when: aci_hostname is not defined or aci_username is not defined or aci_password is not defined # GET Credentials from the inventory - name: Set vars - set_fact: + ansible.builtin.set_fact: aci_info: &aci_info host: "{{ aci_hostname }}" username: "{{ aci_username }}" @@ -35,7 +35,7 @@ register: add_bgp_rr_asn - name: Verify that BGP route reflector ASN has been created with correct attributes - assert: + ansible.builtin.assert: that: - add_bgp_rr_asn is changed - add_bgp_rr_asn.current.0.bgpAsP.attributes.annotation == 'orchestrator:ansible' @@ -51,7 +51,7 @@ register: add_bgp_rr_asn_again - name: Verify that BGP route reflector ASN idempotence - assert: + ansible.builtin.assert: that: - add_bgp_rr_asn_again is not changed - add_bgp_rr_asn_again.current.0.bgpAsP.attributes.dn == "uni/fabric/bgpInstP-default/as" @@ -66,7 +66,7 @@ register: update_bgp_rr_asn - name: Verify that BGP route reflector ASN has been updated with correct attributes - assert: + ansible.builtin.assert: that: - update_bgp_rr_asn is changed - update_bgp_rr_asn.current.0.bgpAsP.attributes.dn == "uni/fabric/bgpInstP-default/as" @@ -80,7 +80,7 @@ register: query_bgp_rr_asn - name: Verify BGP route reflector ASN - assert: + ansible.builtin.assert: that: - query_bgp_rr_asn is not changed - query_bgp_rr_asn.current.0.bgpAsP.attributes.dn == "uni/fabric/bgpInstP-default/as" diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_bgp_rr_node/tasks/main.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_bgp_rr_node/tasks/main.yml index d1ec77a27..609574cf6 100644 --- a/ansible_collections/cisco/aci/tests/integration/targets/aci_bgp_rr_node/tasks/main.yml +++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_bgp_rr_node/tasks/main.yml @@ -4,13 +4,13 @@ # GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) - name: Test that we have an ACI APIC host, ACI username and ACI password - fail: + ansible.builtin.fail: msg: 'Please define the following variables: aci_hostname, aci_username and aci_password.' when: aci_hostname is not defined or aci_username is not defined or aci_password is not defined # GET Credentials from the inventory - name: Set vars - set_fact: + ansible.builtin.set_fact: aci_info: &aci_info host: "{{ aci_hostname }}" username: "{{ aci_username }}" @@ -38,7 +38,7 @@ register: add_bgp_rr_node - name: Verify that BGP route reflector node has been created with correct attributes - assert: + ansible.builtin.assert: that: - add_bgp_rr_node is changed - add_bgp_rr_node.current.0.bgpRRNodePEp.attributes.annotation == 'orchestrator:ansible' @@ -58,7 +58,7 @@ register: add_bgp_rr_node_again - name: Verify that BGP route reflector node has been created with correct attributes - assert: + ansible.builtin.assert: that: - add_bgp_rr_node_again is not changed - add_bgp_rr_node_again.current.0.bgpRRNodePEp.attributes.dn == "uni/fabric/bgpInstP-default/rr/node-101" @@ -77,7 +77,7 @@ register: update_bgp_rr_node - name: Verify that BGP route reflector node has been updated with correct attributes - assert: + ansible.builtin.assert: that: - update_bgp_rr_node is changed - update_bgp_rr_node.current.0.bgpRRNodePEp.attributes.dn == "uni/fabric/bgpInstP-default/rr/node-101" @@ -94,7 +94,7 @@ register: query_bgp_rr_node - name: Verify that BGP route reflector node attributes - assert: + ansible.builtin.assert: that: - query_bgp_rr_node is not changed - query_bgp_rr_node.current.0.bgpRRNodePEp.attributes.dn == "uni/fabric/bgpInstP-default/rr/node-101" @@ -109,7 +109,7 @@ register: query_bgp_rr_node_all - name: Verify query_bgp_rr_node_all - assert: + ansible.builtin.assert: that: - query_bgp_rr_node_all is not changed @@ -122,7 +122,7 @@ register: remove_bgp_rr_node - name: Verify BGP route reflector node removal - assert: + ansible.builtin.assert: that: - remove_bgp_rr_node is changed - remove_bgp_rr_node.current == [] diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_bgp_timers_policy/tasks/main.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_bgp_timers_policy/tasks/main.yml index 0c7cdd77d..41a099dab 100644 --- a/ansible_collections/cisco/aci/tests/integration/targets/aci_bgp_timers_policy/tasks/main.yml +++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_bgp_timers_policy/tasks/main.yml @@ -4,12 +4,12 @@ # GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) - name: Test that we have an ACI APIC host, ACI username and ACI password - fail: + ansible.builtin.fail: msg: 'Please define the following variables: aci_hostname, aci_username and aci_password.' when: aci_hostname is not defined or aci_username is not defined or aci_password is not defined - name: Set vars - set_fact: + ansible.builtin.set_fact: aci_info: &aci_info host: "{{ aci_hostname }}" username: "{{ aci_username }}" @@ -21,26 +21,26 @@ # CLEAN ENVIRONMENT - name: Remove the ansible_tenant - aci_tenant: &aci_tenant_absent + cisco.aci.aci_tenant: &aci_tenant_absent <<: *aci_info tenant: ansible_tenant state: absent - name: Verify Cloud and Non-Cloud Sites in use. - include_tasks: ../../../../../../integration/targets/aci_cloud_provider/tasks/main.yml + ansible.builtin.include_tasks: ../../../../../../integration/targets/aci_cloud_provider/tasks/main.yml - name: Execute tasks only for non-cloud sites when: query_cloud.current == [] # This condition will execute only non-cloud sites block: # block specifies execution of tasks within, based on conditions - name: Add a new tenant - aci_tenant: &aci_tenant_present + cisco.aci.aci_tenant: &aci_tenant_present <<: *aci_info tenant: ansible_tenant description: Ansible tenant state: present - name: Add a BGP timers policy (check_mode) - aci_bgp_timers_policy: &aci_bgp_timers_policy_present + cisco.aci.aci_bgp_timers_policy: &aci_bgp_timers_policy_present <<: *aci_info tenant: ansible_tenant bgp_timers_policy: ansible_bgp_timers_policy_1 @@ -55,17 +55,17 @@ register: cm_add_bgp_timers_policy - name: Add a BGP timers policy (normal_mode) - aci_bgp_timers_policy: + cisco.aci.aci_bgp_timers_policy: <<: *aci_bgp_timers_policy_present register: nm_add_bgp_timers_policy - name: Add the first BGP timers policy again - testing idempotency - aci_bgp_timers_policy: + cisco.aci.aci_bgp_timers_policy: <<: *aci_bgp_timers_policy_present register: nm_add_bgp_timers_policy_idempotency - name: Add a second BGP timers policy (normal_mode) - aci_bgp_timers_policy: + cisco.aci.aci_bgp_timers_policy: <<: *aci_info tenant: ansible_tenant bgp_timers_policy: ansible_bgp_timers_policy_2 @@ -74,7 +74,7 @@ register: nm_add_bgp_timers_policy_2 - name: Asserts for BGP timers policys creation tasks - assert: + ansible.builtin.assert: that: - cm_add_bgp_timers_policy is changed - cm_add_bgp_timers_policy.previous == [] @@ -97,19 +97,19 @@ - nm_add_bgp_timers_policy_2.current.0.bgpCtxPol.attributes.staleIntvl == "default" - name: Query all BGP timers policies - aci_bgp_timers_policy: + cisco.aci.aci_bgp_timers_policy: <<: *aci_info state: query register: query_all_bgp_timers_policy - name: Query ansible_bgp_timers_policy_1 - aci_bgp_timers_policy: + cisco.aci.aci_bgp_timers_policy: <<: *aci_bgp_timers_policy_present state: query register: query_ansible_bgp_timers_policy_1 - name: Asserts query tasks - assert: + ansible.builtin.assert: that: - query_all_bgp_timers_policy is not changed - query_all_bgp_timers_policy.current|length >= 2 @@ -122,24 +122,24 @@ - query_ansible_bgp_timers_policy_1.current.0.bgpCtxPol.attributes.staleIntvl == "600" - name: Remove BGP timers policy (check_mode) - aci_bgp_timers_policy: &bgp_timers_policy_absent + cisco.aci.aci_bgp_timers_policy: &bgp_timers_policy_absent <<: *aci_bgp_timers_policy_present state: absent check_mode: true register: cm_remove_bgp_timers_policy - name: Remove BGP timers policy (normal_mode) - aci_bgp_timers_policy: + cisco.aci.aci_bgp_timers_policy: <<: *bgp_timers_policy_absent register: nm_remove_bgp_timers_policy - name: Remove BGP timers policy - testing idempotency - aci_bgp_timers_policy: + cisco.aci.aci_bgp_timers_policy: <<: *bgp_timers_policy_absent register: nm_remove_bgp_timers_policy_idempotency - name: Asserts deletion tasks - assert: + ansible.builtin.assert: that: - cm_remove_bgp_timers_policy is changed - cm_remove_bgp_timers_policy.proposed == {} @@ -150,6 +150,6 @@ - nm_remove_bgp_timers_policy_idempotency.previous == [] - name: Remove the ansible_tenant - cleanup before ending tests - aci_tenant: + cisco.aci.aci_tenant: <<: *aci_tenant_present state: absent diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_bulk_static_binding_to_epg/tasks/main.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_bulk_static_binding_to_epg/tasks/main.yml index 909cf933c..700c2975c 100644 --- a/ansible_collections/cisco/aci/tests/integration/targets/aci_bulk_static_binding_to_epg/tasks/main.yml +++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_bulk_static_binding_to_epg/tasks/main.yml @@ -4,12 +4,12 @@ # GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) - name: Test that we have an ACI APIC host, ACI username and ACI password - fail: + ansible.builtin.fail: msg: 'Please define the following variables: aci_hostname, aci_username and aci_password.' when: aci_hostname is not defined or aci_username is not defined or aci_password is not defined - name: Set vars - set_fact: + ansible.builtin.set_fact: aci_info: &aci_info host: "{{ aci_hostname }}" username: "{{ aci_username }}" @@ -20,7 +20,7 @@ output_level: debug - name: Verify Cloud and Non-Cloud Sites in use. - include_tasks: ../../../../../../integration/targets/aci_cloud_provider/tasks/main.yml + ansible.builtin.include_tasks: ../../../../../../integration/targets/aci_cloud_provider/tasks/main.yml - name: Execute tasks only for non-cloud sites when: query_cloud.current == [] # This condition will execute only non-cloud sites @@ -70,7 +70,7 @@ register: cm_interfaces_present - name: Assertions check for add list of interfaces with check mode - assert: + ansible.builtin.assert: that: - cm_interfaces_present is changed - cm_interfaces_present.current.0.fvAEPg.attributes.name == "anstest" @@ -83,7 +83,7 @@ register: nm_interfaces_present - name: Assertions check for add list of interfaces with normal mode - assert: + ansible.builtin.assert: that: - nm_interfaces_present is changed - nm_interfaces_present.current.0.fvAEPg.attributes.name == "anstest" @@ -97,7 +97,7 @@ register: idempotency_interfaces_present - name: Idempotency assertions check for add list of interfaces with normal mode - assert: + ansible.builtin.assert: that: - idempotency_interfaces_present is not changed - idempotency_interfaces_present.current.0.fvAEPg.attributes.name == "anstest" @@ -112,7 +112,7 @@ register: cm_update_interfaces_present - name: Assertions check for update list of interfaces - description with normal mode - assert: + ansible.builtin.assert: that: - cm_update_interfaces_present is changed - cm_update_interfaces_present.current.0.fvAEPg.attributes.name == "anstest" @@ -127,7 +127,7 @@ register: nm_update_interfaces_present - name: Assertions check for update list of interfaces - description with normal mode - assert: + ansible.builtin.assert: that: - nm_update_interfaces_present is changed - nm_update_interfaces_present.current.0.fvAEPg.attributes.name == "anstest" @@ -142,7 +142,7 @@ register: idempotency_nm_update_interfaces_present - name: Idempotency assertions check for update list of interfaces - description with normal mode - assert: + ansible.builtin.assert: that: - idempotency_nm_update_interfaces_present is not changed - idempotency_nm_update_interfaces_present.current.0.fvAEPg.attributes.name == "anstest" @@ -177,7 +177,7 @@ register: cm_path_update_interfaces_present - name: Assertions check for update list of interfaces description using path level attributes with check mode - assert: + ansible.builtin.assert: that: - cm_path_update_interfaces_present is changed - cm_path_update_interfaces_present.current.0.fvAEPg.attributes.name == "anstest" @@ -193,7 +193,7 @@ register: nm_path_update_interfaces_present - name: Assertions check for update list of interfaces description using path level attributes with normal mode - assert: + ansible.builtin.assert: that: - nm_path_update_interfaces_present is changed - nm_path_update_interfaces_present.current.0.fvAEPg.attributes.name == "anstest" @@ -208,7 +208,7 @@ register: idempotency_path_update_interfaces_present - name: Idempotency assertions check for update list of interfaces description using path level attributes with normal mode - assert: + ansible.builtin.assert: that: - idempotency_path_update_interfaces_present is not changed - idempotency_path_update_interfaces_present.current.0.fvAEPg.attributes.name == "anstest" @@ -226,7 +226,7 @@ register: query_result_of_anstest_epg - name: Assertions check for query all interfaces of an EPG - assert: + ansible.builtin.assert: that: - query_result_of_anstest_epg is not changed - query_result_of_anstest_epg.current.0.fvAEPg.children | length == 3 @@ -241,7 +241,7 @@ register: query_all_interfaces - name: Assertions check for query all interfaces # Check covers only EPG level - assert: + ansible.builtin.assert: that: - query_all_interfaces is not changed - query_all_interfaces.current | length >= 1 @@ -254,7 +254,7 @@ register: cm_interfaces_absent - name: Assertions check for remove list of interfaces with check mode - assert: + ansible.builtin.assert: that: - cm_interfaces_absent is changed - cm_interfaces_absent.current.0.fvAEPg.children | length == 3 @@ -269,7 +269,7 @@ register: nm_interfaces_absent - name: Assertions check for remove list of interfaces with normal mode - assert: + ansible.builtin.assert: that: - nm_interfaces_absent is changed - "'children' not in nm_interfaces_absent.current.0.fvAEPg" @@ -285,7 +285,7 @@ register: idempotency_interfaces_absent - name: Idempotency assertions check for remove list of interfaces with normal mode - assert: + ansible.builtin.assert: that: - idempotency_interfaces_absent is changed - "'children' not in idempotency_interfaces_absent.current.0.fvAEPg" @@ -309,7 +309,7 @@ register: fex_port_channel_present - name: Assertions check for add fex_port_channel interfaces to anstest epg - assert: + ansible.builtin.assert: that: - fex_port_channel_present is changed - fex_port_channel_present.current.0.fvAEPg.children | length == 1 @@ -325,7 +325,7 @@ register: fex_port_channel_absent - name: Assertions check for remove fex_port_channel interfaces from anstest epg - assert: + ansible.builtin.assert: that: - fex_port_channel_absent is changed - fex_port_channel_absent.previous.0.fvAEPg.children | length == 1 @@ -354,7 +354,7 @@ register: fex_vpc_present - name: Assertions check for add fex_vpc interfaces to anstest epg - assert: + ansible.builtin.assert: that: - fex_vpc_present is changed - fex_vpc_present.current.0.fvAEPg.children | length == 1 @@ -370,7 +370,7 @@ register: fex_vpc_absent - name: Assertions check for remove fex_vpc interfaces from anstest epg - assert: + ansible.builtin.assert: that: - fex_vpc_absent is changed - fex_vpc_absent.previous.0.fvAEPg.children | length == 1 @@ -398,7 +398,7 @@ register: vpc_present - name: Assertions check for add vpc interfaces to anstest epg - assert: + ansible.builtin.assert: that: - vpc_present is changed - vpc_present.current.0.fvAEPg.children | length == 1 @@ -414,7 +414,7 @@ register: vpc_absent - name: Assertions check for remove vpc interfaces from anstest epg - assert: + ansible.builtin.assert: that: - vpc_absent is changed - vpc_absent.previous.0.fvAEPg.children | length == 1 @@ -433,7 +433,7 @@ register: query_result - name: Assertions check for query all interfaces before start module and path level check - assert: + ansible.builtin.assert: that: - query_result is not changed - "'children' not in query_result.current.0.fvAEPg" @@ -456,7 +456,7 @@ register: module_level_check - name: Assertions check for add an interface with module level attributes - assert: + ansible.builtin.assert: that: - module_level_check is changed - module_level_check.current.0.fvAEPg.children | length == 1 @@ -474,7 +474,7 @@ register: module_level_check_absent - name: Assertions check for remove an interface with module level attributes - assert: + ansible.builtin.assert: that: - module_level_check_absent is changed - "'children' not in module_level_check_absent.current.0.fvAEPg" @@ -501,7 +501,7 @@ register: path_level_check - name: Assertions check for add an interface with path level attributes - assert: + ansible.builtin.assert: that: - path_level_check is changed - path_level_check.current.0.fvAEPg.children | length == 1 @@ -515,7 +515,7 @@ register: path_level_check_absent - name: Assertions check for remove an interface with path level attributes - assert: + ansible.builtin.assert: that: - path_level_check_absent is changed - "'children' not in path_level_check_absent.current.0.fvAEPg" @@ -542,7 +542,7 @@ register: path_and_module_encap_id_present - name: Assertions check for add an interface encap_id with path and module level attributes - assert: + ansible.builtin.assert: that: - path_and_module_encap_id_present is changed - path_and_module_encap_id_present.current.0.fvAEPg.children | length == 1 @@ -556,7 +556,7 @@ register: path_and_module_encap_id_absent - name: Assertions check for remove an interface encap_id with path and module level attributes - assert: + ansible.builtin.assert: that: - path_and_module_encap_id_absent is changed - "'children' not in path_and_module_encap_id_absent.current.0.fvAEPg" @@ -751,7 +751,7 @@ register: switch_port_primary_encap_id_not_unknown - name: Negative assertions to check error messages - assert: + ansible.builtin.assert: that: - switch_port_no_leafs.msg == "missing required arguments{{':'}} leafs found in interface_configs" - fex_vpc_no_extpaths.msg == "extpaths is required when interface_type is{{':'}} fex_vpc" diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_cloud_ap/tasks/main.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_cloud_ap/tasks/main.yml index 08a62f8cc..eb1e51704 100644 --- a/ansible_collections/cisco/aci/tests/integration/targets/aci_cloud_ap/tasks/main.yml +++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_cloud_ap/tasks/main.yml @@ -4,7 +4,7 @@ # GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) - name: Test that we have an ACI APIC host, ACI username and ACI password - fail: + ansible.builtin.fail: msg: 'Please define the following variables: aci_hostname, aci_username and aci_password.' when: aci_hostname is not defined or aci_username is not defined or aci_password is not defined @@ -22,7 +22,7 @@ register: tenant_present - name: Verify Cloud and Non-Cloud Sites in use. - include_tasks: ../../../../../../integration/targets/aci_cloud_provider/tasks/main.yml + ansible.builtin.include_tasks: ../../../../../../integration/targets/aci_cloud_provider/tasks/main.yml - name: Execute tasks only for cloud sites when: query_cloud.current | length > 0 # This condition will execute only cloud sites @@ -68,7 +68,7 @@ register: update_cloud_ap - name: verify cloud ap creation - assert: + ansible.builtin.assert: that: - cm_create_cloud_ap is changed - nm_create_cloud_ap is changed @@ -119,7 +119,7 @@ register: query_cloud_ap - name: verify query - assert: + ansible.builtin.assert: that: - query_all_tenant is not changed - query_all_tenant.current.0.fvTenant.children | length >= 2 @@ -148,7 +148,7 @@ register: rm_cloud_ap_again - name: verify deletion - assert: + ansible.builtin.assert: that: - rm_cloud_ap is changed - rm_cloud_ap.previous.0.cloudApp.attributes.name == 'anstest' diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_cloud_aws_provider/tasks/main.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_cloud_aws_provider/tasks/main.yml index 4679bf78d..f5a849d69 100644 --- a/ansible_collections/cisco/aci/tests/integration/targets/aci_cloud_aws_provider/tasks/main.yml +++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_cloud_aws_provider/tasks/main.yml @@ -4,12 +4,12 @@ # GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) - name: Test that we have an ACI APIC host, ACI username and ACI password - fail: + ansible.builtin.fail: msg: 'Please define the following variables: aci_hostname, aci_username and aci_password.' when: aci_hostname is not defined or aci_username is not defined or aci_password is not defined - name: Set vars - set_fact: + ansible.builtin.set_fact: aci_info: &aci_info host: "{{ aci_hostname }}" username: "{{ aci_username }}" @@ -20,7 +20,7 @@ output_level: '{{ aci_output_level | default("info") }}' - name: Verify Cloud and Non-Cloud Sites in use. - include_tasks: ../../../../../../integration/targets/aci_cloud_provider/tasks/main.yml + ansible.builtin.include_tasks: ../../../../../../integration/targets/aci_cloud_provider/tasks/main.yml - name: Execute tasks only for aws cloud site when: @@ -112,7 +112,7 @@ register: aws_query_all - name: Verify all - assert: + ansible.builtin.assert: that: - aws_present is changed - aws_present_again is not changed diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_cloud_bgp_asn/tasks/main.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_cloud_bgp_asn/tasks/main.yml index 8d442bf14..9fc045ed1 100644 --- a/ansible_collections/cisco/aci/tests/integration/targets/aci_cloud_bgp_asn/tasks/main.yml +++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_cloud_bgp_asn/tasks/main.yml @@ -4,7 +4,7 @@ # GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) - name: Test that we have an ACI APIC host, ACI username and ACI password - fail: + ansible.builtin.fail: msg: 'Please define the following variables: aci_hostname, aci_username and aci_password.' when: aci_hostname is not defined or aci_username is not defined or aci_password is not defined @@ -17,7 +17,7 @@ # CLEAN ENVIRONMENT - name: Set vars - set_fact: + ansible.builtin.set_fact: aci_info: &aci_info host: "{{ aci_hostname }}" username: "{{ aci_username }}" @@ -28,31 +28,31 @@ output_level: '{{ aci_output_level | default("info") }}' # - name: Verify Cloud and Non-Cloud Sites in use. -# include_tasks: ../../../../../../integration/targets/aci_cloud_provider/tasks/main.yml +# ansible.builtin.include_tasks: ../../../../../../integration/targets/aci_cloud_provider/tasks/main.yml # - name: Execute tasks only for cloud sites # when: query_cloud.current | length > 0 # This condition will execute only cloud sites # block: # block specifies execution of tasks within, based on conditions # - name: Ensure cloud BGP ASN doesn't exist -# aci_cloud_bgp_asn: +# cisco.aci.aci_cloud_bgp_asn: # <<: *aci_info # state: absent # - name: Create cloud BGP ASN -# aci_cloud_bgp_asn: +# cisco.aci.aci_cloud_bgp_asn: # <<: *aci_info # state: present # register: asn_present # - name: Verify asn_present -# assert: +# ansible.builtin.assert: # that: # - asn_present is changed # - asn_present.current.0.cloudBgpAsP.attributes.asn == '0' # - name: Create cloud BGP ASN -# aci_cloud_bgp_asn: +# cisco.aci.aci_cloud_bgp_asn: # <<: *aci_info # annotation: 'tag_system' # asn: 64605 @@ -63,13 +63,13 @@ # register: asn_present_2 # - name: Verify asn_present_2 -# assert: +# ansible.builtin.assert: # that: # - asn_present_2 is changed # - asn_present_2.current.0.cloudBgpAsP.attributes.asn == '64605' # - name: Create same cloud BGP ASN again -# aci_cloud_bgp_asn: +# cisco.aci.aci_cloud_bgp_asn: # <<: *aci_info # annotation: 'tag_system' # asn: 64605 @@ -80,13 +80,13 @@ # register: asn_present_again # - name: Verify asn_present_again -# assert: +# ansible.builtin.assert: # that: # - asn_present_again is not changed # - asn_present_again.current.0.cloudBgpAsP.attributes.asn == '64605' # - name: Query particular cloud BGP ASN -# aci_cloud_bgp_asn: +# cisco.aci.aci_cloud_bgp_asn: # <<: *aci_info # annotation: 'tag_system' # asn: 64605 @@ -99,25 +99,25 @@ # # Query all will give same result as query # # There can be only one cloud BGP ASN # - name: Query all cloud BGP ASN -# aci_cloud_bgp_asn: +# cisco.aci.aci_cloud_bgp_asn: # <<: *aci_info # state: query # register: asn_query_all # - name: Verify query -# assert: +# ansible.builtin.assert: # that: # - asn_query is not changed # - asn_query_all is not changed # - name: Delete cloud BGP ASN -# aci_cloud_bgp_asn: +# cisco.aci.aci_cloud_bgp_asn: # <<: *aci_info # state: absent # register: asn_absent # - name: Verify absent -# assert: +# ansible.builtin.assert: # that: # - asn_absent is changed # - asn_absent.current == [] \ No newline at end of file diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_cloud_cidr/tasks/main.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_cloud_cidr/tasks/main.yml index ab61eba83..9c00b67f4 100644 --- a/ansible_collections/cisco/aci/tests/integration/targets/aci_cloud_cidr/tasks/main.yml +++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_cloud_cidr/tasks/main.yml @@ -4,13 +4,13 @@ # GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) - name: Test that we have an ACI APIC host, ACI username and ACI password - fail: + ansible.builtin.fail: msg: 'Please define the following variables: aci_hostname, aci_username and aci_password.' when: aci_hostname is not defined or aci_username is not defined or aci_password is not defined # CLEAN ENVIRONMENT - name: Set vars - set_fact: + ansible.builtin.set_fact: aci_info: &aci_info host: "{{ aci_hostname }}" username: "{{ aci_username }}" @@ -21,27 +21,27 @@ output_level: '{{ aci_output_level | default("info") }}' - name: Verify Cloud and Non-Cloud Sites in use. - include_tasks: ../../../../../../integration/targets/aci_cloud_provider/tasks/main.yml + ansible.builtin.include_tasks: ../../../../../../integration/targets/aci_cloud_provider/tasks/main.yml - name: Execute tasks only for cloud sites when: query_cloud.current | length > 0 # This condition will execute only cloud sites block: # block specifies execution of tasks within, based on conditions - name: Ensure tenant doesn't exist - aci_tenant: + cisco.aci.aci_tenant: <<: *aci_info state: absent tenant: ansible_test register: tenant_absent - name: Ensure tenant exists for tests to kick off - aci_tenant: + cisco.aci.aci_tenant: <<: *aci_info state: present tenant: ansible_test register: tenant_present - name: Ensure aci cloud context profile does not exists - aci_cloud_ctx_profile: + cisco.aci.aci_cloud_ctx_profile: <<: *aci_info tenant: ansible_test name: ctx_profile_1 @@ -49,7 +49,7 @@ register: rm_ctx_profile_1 - name: Create aci cloud context profile - aci_cloud_ctx_profile: + cisco.aci.aci_cloud_ctx_profile: <<: *aci_info tenant: ansible_test name: ctx_profile_1 @@ -61,7 +61,7 @@ register: nm_add_aci_ctx_profile - name: Create non_primary CIDR (check_mode) - aci_cloud_cidr: + cisco.aci.aci_cloud_cidr: <<: *aci_info tenant: ansible_test address: 10.0.0.0/16 @@ -71,7 +71,7 @@ register: cm_non_primary_cidr - name: Create non_primary CIDR (normal_mode) - aci_cloud_cidr: + cisco.aci.aci_cloud_cidr: <<: *aci_info tenant: ansible_test address: 10.0.0.0/16 @@ -80,7 +80,7 @@ register: nm_non_primary_cidr - name: Verify cm_non_primary_cidr and nm_non_primary_cidr - assert: + ansible.builtin.assert: that: - cm_non_primary_cidr is changed - nm_non_primary_cidr is changed @@ -95,7 +95,7 @@ - nm_non_primary_cidr.current.0.cloudCidr.attributes.primary == "no" - name: Create non_primary CIDR again - aci_cloud_cidr: + cisco.aci.aci_cloud_cidr: <<: *aci_info tenant: ansible_test address: 10.0.0.0/16 @@ -104,7 +104,7 @@ register: nm_non_primary_cidr_again - name: Verify nm_non_primary_cidr_again - assert: + ansible.builtin.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" @@ -115,7 +115,7 @@ - nm_non_primary_cidr_again.current.0.cloudCidr.attributes.primary == "no" - name: Change primary CIDR to non_primary (check_mode) - aci_cloud_cidr: + cisco.aci.aci_cloud_cidr: <<: *aci_info tenant: ansible_test address: 10.11.0.0/16 @@ -125,7 +125,7 @@ register: cm_change_to_non_primary_cidr - name: Change primary CIDR to non_primary (normal_mode) - aci_cloud_cidr: + cisco.aci.aci_cloud_cidr: <<: *aci_info tenant: ansible_test address: 10.11.0.0/16 @@ -135,14 +135,14 @@ register: nm_change_to_non_primary_cidr - name: Verify cm_primary_cidr and nm_change_to_non_primary_cidr - assert: + ansible.builtin.assert: that: - nm_change_to_non_primary_cidr.msg == "APIC Error 1{{':'}} Invalid Configuration {{':'}} Exactly one Primary CIDR expected for{{':'}} uni/tn-ansible_test/ctxprofile-ctx_profile_1, but found{{':'}} 0" - cm_change_to_non_primary_cidr.proposed.cloudCidr.attributes.primary == "no" - cm_change_to_non_primary_cidr.previous.0.cloudCidr.attributes.primary == cm_change_to_non_primary_cidr.current.0.cloudCidr.attributes.primary == "yes" - name: Remove primary CIDR (check_mode) - aci_cloud_cidr: + cisco.aci.aci_cloud_cidr: <<: *aci_info tenant: ansible_test address: 10.11.0.0/16 @@ -152,7 +152,7 @@ register: cm_remove_primary_cidr - name: Remove primary CIDR (normal_mode) - aci_cloud_cidr: + cisco.aci.aci_cloud_cidr: <<: *aci_info tenant: ansible_test address: 10.11.0.0/16 @@ -162,14 +162,14 @@ register: nm_remove_primary_cidr - name: Verify cm_remove_primary_cidr and nm_remove_primary_cidr - assert: + ansible.builtin.assert: that: - nm_remove_primary_cidr.msg == "APIC Error 1{{':'}} Invalid Configuration {{':'}} Exactly one Primary CIDR expected for{{':'}} uni/tn-ansible_test/ctxprofile-ctx_profile_1, but found{{':'}} 0" - cm_remove_primary_cidr.proposed == {} - cm_remove_primary_cidr.previous.0.cloudCidr.attributes.primary == cm_remove_primary_cidr.current.0.cloudCidr.attributes.primary == "yes" - name: Create second non_primary CIDR - aci_cloud_cidr: + cisco.aci.aci_cloud_cidr: <<: *aci_info tenant: ansible_test address: 10.18.0.0/16 @@ -178,7 +178,7 @@ register: nm_add_second_non_primary_cidr - name: Verify nm_add_second_non_primary_cidr - assert: + ansible.builtin.assert: that: - nm_add_second_non_primary_cidr is changed - nm_add_second_non_primary_cidr.previous == [] @@ -187,7 +187,7 @@ - nm_add_second_non_primary_cidr.current.0.cloudCidr.attributes.dn == "uni/tn-ansible_test/ctxprofile-ctx_profile_1/cidr-[10.18.0.0/16]" - name: Change setting of second non_primary CIDR - aci_cloud_cidr: + cisco.aci.aci_cloud_cidr: <<: *aci_info tenant: ansible_test cidr: 10.18.0.0/16 @@ -198,7 +198,7 @@ register: change_non_primary_cidr - name: Verify change_non_primary_cidr - assert: + ansible.builtin.assert: that: - change_non_primary_cidr is changed - change_non_primary_cidr.current.0.cloudCidr.attributes.addr == "10.18.0.0/16" @@ -207,7 +207,7 @@ - change_non_primary_cidr.current.0.cloudCidr.attributes.dn == "uni/tn-ansible_test/ctxprofile-ctx_profile_1/cidr-[10.18.0.0/16]" - name: Query all CIDRs - aci_cloud_cidr: + cisco.aci.aci_cloud_cidr: <<: *aci_info tenant: ansible_test cloud_context_profile: ctx_profile_1 @@ -215,7 +215,7 @@ register: query_all - name: Verify query_all - assert: + ansible.builtin.assert: that: - query_all is not changed - query_all.current.0.cloudCtxProfile.attributes.name == "ctx_profile_1" @@ -228,7 +228,7 @@ - query_all.current.0.cloudCtxProfile.children.2.cloudCidr.attributes.primary == "yes" - name: Query primary CIDR - aci_cloud_cidr: + cisco.aci.aci_cloud_cidr: <<: *aci_info tenant: ansible_test cloud_context_profile: ctx_profile_1 @@ -237,7 +237,7 @@ register: query_primary - name: Verify query_primary - assert: + ansible.builtin.assert: that: - query_primary is not changed - query_primary.current.0.cloudCidr.attributes.addr == "10.11.0.0/16" @@ -245,7 +245,7 @@ - query_primary.current.0.cloudCidr.attributes.primary == "yes" - name: Query non_primary CIDR - aci_cloud_cidr: + cisco.aci.aci_cloud_cidr: <<: *aci_info tenant: ansible_test cloud_context_profile: ctx_profile_1 @@ -254,7 +254,7 @@ register: query_non_primary - name: Verify query_non_primary - assert: + ansible.builtin.assert: that: - query_non_primary is not changed - query_non_primary.current.0.cloudCidr.attributes.addr == "10.0.0.0/16" @@ -262,7 +262,7 @@ - query_non_primary.current.0.cloudCidr.attributes.primary == "no" - name: Query non_exsisting CIDR - aci_cloud_cidr: + cisco.aci.aci_cloud_cidr: <<: *aci_info tenant: ansible_test cloud_context_profile: ctx_profile_1 @@ -272,12 +272,12 @@ register: query_non_existing - name: Verify query_non_existing - assert: + ansible.builtin.assert: that: - query_non_existing.msg == "APIC Error 104{{':'}} Invalid RN cidr-[non_exsisting]" - name: Remove non_primary CIDR(check_mode) - aci_cloud_cidr: + cisco.aci.aci_cloud_cidr: <<: *aci_info tenant: ansible_test address: 10.0.0.0/16 @@ -287,7 +287,7 @@ register: cm_remove_non_primary_cidr - name: Remove non_primary CIDR(normal_mode) - aci_cloud_cidr: + cisco.aci.aci_cloud_cidr: <<: *aci_info tenant: ansible_test address: 10.0.0.0/16 @@ -296,7 +296,7 @@ register: nm_remove_non_primary_cidr - name: Verify cm_remove_non_primary_cidr and nm_remove_non_primary_cidr - assert: + ansible.builtin.assert: that: - cm_remove_non_primary_cidr is changed - nm_remove_non_primary_cidr is changed diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_cloud_ctx_profile/tasks/main.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_cloud_ctx_profile/tasks/main.yml index 981eadea8..fad2a6452 100644 --- a/ansible_collections/cisco/aci/tests/integration/targets/aci_cloud_ctx_profile/tasks/main.yml +++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_cloud_ctx_profile/tasks/main.yml @@ -4,13 +4,13 @@ # GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) - name: Test that we have an ACI APIC host, ACI username and ACI password - fail: + ansible.builtin.fail: msg: 'Please define the following variables: aci_hostname, aci_username and aci_password.' when: aci_hostname is not defined or aci_username is not defined or aci_password is not defined # CLEAN ENVIRONMENT - name: Set vars - set_fact: + ansible.builtin.set_fact: aci_info: &aci_info host: "{{ aci_hostname }}" username: "{{ aci_username }}" @@ -21,27 +21,27 @@ output_level: '{{ aci_output_level | default("info") }}' - name: Verify Cloud and Non-Cloud Sites in use. - include_tasks: ../../../../../../integration/targets/aci_cloud_provider/tasks/main.yml + ansible.builtin.include_tasks: ../../../../../../integration/targets/aci_cloud_provider/tasks/main.yml - name: Execute tasks only for cloud sites when: query_cloud.current | length > 0 # This condition will execute only cloud sites block: # block specifies execution of tasks within, based on conditions - name: Ensure tenant doesn't exist - aci_tenant: + cisco.aci.aci_tenant: <<: *aci_info state: absent tenant: ansible_test register: tenant_absent - name: Ensure tenant exists for tests to kick off - aci_tenant: + cisco.aci.aci_tenant: <<: *aci_info state: present tenant: ansible_test register: tenant_present - name: Ensure aci cloud context profile does not exists - aci_cloud_ctx_profile: + cisco.aci.aci_cloud_ctx_profile: <<: *aci_info tenant: ansible_test name: ctx_profile_1 @@ -49,12 +49,12 @@ register: rm_ctx_profile_1 - name: Verify rm_ctx_profile_1 - assert: + ansible.builtin.assert: that: - rm_ctx_profile_1.current == [] - name: Ensure aci cloud context profile 2 does not exists - aci_cloud_ctx_profile: + cisco.aci.aci_cloud_ctx_profile: <<: *aci_info tenant: ansible_test name: ctx_profile_2 @@ -62,12 +62,12 @@ register: rm_ctx_profile_2 - name: Verify rm_ctx_profile_2 - assert: + ansible.builtin.assert: that: - rm_ctx_profile_2.current == [] - name: Create aci cloud context profile (check mode) - aci_cloud_ctx_profile: + cisco.aci.aci_cloud_ctx_profile: <<: *aci_info tenant: ansible_test cloud: "{{ cloud_type }}" @@ -80,7 +80,7 @@ register: cm_add_aci_ctx_profile - name: Create aci cloud context profile (normal mode) - aci_cloud_ctx_profile: + cisco.aci.aci_cloud_ctx_profile: <<: *aci_info tenant: ansible_test cloud: "{{ cloud_type }}" @@ -92,7 +92,7 @@ register: nm_add_aci_ctx_profile - name: Verify cm_add_aci_ctx_profile - assert: + ansible.builtin.assert: that: - cm_add_aci_ctx_profile is changed - cm_add_aci_ctx_profile.previous == [] @@ -103,7 +103,7 @@ - cm_add_aci_ctx_profile.proposed.cloudCtxProfile.children[2].cloudCidr.attributes.primary == "yes" - name: Verify nm_add_aci_ctx_profile - assert: + ansible.builtin.assert: that: - nm_add_aci_ctx_profile is changed - nm_add_aci_ctx_profile.previous == [] @@ -115,7 +115,7 @@ - nm_add_aci_ctx_profile.current[0].cloudCtxProfile.children[0].cloudCidr.attributes.primary == "yes" - name: Add aci cloud context profile again (check_mode) - aci_cloud_ctx_profile: + cisco.aci.aci_cloud_ctx_profile: <<: *aci_info tenant: ansible_test cloud: "{{ cloud_type }}" @@ -128,7 +128,7 @@ register: cm_add_aci_ctx_profile_again - name: Verify cm_add_aci_ctx_profile_again - assert: + ansible.builtin.assert: that: - cm_add_aci_ctx_profile_again is not changed - cm_add_aci_ctx_profile_again.previous[0].cloudCtxProfile.attributes.name == "ctx_profile_1" @@ -139,7 +139,7 @@ - name: Add aci cloud context profile again (normal_mode) - aci_cloud_ctx_profile: + cisco.aci.aci_cloud_ctx_profile: <<: *aci_info tenant: ansible_test cloud: "{{ cloud_type }}" @@ -151,7 +151,7 @@ register: nm_add_aci_ctx_profile_again - name: Verify nm_add_aci_ctx_profile_again - assert: + ansible.builtin.assert: that: - nm_add_aci_ctx_profile_again is not changed - nm_add_aci_ctx_profile_again.current[0].cloudCtxProfile.attributes.name == "ctx_profile_1" @@ -161,7 +161,7 @@ - nm_add_aci_ctx_profile_again.current[0].cloudCtxProfile.children[0].cloudCidr.attributes.primary == "yes" - name: Add another aci cloud context profile (check_mode) - aci_cloud_ctx_profile: + cisco.aci.aci_cloud_ctx_profile: <<: *aci_info tenant: ansible_test cloud: "{{ cloud_type }}" @@ -175,7 +175,7 @@ register: cm_add_another_aci_ctx_profile - name: Verify cm_add_another_aci_ctx_profile - assert: + ansible.builtin.assert: that: - cm_add_another_aci_ctx_profile is changed - cm_add_another_aci_ctx_profile.previous == [] @@ -187,7 +187,7 @@ - cm_add_another_aci_ctx_profile.proposed.cloudCtxProfile.attributes.descr == "add ctx_profile_2" - name: Add another aci cloud context profile (normal_mode) - aci_cloud_ctx_profile: + cisco.aci.aci_cloud_ctx_profile: <<: *aci_info tenant: ansible_test cloud: "{{ cloud_type }}" @@ -200,7 +200,7 @@ register: nm_add_another_aci_ctx_profile - name: Verify nm_add_another_aci_ctx_profile - assert: + ansible.builtin.assert: that: - nm_add_another_aci_ctx_profile is changed - nm_add_another_aci_ctx_profile.previous == [] @@ -212,7 +212,7 @@ - nm_add_another_aci_ctx_profile.current[0].cloudCtxProfile.attributes.descr == "add ctx_profile_2" - name: Query aci cloud context profile ctx_profile_1 - aci_cloud_ctx_profile: + cisco.aci.aci_cloud_ctx_profile: <<: *aci_info tenant: ansible_test name: ctx_profile_1 @@ -220,28 +220,28 @@ register: query_aci_cloud_profile_1 - name: Verify query_aci_cloud_profile_1 - assert: + ansible.builtin.assert: that: - query_aci_cloud_profile_1 is not changed - query_aci_cloud_profile_1.current[0].cloudCtxProfile.attributes.name == "ctx_profile_1" - query_aci_cloud_profile_1.current[0].cloudCtxProfile.children | length == 3 - name: Query all aci cloud context profiles - aci_cloud_ctx_profile: + cisco.aci.aci_cloud_ctx_profile: <<: *aci_info tenant: ansible_test state: query register: query_all - name: Verify query_all - assert: + ansible.builtin.assert: that: - query_all is not changed - query_all.current | length == 1 - query_all.current.0.fvTenant.children | length == 2 - name: Remove aci cloud context profile - aci_cloud_ctx_profile: + cisco.aci.aci_cloud_ctx_profile: <<: *aci_info tenant: ansible_test name: ctx_profile_1 @@ -249,7 +249,7 @@ register: rm_ctx_profile - name: Verify rm_ctx_profile - assert: + ansible.builtin.assert: that: - rm_ctx_profile.current == [] - rm_ctx_profile.previous.0.cloudCtxProfile.attributes.name == "ctx_profile_1" diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_cloud_epg/tasks/main.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_cloud_epg/tasks/main.yml index 966b6afc2..b8804bad7 100644 --- a/ansible_collections/cisco/aci/tests/integration/targets/aci_cloud_epg/tasks/main.yml +++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_cloud_epg/tasks/main.yml @@ -4,12 +4,12 @@ # GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) - name: Test that we have an ACI APIC host, ACI username and ACI password - fail: + ansible.builtin.fail: msg: 'Please define the following variables: aci_hostname, aci_username and aci_password.' when: aci_hostname is not defined or aci_username is not defined or aci_password is not defined - name: Set vars - set_fact: + ansible.builtin.set_fact: aci_info: &aci_info host: "{{ aci_hostname }}" username: "{{ aci_username }}" @@ -20,7 +20,7 @@ output_level: '{{ aci_output_level | default("info") }}' - name: Verify Cloud and Non-Cloud Sites in use. - include_tasks: ../../../../../../integration/targets/aci_cloud_provider/tasks/main.yml + ansible.builtin.include_tasks: ../../../../../../integration/targets/aci_cloud_provider/tasks/main.yml - name: Execute tasks only for cloud sites when: query_cloud.current | length > 0 # This condition will execute only cloud sites @@ -89,7 +89,7 @@ register: nm_another_epg_present - name: Verify cloud epg creation - assert: + ansible.builtin.assert: that: - cm_epg_present is changed - nm_epg_present is changed @@ -129,7 +129,7 @@ # register: create_no_vrf - name: Veirfy update_cloud_epg - assert: + ansible.builtin.assert: that: - update_cloud_epg is changed - update_cloud_epg.current.0.cloudEPg.children.0.cloudRsCloudEPgCtx.attributes.tnFvCtxName == 'anstest_2' @@ -152,7 +152,7 @@ register: query_all - name: Verify query - assert: + ansible.builtin.assert: that: - cloud_epg_query is not changed - cloud_epg_query.current.0.cloudEPg.attributes.name == 'anstest' @@ -178,7 +178,7 @@ register: cloud_epg_absent_again - name: Verify deletion - assert: + ansible.builtin.assert: that: - cloud_epg_absent is changed - cloud_epg_absent.current == [] diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_cloud_epg_selector/tasks/main.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_cloud_epg_selector/tasks/main.yml index c1261eae7..194a35fea 100644 --- a/ansible_collections/cisco/aci/tests/integration/targets/aci_cloud_epg_selector/tasks/main.yml +++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_cloud_epg_selector/tasks/main.yml @@ -4,12 +4,12 @@ # GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) - name: Test that we have an ACI APIC host, ACI username and ACI password - fail: + ansible.builtin.fail: msg: 'Please define the following variables: aci_hostname, aci_username and aci_password.' when: aci_hostname is not defined or aci_username is not defined or aci_password is not defined - name: Set vars - set_fact: + ansible.builtin.set_fact: aci_info: &aci_info host: "{{ aci_hostname }}" username: "{{ aci_username }}" @@ -20,7 +20,7 @@ output_level: '{{ aci_output_level | default("info") }}' - name: Verify Cloud and Non-Cloud Sites in use. - include_tasks: ../../../../../../integration/targets/aci_cloud_provider/tasks/main.yml + ansible.builtin.include_tasks: ../../../../../../integration/targets/aci_cloud_provider/tasks/main.yml - name: Execute tasks only for cloud sites when: query_cloud.current | length > 0 # This condition will execute only cloud sites @@ -92,7 +92,7 @@ register: selector_present_again - name: Verify creation of cloud epg selector - assert: + ansible.builtin.assert: that: - cm_selector_present is changed - nm_selector_present is changed @@ -174,7 +174,7 @@ register: equals_without_value - name: Verify creation of other selectors - assert: + ansible.builtin.assert: that: - sec_selector is changed - udpate_selector is changed @@ -204,7 +204,7 @@ register: query_all - name: Verify query - assert: + ansible.builtin.assert: that: - query_selector.current.0.cloudEPSelector.attributes.name == 'ansible_selector' - query_all.current.0.cloudEPg.children | length >= 2 @@ -225,7 +225,7 @@ register: rm_selector_2_again - name: Verify rm_selector_2 - assert: + ansible.builtin.assert: that: - rm_selector_2 is changed - rm_selector_2.current == [] diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_cloud_external_epg/tasks/main.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_cloud_external_epg/tasks/main.yml index b9511e98f..e3676759f 100644 --- a/ansible_collections/cisco/aci/tests/integration/targets/aci_cloud_external_epg/tasks/main.yml +++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_cloud_external_epg/tasks/main.yml @@ -4,12 +4,12 @@ # GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) - name: Test that we have an ACI APIC host, ACI username and ACI password - fail: + ansible.builtin.fail: msg: 'Please define the following variables: aci_hostname, aci_username and aci_password.' when: aci_hostname is not defined or aci_username is not defined or aci_password is not defined - name: Set vars - set_fact: + ansible.builtin.set_fact: aci_info: &aci_info host: "{{ aci_hostname }}" username: "{{ aci_username }}" @@ -20,7 +20,7 @@ output_level: '{{ aci_output_level | default("info") }}' - name: Verify Cloud and Non-Cloud Sites in use. - include_tasks: ../../../../../../integration/targets/aci_cloud_provider/tasks/main.yml + ansible.builtin.include_tasks: ../../../../../../integration/targets/aci_cloud_provider/tasks/main.yml - name: Execute tasks only for cloud sites when: query_cloud.current | length > 0 # This condition will execute only cloud sites @@ -92,7 +92,7 @@ register: nm_epg_present_again - name: Verify cloud external epg creation - assert: + ansible.builtin.assert: that: - cm_epg_present is changed - nm_epg_present is changed @@ -116,7 +116,7 @@ register: nm_another_epg_present - name: Verify another cloud external epg creation - assert: + ansible.builtin.assert: that: - nm_another_epg_present is changed - nm_another_epg_present.previous == [] @@ -135,7 +135,7 @@ register: no_vrf - name: Veirfy update_cloud_ext_epg - assert: + ansible.builtin.assert: that: - update_cloud_ext_epg is changed - update_cloud_ext_epg.current.0.cloudExtEPg.children.0.cloudRsCloudEPgCtx.attributes.tnFvCtxName == 'anstest_2' @@ -158,7 +158,7 @@ register: query_all - name: Verify query - assert: + ansible.builtin.assert: that: - cloud_ext_epg_query is not changed - cloud_ext_epg_query.current.0.cloudExtEPg.attributes.name == 'anstest' @@ -184,7 +184,7 @@ register: cloud_ext_epg_absent_again - name: Verify deletion - assert: + ansible.builtin.assert: that: - cloud_ext_epg_absent is changed - cloud_ext_epg_absent.current == [] diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_cloud_external_epg_selector/tasks/main.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_cloud_external_epg_selector/tasks/main.yml index 21260c054..671638a66 100644 --- a/ansible_collections/cisco/aci/tests/integration/targets/aci_cloud_external_epg_selector/tasks/main.yml +++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_cloud_external_epg_selector/tasks/main.yml @@ -4,12 +4,12 @@ # GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) - name: Test that we have an ACI APIC host, ACI username and ACI password - fail: + ansible.builtin.fail: msg: 'Please define the following variables: aci_hostname, aci_username and aci_password.' when: aci_hostname is not defined or aci_username is not defined or aci_password is not defined - name: Set vars - set_fact: + ansible.builtin.set_fact: aci_info: &aci_info host: "{{ aci_hostname }}" username: "{{ aci_username }}" @@ -20,7 +20,7 @@ output_level: '{{ aci_output_level | default("info") }}' - name: Verify Cloud and Non-Cloud Sites in use. - include_tasks: ../../../../../../integration/targets/aci_cloud_provider/tasks/main.yml + ansible.builtin.include_tasks: ../../../../../../integration/targets/aci_cloud_provider/tasks/main.yml - name: Execute tasks only for cloud sites when: query_cloud.current | length > 0 # This condition will execute only cloud sites @@ -103,7 +103,7 @@ register: nm_epg_present_again - name: Verify cloud external epg creation - assert: + ansible.builtin.assert: that: - cm_epg_present is changed - nm_epg_present is changed @@ -126,7 +126,7 @@ register: nm_another_epg_present - name: Verify another cloud external epg creation - assert: + ansible.builtin.assert: that: - nm_another_epg_present is changed - nm_another_epg_present.previous == [] @@ -153,7 +153,7 @@ register: query_all - name: Verify query - assert: + ansible.builtin.assert: that: - query_all is not changed - query_all.current.0.cloudExtEPg.children | length >= 2 @@ -175,7 +175,7 @@ register: cloud_ext_epg_absent_again - name: Verify deletion - assert: + ansible.builtin.assert: that: - cloud_ext_epg_absent is changed - cloud_ext_epg_absent.current == [] diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_cloud_provider/tasks/main.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_cloud_provider/tasks/main.yml index 9cc4c87b7..6b1547a8a 100644 --- a/ansible_collections/cisco/aci/tests/integration/targets/aci_cloud_provider/tasks/main.yml +++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_cloud_provider/tasks/main.yml @@ -4,13 +4,13 @@ # GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) - name: Test that we have an ACI APIC host, ACI username and ACI password - fail: + ansible.builtin.fail: msg: 'Please define the following variables: aci_hostname, aci_username and aci_password.' when: aci_hostname is not defined or aci_username is not defined or aci_password is not defined # CLEAN ENVIRONMENT - name: Set vars - set_fact: + ansible.builtin.set_fact: aci_info: &aci_info host: "{{ aci_hostname }}" username: "{{ aci_username }}" @@ -21,7 +21,7 @@ output_level: '{{ aci_output_level | default("info") }}' - name: Query system information - aci_system: + cisco.aci.aci_system: <<: *aci_info id: 1 state: query @@ -29,25 +29,25 @@ # QUERY OBJECTS - name: Query cloud provider object - aci_cloud_provider: + cisco.aci.aci_cloud_provider: <<: *aci_info state: query register: query_cloud when: version.current.0.topSystem.attributes.version is version('4.1', '>=') - name: Set vars - set_fact: + ansible.builtin.set_fact: query_cloud: current: [] when: version.current.0.topSystem.attributes.version is version('4.1', '<') - name: Verify query_cloud for all sites - assert: + ansible.builtin.assert: that: - query_cloud is not changed - name: Verify query_cloud for Cloud Sites - assert: + ansible.builtin.assert: that: - query_cloud is not changed - query_cloud.current.0.cloudProvP.attributes.environment == "public-cloud" diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_cloud_region/tasks/main.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_cloud_region/tasks/main.yml index f4c19c3f7..ab2384791 100644 --- a/ansible_collections/cisco/aci/tests/integration/targets/aci_cloud_region/tasks/main.yml +++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_cloud_region/tasks/main.yml @@ -4,13 +4,13 @@ # GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) - name: Test that we have an ACI APIC host, ACI username and ACI password - fail: + ansible.builtin.fail: msg: 'Please define the following variables: aci_hostname, aci_username and aci_password.' when: aci_hostname is not defined or aci_username is not defined or aci_password is not defined # CLEAN ENVIRONMENT - name: Set vars - set_fact: + ansible.builtin.set_fact: aci_info: &aci_info host: "{{ aci_hostname }}" username: "{{ aci_username }}" @@ -21,20 +21,20 @@ output_level: '{{ aci_output_level | default("info") }}' - name: Verify Cloud and Non-Cloud Sites in use. - include_tasks: ../../../../../../integration/targets/aci_cloud_provider/tasks/main.yml + ansible.builtin.include_tasks: ../../../../../../integration/targets/aci_cloud_provider/tasks/main.yml - name: Execute tasks only for cloud sites when: query_cloud.current | length > 0 # This condition will execute only cloud sites block: # block specifies execution of tasks within, based on conditions - name: Query all regions - aci_cloud_region: + cisco.aci.aci_cloud_region: <<: *aci_info cloud: "{{ cloud_type }}" state: query register: query_all - name: Verify query_all - assert: + ansible.builtin.assert: that: - query_all is not changed - query_all.current.0.cloudProvP.attributes.dn == "uni/clouddomp/provp-{{cloud_type}}" @@ -43,7 +43,7 @@ when: query_all.current != [] - name: Query a specific region - aci_cloud_region: + cisco.aci.aci_cloud_region: <<: *aci_info cloud: "{{ cloud_type }}" region: "{{ region_2 }}" @@ -51,7 +51,7 @@ register: query_region - name: Verify query_region - assert: + ansible.builtin.assert: that: - query_region is not changed - query_region.current.0.cloudRegion.attributes.adminSt == "managed" @@ -60,7 +60,7 @@ when: query_region.current != [] - name: Query non_existing region - aci_cloud_region: + cisco.aci.aci_cloud_region: <<: *aci_info cloud: "{{ cloud_type }}" region: non_existing @@ -68,7 +68,7 @@ register: query_non_existing_region - name: Verify query_non_existing_region - assert: + ansible.builtin.assert: that: - query_non_existing_region is not changed - query_non_existing_region.current == [] diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_cloud_subnet/tasks/main.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_cloud_subnet/tasks/main.yml index e438b4144..8e6a9a15a 100644 --- a/ansible_collections/cisco/aci/tests/integration/targets/aci_cloud_subnet/tasks/main.yml +++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_cloud_subnet/tasks/main.yml @@ -1,16 +1,17 @@ # Test code for the ACI modules # Copyright: (c) 2020, Cindy Zhao (@cizhao) +# Copyright: (c) 2024, Samita Bhattacharjee (@samitab) # GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) - name: Test that we have an ACI APIC host, ACI username and ACI password - fail: + ansible.builtin.fail: msg: 'Please define the following variables: aci_hostname, aci_username and aci_password.' when: aci_hostname is not defined or aci_username is not defined or aci_password is not defined -# CLEAN ENVIRONMENT +# SET VARS - name: Set vars - set_fact: + ansible.builtin.set_fact: aci_info: &aci_info host: "{{ aci_hostname }}" username: "{{ aci_username }}" @@ -21,177 +22,193 @@ output_level: '{{ aci_output_level | default("info") }}' - name: Verify Cloud and Non-Cloud Sites in use. - include_tasks: ../../../../../../integration/targets/aci_cloud_provider/tasks/main.yml + ansible.builtin.include_tasks: ../../../../../../integration/targets/aci_cloud_provider/tasks/main.yml - name: Execute tasks only for cloud sites when: query_cloud.current | length > 0 # This condition will execute only cloud sites block: # block specifies execution of tasks within, based on conditions - name: Ensure tenant doesn't exist - aci_tenant: + cisco.aci.aci_tenant: <<: *aci_info state: absent tenant: ansible_test register: tenant_absent - - name: Ensure tenant exists for tests to kick off - aci_tenant: - <<: *aci_info - state: present - tenant: ansible_test - register: tenant_present + # CLEAN ENVIRONMENT - - name: Ensure aci cloud context profile does not exists - aci_cloud_ctx_profile: + - name: Remove aci cloud context profile + cisco.aci.aci_cloud_ctx_profile: <<: *aci_info tenant: ansible_test name: ctx_profile_1 state: absent - register: rm_ctx_profile_1 - - - name: Verify rm_ctx_profile_1 - assert: - that: - - rm_ctx_profile_1.current == [] - - name: Create aci cloud context profile (normal mode) - aci_cloud_ctx_profile: + - name: Remove ansible_test + cisco.aci.aci_tenant: &aci_tenant_absent <<: *aci_info tenant: ansible_test + state: absent + + - name: Create ansible_test + cisco.aci.aci_tenant: &aci_tenant + <<: *aci_tenant_absent + state: present + + - name: Create aci cloud context profile + cisco.aci.aci_cloud_ctx_profile: + <<: *aci_tenant cloud: "{{ cloud_type }}" name: ctx_profile_1 vrf: ctx_profile_vrf_1 region: "{{ region_2 }}" primary_cidr: '10.50.0.0/16' state: present - register: nm_add_aci_ctx_profile + + # CREATION TASKS - name: Create aci cloud subnet (check_mode) - aci_cloud_subnet: - <<: *aci_info - tenant: ansible_test + cisco.aci.aci_cloud_subnet: &aci_cloud_subnet + <<: *aci_tenant cloud_context_profile: ctx_profile_1 cidr: '10.50.0.0/16' availability_zone: "{{ availability_zone | default(omit) }}" + azure_region: "{{ az_region | default(omit) }}" + vnet_gateway: "{{ vnet_gateway | default(omit) }}" address: 10.50.0.1 description: test description check_mode: true register: cm_add_subnet - name: Create aci cloud subnet (normal_mode) - aci_cloud_subnet: - <<: *aci_info - tenant: ansible_test - cloud_context_profile: ctx_profile_1 - cidr: '10.50.0.0/16' - availability_zone: "{{ availability_zone | default(omit) }}" - address: 10.50.0.1 - description: test description + cisco.aci.aci_cloud_subnet: + <<: *aci_cloud_subnet register: nm_add_subnet - - name: Verify cm_add_subnet - assert: + - name: Create aci cloud subnet again (normal_mode) + cisco.aci.aci_cloud_subnet: + <<: *aci_cloud_subnet + register: nm_add_subnet_again + + - name: Create aci cloud subnet with invalid zone/region + cisco.aci.aci_cloud_subnet: + <<: *aci_cloud_subnet + availability_zone: us-west-1a + azure_region: westus2 + ignore_errors: true + register: nm_invalid_subnet_zone + + - name: Verify create tasks + ansible.builtin.assert: that: - cm_add_subnet is changed + - cm_add_subnet.current == [] - cm_add_subnet.previous == [] - cm_add_subnet.proposed.cloudSubnet.attributes.ip == "10.50.0.1" - cm_add_subnet.proposed.cloudSubnet.attributes.descr == "test description" - cm_add_subnet.proposed.cloudSubnet.attributes.dn == "uni/tn-ansible_test/ctxprofile-ctx_profile_1/cidr-[10.50.0.0/16]/subnet-[10.50.0.1]" - - - name: Create aci cloud subnet again (normal_mode) - aci_cloud_subnet: - <<: *aci_info - tenant: ansible_test - cloud_context_profile: ctx_profile_1 - cidr: '10.50.0.0/16' - availability_zone: "{{ availability_zone | default(omit) }}" - address: 10.50.0.1 - description: test description - register: nm_add_subnet_again - - - name: Verify nm_add_subnet_again - assert: - that: + - cm_add_subnet.proposed.cloudSubnet.attributes.annotation == "orchestrator:ansible" + - cm_add_subnet.proposed.cloudSubnet.attributes.scope == "private" + - nm_add_subnet is changed + - nm_add_subnet.current.0.cloudSubnet.attributes.ip == "10.50.0.1" + - nm_add_subnet.current.0.cloudSubnet.attributes.descr == "test description" + - nm_add_subnet.current.0.cloudSubnet.attributes.dn == "uni/tn-ansible_test/ctxprofile-ctx_profile_1/cidr-[10.50.0.0/16]/subnet-[10.50.0.1]" + - nm_add_subnet.current.0.cloudSubnet.attributes.annotation == "orchestrator:ansible" + - nm_add_subnet.current.0.cloudSubnet.attributes.scope == "private" + - nm_add_subnet.previous == [] - nm_add_subnet_again is not changed + - nm_add_subnet_again.current.0.cloudSubnet.attributes.ip == "10.50.0.1" + - nm_add_subnet_again.current.0.cloudSubnet.attributes.descr == "test description" + - nm_add_subnet_again.current.0.cloudSubnet.attributes.dn == "uni/tn-ansible_test/ctxprofile-ctx_profile_1/cidr-[10.50.0.0/16]/subnet-[10.50.0.1]" + - nm_add_subnet_again.current.0.cloudSubnet.attributes.annotation == "orchestrator:ansible" + - nm_add_subnet_again.current.0.cloudSubnet.attributes.scope == "private" + - nm_add_subnet_again.previous.0.cloudSubnet.attributes.ip == "10.50.0.1" + - nm_add_subnet_again.previous.0.cloudSubnet.attributes.descr == "test description" + - nm_add_subnet_again.previous.0.cloudSubnet.attributes.dn == "uni/tn-ansible_test/ctxprofile-ctx_profile_1/cidr-[10.50.0.0/16]/subnet-[10.50.0.1]" + - nm_add_subnet_again.previous.0.cloudSubnet.attributes.annotation == "orchestrator:ansible" + - nm_add_subnet_again.previous.0.cloudSubnet.attributes.scope == "private" + - nm_invalid_subnet_zone.msg == "parameters are mutually exclusive{{":"}} aws_availability_zone|azure_region" - - name: Create another cloud subnet (normal_mode) - aci_cloud_subnet: - <<: *aci_info - tenant: ansible_test - cloud_context_profile: ctx_profile_1 - cidr: '10.50.0.0/16' - availability_zone: "{{ availability_zone | default(omit) }}" - address: 10.50.0.2 - description: another subnet - register: nm_add_another_subnet + - name: Verify create tasks for Azure + ansible.builtin.assert: + that: + - cm_add_subnet.proposed.cloudSubnet.attributes.usage == "gateway" + - cm_add_subnet.proposed.cloudSubnet.children.0.cloudRsZoneAttach.attributes.tDn == "uni/clouddomp/provp-azure/region-westus2/zone-default" + - nm_add_subnet.current.0.cloudSubnet.attributes.usage == "gateway" + - nm_add_subnet.current.0.cloudSubnet.children.0.cloudRsZoneAttach.attributes.tDn == "uni/clouddomp/provp-azure/region-westus2/zone-default" + - nm_add_subnet_again.current.0.cloudSubnet.attributes.usage == "gateway" + - nm_add_subnet_again.current.0.cloudSubnet.children.0.cloudRsZoneAttach.attributes.tDn == "uni/clouddomp/provp-azure/region-westus2/zone-default" + - nm_add_subnet_again.previous.0.cloudSubnet.attributes.usage == "gateway" + - nm_add_subnet_again.previous.0.cloudSubnet.children.0.cloudRsZoneAttach.attributes.tDn == "uni/clouddomp/provp-azure/region-westus2/zone-default" + when: az_region is defined and vnet_gateway is defined - - name: Verify nm_add_another_subnet - assert: + - name: Verify create tasks for AWS + ansible.builtin.assert: that: - - nm_add_another_subnet is changed - - nm_add_another_subnet.previous == [] - - nm_add_another_subnet.current.0.cloudSubnet.attributes.annotation == 'orchestrator:ansible' - - nm_add_another_subnet.current.0.cloudSubnet.attributes.descr == "another subnet" - - nm_add_another_subnet.current.0.cloudSubnet.attributes.dn == "uni/tn-ansible_test/ctxprofile-ctx_profile_1/cidr-[10.50.0.0/16]/subnet-[10.50.0.2]" + - cm_add_subnet.proposed.cloudSubnet.attributes.usage == "user" + - cm_add_subnet.proposed.cloudSubnet.children.0.cloudRsZoneAttach.attributes.tDn == "uni/clouddomp/provp-aws/region-us-west-1/zone-a" + - nm_add_subnet.current.0.cloudSubnet.attributes.usage == "user" + - nm_add_subnet.current.0.cloudSubnet.children.0.cloudRsZoneAttach.attributes.tDn == "uni/clouddomp/provp-aws/region-us-west-1/zone-a" + - nm_add_subnet_again.current.0.cloudSubnet.attributes.usage == "user" + - nm_add_subnet_again.current.0.cloudSubnet.children.0.cloudRsZoneAttach.attributes.tDn == "uni/clouddomp/provp-aws/region-us-west-1/zone-a" + - nm_add_subnet_again.previous.0.cloudSubnet.attributes.usage == "user" + - nm_add_subnet_again.previous.0.cloudSubnet.children.0.cloudRsZoneAttach.attributes.tDn == "uni/clouddomp/provp-aws/region-us-west-1/zone-a" + when: availability_zone is defined - - name: Create cloud subnet 3(normal_mode) - aci_cloud_subnet: - <<: *aci_info - tenant: ansible_test - cloud_context_profile: ctx_profile_1 - cidr: '10.50.0.0/16' - availability_zone: "{{ availability_zone | default(omit) }}" - address: 10.50.0.3 - name: subnet_3 - register: nm_add_subnet_3 + # UPDATE TASKS - - name: Specify subnet as VpnGateway enabled - aci_cloud_subnet: - <<: *aci_info - tenant: ansible_test - cloud_context_profile: ctx_profile_1 - cidr: '10.50.0.0/16' - availability_zone: "{{ availability_zone | default(omit) }}" - address: 10.50.0.1 - # name: subnet_1 - description: change subnet 1 - vnet_gateway: "{{ vnet_gateway | default(omit)}}" - #scope: public - register: nm_change_subnet_1 + - name: Update aci cloud subnet + cisco.aci.aci_cloud_subnet: + <<: *aci_cloud_subnet + description: test description 2 + register: nm_update_subnet - # Enable vpn_gateway router in cloud ctx profile - - name: Enable VpnGateway - aci_cloud_vpn_gateway: - <<: *aci_info - tenant: ansible_test - cloud_context_profile: ctx_profile_1 - state: present + - name: Verify aci cloud subnet update + ansible.builtin.assert: + that: + - nm_update_subnet is changed + - nm_update_subnet.current.0.cloudSubnet.attributes.ip == "10.50.0.1" + - nm_update_subnet.current.0.cloudSubnet.attributes.descr == "test description 2" + - nm_update_subnet.current.0.cloudSubnet.attributes.dn == "uni/tn-ansible_test/ctxprofile-ctx_profile_1/cidr-[10.50.0.0/16]/subnet-[10.50.0.1]" + - nm_update_subnet.current.0.cloudSubnet.attributes.annotation == "orchestrator:ansible" + - nm_update_subnet.current.0.cloudSubnet.attributes.scope == "private" + - nm_update_subnet.previous.0.cloudSubnet.attributes.ip == "10.50.0.1" + - nm_update_subnet.previous.0.cloudSubnet.attributes.descr == "test description" + - nm_update_subnet.previous.0.cloudSubnet.attributes.dn == "uni/tn-ansible_test/ctxprofile-ctx_profile_1/cidr-[10.50.0.0/16]/subnet-[10.50.0.1]" + - nm_update_subnet.previous.0.cloudSubnet.attributes.annotation == "orchestrator:ansible" + - nm_update_subnet.previous.0.cloudSubnet.attributes.scope == "private" - # Try to disable vpn_gateway router again in cloud ctx profile - - name: Disable VpnGateway - aci_cloud_vpn_gateway: - <<: *aci_info - tenant: ansible_test - cloud_context_profile: ctx_profile_1 - state: absent + # QUERY TASKS + + - name: Create extra subnets for query + cisco.aci.aci_cloud_subnet: + <<: *aci_cloud_subnet + cidr: 10.50.0.0/16 + vnet_gateway: false + address: "{{ item }}" + loop: + - 10.50.0.2 + - 10.50.0.3 - name: Query all subnets - aci_cloud_subnet: - <<: *aci_info - tenant: ansible_test + cisco.aci.aci_cloud_subnet: + <<: *aci_tenant cloud_context_profile: ctx_profile_1 cidr: '10.50.0.0/16' state: query register: query_all - name: Verify query_all - assert: + ansible.builtin.assert: that: - query_all is not changed - query_all.current.0.cloudCidr.attributes.addr == "10.50.0.0/16" - query_all.current.0.cloudCidr.children | length == 3 + - query_all.current.0.cloudCidr.children.0.cloudSubnet.attributes.ip == "10.50.0.3" + - query_all.current.0.cloudCidr.children.1.cloudSubnet.attributes.ip == "10.50.0.2" + - query_all.current.0.cloudCidr.children.2.cloudSubnet.attributes.ip == "10.50.0.1" - name: Query a specific subnet - aci_cloud_subnet: + cisco.aci.aci_cloud_subnet: <<: *aci_info tenant: ansible_test cloud_context_profile: ctx_profile_1 @@ -201,61 +218,50 @@ register: query_subnet_1 - name: Verify query_subnet_1 - assert: + ansible.builtin.assert: that: - query_subnet_1 is not changed - query_subnet_1.current.0.cloudSubnet.attributes.ip == "10.50.0.1" - query_subnet_1.current.0.cloudSubnet.attributes.scope == "private" - query_subnet_1.current.0.cloudSubnet.attributes.dn == "uni/tn-ansible_test/ctxprofile-ctx_profile_1/cidr-[10.50.0.0/16]/subnet-[10.50.0.1]" - - name: Remove subnet 3 (check_mode) - aci_cloud_subnet: - <<: *aci_info - tenant: ansible_test - cloud_context_profile: ctx_profile_1 - cidr: '10.50.0.0/16' - address: 10.50.0.3 + # DELETE TASKS + + - name: Remove cloud subnet (check_mode) + cisco.aci.aci_cloud_subnet: + <<: *aci_cloud_subnet state: absent check_mode: true - register: cm_remove_subnet_3 + register: cm_remove_subnet - - name: Verify cm_remove_subnet_3 - assert: - that: - - cm_remove_subnet_3 is changed - - cm_remove_subnet_3.proposed == {} - - cm_remove_subnet_3.previous.0.cloudSubnet.attributes.ip == "10.50.0.3" - - - name: Remove subnet 3 (normal_mode) - aci_cloud_subnet: - <<: *aci_info - tenant: ansible_test - cloud_context_profile: ctx_profile_1 - cidr: '10.50.0.0/16' - address: 10.50.0.3 + - name: Remove cloud subnet (normal_mode) + cisco.aci.aci_cloud_subnet: + <<: *aci_cloud_subnet state: absent - register: nm_remove_subnet_3 - - - name: Verify nm_remove_subnet_3 - assert: - that: - - nm_remove_subnet_3 is changed - - nm_remove_subnet_3.current == [] - - nm_remove_subnet_3.previous.0.cloudSubnet.attributes.ip == "10.50.0.3" + register: nm_remove_subnet - - name: Remove subnet 3 again - aci_cloud_subnet: - <<: *aci_info - tenant: ansible_test - cloud_context_profile: ctx_profile_1 - cidr: '10.50.0.0/16' - address: 10.50.0.3 + - name: Remove cloud subnet again (normal_mode) + cisco.aci.aci_cloud_subnet: + <<: *aci_cloud_subnet state: absent - register: nm_remove_subnet_3_again + register: nm_remove_subnet_again - - name: Verify nm_remove_subnet_3_again - assert: + - name: Verify remove cloud subnet + ansible.builtin.assert: that: - - nm_remove_subnet_3_again is not changed - - nm_remove_subnet_3_again.previous == [] - - nm_remove_subnet_3_again.current == [] + - cm_remove_subnet is changed + - cm_remove_subnet.proposed == {} + - cm_remove_subnet.previous.0.cloudSubnet.attributes.ip == "10.50.0.1" + - cm_remove_subnet.previous.0.cloudSubnet.attributes.dn == "uni/tn-ansible_test/ctxprofile-ctx_profile_1/cidr-[10.50.0.0/16]/subnet-[10.50.0.1]" + - nm_remove_subnet is changed + - nm_remove_subnet.current == [] + - nm_remove_subnet.previous.0.cloudSubnet.attributes.ip == "10.50.0.1" + - nm_remove_subnet.previous.0.cloudSubnet.attributes.dn == "uni/tn-ansible_test/ctxprofile-ctx_profile_1/cidr-[10.50.0.0/16]/subnet-[10.50.0.1]" + - nm_remove_subnet_again is not changed + - nm_remove_subnet_again.previous == [] + - nm_remove_subnet_again.current == [] + + # CLEAN ENVIRONMENT + - name: Remove ansible_test + cisco.aci.aci_tenant: + <<: *aci_tenant_absent \ No newline at end of file diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_cloud_vpn_gateway/tasks/main.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_cloud_vpn_gateway/tasks/main.yml index 834331a03..f1b0683fc 100644 --- a/ansible_collections/cisco/aci/tests/integration/targets/aci_cloud_vpn_gateway/tasks/main.yml +++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_cloud_vpn_gateway/tasks/main.yml @@ -4,13 +4,13 @@ # GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) - name: Test that we have an ACI APIC host, ACI username and ACI password - fail: + ansible.builtin.fail: msg: 'Please define the following variables: aci_hostname, aci_username and aci_password.' when: aci_hostname is not defined or aci_username is not defined or aci_password is not defined # CLEAN ENVIRONMENT - name: Set vars - set_fact: + ansible.builtin.set_fact: aci_info: &aci_info host: "{{ aci_hostname }}" username: "{{ aci_username }}" @@ -21,27 +21,27 @@ output_level: '{{ aci_output_level | default("info") }}' - name: Verify Cloud and Non-Cloud Sites in use. - include_tasks: ../../../../../../integration/targets/aci_cloud_provider/tasks/main.yml + ansible.builtin.include_tasks: ../../../../../../integration/targets/aci_cloud_provider/tasks/main.yml - name: Execute tasks only for cloud sites when: query_cloud.current | length > 0 # This condition will execute only cloud sites block: # block specifies execution of tasks within, based on conditions - name: Ensure tenant doesn't exist - aci_tenant: + cisco.aci.aci_tenant: <<: *aci_info state: absent tenant: ansible_test register: tenant_absent - name: Ensure tenant exists for tests to kick off - aci_tenant: + cisco.aci.aci_tenant: <<: *aci_info state: present tenant: ansible_test register: tenant_present - name: Ensure aci cloud context profile does not exists - aci_cloud_ctx_profile: + cisco.aci.aci_cloud_ctx_profile: <<: *aci_info tenant: ansible_test name: ctx_profile_1 @@ -49,12 +49,12 @@ register: rm_ctx_profile_1 - name: Verify rm_ctx_profile_1 - assert: + ansible.builtin.assert: that: - rm_ctx_profile_1.current == [] - name: Create aci cloud context profile (normal mode) - aci_cloud_ctx_profile: + cisco.aci.aci_cloud_ctx_profile: <<: *aci_info tenant: ansible_test cloud: "{{ cloud_type }}" @@ -66,7 +66,7 @@ register: nm_add_aci_ctx_profile - name: Create aci cloud subnet with VpnGateway enabled (normal_mode) - aci_cloud_subnet: + cisco.aci.aci_cloud_subnet: <<: *aci_info tenant: ansible_test cloud_context_profile: ctx_profile_1 @@ -79,35 +79,35 @@ register: nm_add_subnet - name: Enable VpnGateway - aci_cloud_vpn_gateway: + cisco.aci.aci_cloud_vpn_gateway: <<: *aci_info tenant: ansible_test cloud_context_profile: ctx_profile_1 state: present - name: Disable VpnGateway - aci_cloud_vpn_gateway: + cisco.aci.aci_cloud_vpn_gateway: <<: *aci_info tenant: ansible_test cloud_context_profile: ctx_profile_1 state: absent - name: Enable VpnGateway again - aci_cloud_vpn_gateway: + cisco.aci.aci_cloud_vpn_gateway: <<: *aci_info tenant: ansible_test cloud_context_profile: ctx_profile_1 state: present - name: Query VpnGateway - aci_cloud_vpn_gateway: + cisco.aci.aci_cloud_vpn_gateway: <<: *aci_info tenant: ansible_test cloud_context_profile: ctx_profile_1 register: query_vpn_gateway - name: Verify VpnGateway - assert: + ansible.builtin.assert: that: - query_vpn_gateway is not changed - query_vpn_gateway.current.0.cloudRouterP.children | length == 3 diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_cloud_zone/tasks/main.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_cloud_zone/tasks/main.yml index 85a2ec087..09a1d18db 100644 --- a/ansible_collections/cisco/aci/tests/integration/targets/aci_cloud_zone/tasks/main.yml +++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_cloud_zone/tasks/main.yml @@ -4,13 +4,13 @@ # GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) - name: Test that we have an ACI APIC host, ACI username and ACI password - fail: + ansible.builtin.fail: msg: 'Please define the following variables: aci_hostname, aci_username and aci_password.' when: aci_hostname is not defined or aci_username is not defined or aci_password is not defined # CLEAN ENVIRONMENT - name: Set vars - set_fact: + ansible.builtin.set_fact: aci_info: &aci_info host: "{{ aci_hostname }}" username: "{{ aci_username }}" @@ -21,13 +21,13 @@ output_level: '{{ aci_output_level | default("info") }}' - name: Verify Cloud and Non-Cloud Sites in use. - include_tasks: ../../../../../../integration/targets/aci_cloud_provider/tasks/main.yml + ansible.builtin.include_tasks: ../../../../../../integration/targets/aci_cloud_provider/tasks/main.yml - name: Execute tasks only for cloud sites when: query_cloud.current | length > 0 # This condition will execute only cloud sites block: # block specifies execution of tasks within, based on conditions - name: Query all zones under us-west-1 - aci_cloud_zone: + cisco.aci.aci_cloud_zone: <<: *aci_info cloud: "{{ cloud_type }}" region: "{{ region_2 }}" @@ -35,14 +35,14 @@ register: query_all - name: Verify query_all - assert: + ansible.builtin.assert: that: - query_all is not changed - query_all.current.0.cloudRegion.attributes.name == "{{region_2}}" - query_all.current.0.cloudRegion.children | length >= 1 - name: Query a specific zone under region us-west-1 - aci_cloud_zone: + cisco.aci.aci_cloud_zone: <<: *aci_info cloud: "{{ cloud_type }}" region: "{{ region_2 }}" @@ -51,7 +51,7 @@ register: query_zone_1 - name: Query another specific zone under region us-west-1 - aci_cloud_zone: + cisco.aci.aci_cloud_zone: <<: *aci_info cloud: "{{ cloud_type }}" region: "{{ region_2 }}" @@ -60,7 +60,7 @@ register: query_zone_2 - name: Verify query_zone_1 and query_zone_2 - assert: + ansible.builtin.assert: that: - query_zone_1 is not changed - query_zone_2 is not changed @@ -71,7 +71,7 @@ when: query_zone_1.current != [] and query_zone_2.current != [] - name: Query non_existing zone under region us-west-1 - aci_cloud_zone: + cisco.aci.aci_cloud_zone: <<: *aci_info cloud: "{{ cloud_type }}" region: "{{ region_2 }}" @@ -80,7 +80,7 @@ register: query_non_existing_zone - name: Query zone under non_existing region - aci_cloud_zone: + cisco.aci.aci_cloud_zone: <<: *aci_info cloud: "{{ cloud_type }}" region: non_existing @@ -89,7 +89,7 @@ register: query_non_existing_region - name: Verify query_non_existing_zone - assert: + ansible.builtin.assert: that: - query_non_existing_zone is not changed - query_non_existing_zone.current == [] diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_config_export_policy/tasks/main.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_config_export_policy/tasks/main.yml index bb290aa5f..ad4389e94 100644 --- a/ansible_collections/cisco/aci/tests/integration/targets/aci_config_export_policy/tasks/main.yml +++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_config_export_policy/tasks/main.yml @@ -3,7 +3,7 @@ # SET VARS - name: Set vars - set_fact: + ansible.builtin.set_fact: aci_info: &aci_info host: '{{ aci_hostname }}' username: '{{ aci_username }}' diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_config_rollback/tasks/main.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_config_rollback/tasks/main.yml index 9b43c9cfc..c96a2c1e9 100644 --- a/ansible_collections/cisco/aci/tests/integration/targets/aci_config_rollback/tasks/main.yml +++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_config_rollback/tasks/main.yml @@ -4,7 +4,7 @@ # GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) - name: Test that we have an ACI APIC host, ACI username and ACI password - fail: + ansible.builtin.fail: msg: 'Please define the following variables: aci_hostname, aci_username and aci_password.' when: aci_hostname is not defined or aci_username is not defined or aci_password is not defined @@ -21,7 +21,7 @@ tenant: ansible_test - name: Verify Cloud and Non-Cloud Sites in use. - include_tasks: ../../../../../../integration/targets/aci_cloud_provider/tasks/main.yml + ansible.builtin.include_tasks: ../../../../../../integration/targets/aci_cloud_provider/tasks/main.yml - name: create a snapshot cisco.aci.aci_config_snapshot: &create_snapshot @@ -43,7 +43,7 @@ register: create_snapshot_annotation_check - name: waiting for snapshot to be finished before querying - pause: + ansible.builtin.pause: seconds: 10 - name: get snapshots @@ -142,7 +142,7 @@ register: rollback_rollback - name: pause execution to let rollback take effect - pause: + ansible.builtin.pause: seconds: 15 - name: ensure tenant doesn't exist after rollback @@ -154,7 +154,7 @@ msg: '{{ rollback_preview_json }}' - name: rollback assertions - assert: + ansible.builtin.assert: that: - rollback_preview_xml is not changed - '"ansible_test" in rollback_preview_xml.preview' diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_config_snapshot/tasks/main.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_config_snapshot/tasks/main.yml index c9415a86d..fc4f7d906 100644 --- a/ansible_collections/cisco/aci/tests/integration/targets/aci_config_snapshot/tasks/main.yml +++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_config_snapshot/tasks/main.yml @@ -4,7 +4,7 @@ # GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) - name: Test that we have an ACI APIC host, ACI username and ACI password - fail: + ansible.builtin.fail: msg: 'Please define the following variables: aci_hostname, aci_username and aci_password.' when: aci_hostname is not defined or aci_username is not defined or aci_password is not defined @@ -46,7 +46,7 @@ register: missing_param - name: present assertion tests - assert: + ansible.builtin.assert: that: - create is not failed - create is changed @@ -72,7 +72,7 @@ register: query_export - name: generate snapshot name - set_fact: + ansible.builtin.set_fact: test_snapshot: "{{ query_export.current.0.configSnapshotCont.children.0.configSnapshot.attributes.rn.strip('snapshot-') }}" - name: query with export_policy and snapshot @@ -95,7 +95,7 @@ register: query_all - name: query assertion tests - assert: + ansible.builtin.assert: that: - query_export is not failed - query_export is not changed @@ -134,7 +134,7 @@ register: delete_missing_param - name: absent assertion tests - assert: + ansible.builtin.assert: that: - delete_snapshot is not failed - delete_snapshot is changed @@ -149,7 +149,7 @@ # Create, query and delete snapshot with certificate authentication Ref# 427 - name: Set vars - set_fact: + ansible.builtin.set_fact: aci_info: &aci_info host: "{{ aci_hostname }}" username: "{{ aci_username }}" @@ -178,7 +178,7 @@ register: create_private_key - name: creation assertion tests with private key - assert: + ansible.builtin.assert: that: - create_private_key is not failed - create_private_key is changed @@ -193,11 +193,11 @@ register: query_private_key - name: generate snapshot name using query_private_key - set_fact: + ansible.builtin.set_fact: test_snapshot_private_key: "{{ query_private_key.current.0.configSnapshotCont.children.0.configSnapshot.attributes.rn.strip('snapshot-') }}" - name: query assertion tests with private key - assert: + ansible.builtin.assert: that: - query_private_key is not failed - query_private_key is not changed @@ -213,7 +213,7 @@ register: delete_snapshot_private_key - name: delete assertion tests with the private key - assert: + ansible.builtin.assert: that: - delete_snapshot_private_key is not failed - delete_snapshot_private_key is changed diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_contract/tasks/main.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_contract/tasks/main.yml index 635f2d331..1093c6b8e 100644 --- a/ansible_collections/cisco/aci/tests/integration/targets/aci_contract/tasks/main.yml +++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_contract/tasks/main.yml @@ -4,7 +4,7 @@ # GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) - name: Test that we have an ACI APIC host, ACI username and ACI password - fail: + ansible.builtin.fail: msg: 'Please define the following variables: aci_hostname, aci_username and aci_password.' when: aci_hostname is not defined or aci_username is not defined or aci_password is not defined @@ -57,7 +57,7 @@ register: present_missing_param - name: present assertions - assert: + ansible.builtin.assert: that: - present_check_mode is changed - present_check_mode.previous == [] @@ -99,7 +99,7 @@ register: query_all - name: query assertions - assert: + ansible.builtin.assert: that: - query_contract is not changed - query_contract.current | length == 1 @@ -147,7 +147,7 @@ register: absent_missing_param - name: absent assertions - assert: + ansible.builtin.assert: that: - absent_check_mode is changed - absent_check_mode.previous != [] diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_contract_export/tasks/main.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_contract_export/tasks/main.yml index 5a1139947..8bd55efef 100644 --- a/ansible_collections/cisco/aci/tests/integration/targets/aci_contract_export/tasks/main.yml +++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_contract_export/tasks/main.yml @@ -3,7 +3,7 @@ # SET VARS - name: Set vars - set_fact: + ansible.builtin.set_fact: aci_info: &aci_info host: '{{ aci_hostname }}' username: '{{ aci_username }}' @@ -62,7 +62,7 @@ register: nm_add_intf - name: Verify add_intf - assert: + ansible.builtin.assert: that: - cm_add_intf is changed - nm_add_intf is changed @@ -76,7 +76,7 @@ register: add_intf_again - name: Verify add_intf_again - assert: + ansible.builtin.assert: that: - add_intf_again is not changed @@ -88,7 +88,7 @@ register: update_intf - name: Verify update_intf - assert: + ansible.builtin.assert: that: - update_intf is changed - update_intf.previous != [] @@ -108,7 +108,7 @@ register: query_all_intfs - name: Verify query_all_intfs - assert: + ansible.builtin.assert: that: - query_all_intfs is not changed - query_all_intfs.current|length > 1 @@ -121,7 +121,7 @@ register: query_spec_intf - name: Verify query_spec_intf - assert: + ansible.builtin.assert: that: - query_spec_intf is not changed - query_spec_intf.current|length == 1 @@ -134,7 +134,7 @@ register: remove_intf - name: Verify remove_intf - assert: + ansible.builtin.assert: that: - remove_intf is changed - remove_intf.current == [] diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_contract_subject/tasks/main.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_contract_subject/tasks/main.yml index b7d53844c..5b3600756 100644 --- a/ansible_collections/cisco/aci/tests/integration/targets/aci_contract_subject/tasks/main.yml +++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_contract_subject/tasks/main.yml @@ -4,12 +4,12 @@ # GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) - name: Test that we have an ACI APIC host, ACI username and ACI password - fail: + ansible.builtin.fail: msg: 'Please define the following variables: aci_hostname, aci_username and aci_password.' when: aci_hostname is not defined or aci_username is not defined or aci_password is not defined - name: Set vars - set_fact: + ansible.builtin.set_fact: aci_info: &aci_info host: "{{ aci_hostname }}" username: "{{ aci_username }}" @@ -83,7 +83,7 @@ register: present_missing_param - name: present assertions - assert: + ansible.builtin.assert: that: - subject_present_check_mode is changed - subject_present_check_mode.sent.vzSubj.attributes.descr == 'Ansible Test' @@ -157,7 +157,7 @@ register: query_all - name: query assertions - assert: + ansible.builtin.assert: that: - query_tenant_contract_subject is not changed - query_tenant_contract_subject.current | length == 1 @@ -234,7 +234,7 @@ register: absent_missing_param - name: absent assertions - assert: + ansible.builtin.assert: that: - subject_absent_check_mode is changed - subject_absent_check_mode.previous != [] @@ -289,7 +289,7 @@ register: nm_subject_present_one_way_again - name: subject assertions - assert: + ansible.builtin.assert: that: - cm_subject_present_both_default is changed - nm_subject_present_both_default is changed @@ -315,7 +315,7 @@ ignore_errors: true - name: subject assertions - assert: + ansible.builtin.assert: that: - nm_subject_reverse_to_one_way is not changed - nm_subject_reverse_to_one_way.msg == "Direction is not allowed, valid option is both." @@ -365,7 +365,7 @@ register: nm_subject_one_way_dscp_change - name: subject assertions - assert: + ansible.builtin.assert: that: - nm_subject_both_qos_dscp is changed - nm_subject_both_qos_dscp.current.0.vzSubj.attributes.prio == "level1" diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_contract_subject_to_filter/tasks/main.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_contract_subject_to_filter/tasks/main.yml index d21571692..39f209789 100644 --- a/ansible_collections/cisco/aci/tests/integration/targets/aci_contract_subject_to_filter/tasks/main.yml +++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_contract_subject_to_filter/tasks/main.yml @@ -3,15 +3,15 @@ # GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) - name: Test that we have an ACI APIC host, ACI username and ACI password - fail: + ansible.builtin.fail: msg: 'Please define the following variables: aci_hostname, aci_username and aci_password.' when: aci_hostname is not defined or aci_username is not defined or aci_password is not defined - name: Verify Cloud and Non-Cloud Sites in use. - include_tasks: ../../../../../../integration/targets/aci_cloud_provider/tasks/main.yml + ansible.builtin.include_tasks: ../../../../../../integration/targets/aci_cloud_provider/tasks/main.yml - name: Set vars - set_fact: + ansible.builtin.set_fact: aci_info: &aci_info host: "{{ aci_hostname }}" username: "{{ aci_username }}" @@ -98,7 +98,7 @@ register: present_missing_param - name: present assertions - assert: + ansible.builtin.assert: that: - subject_filter_present_check_mode is changed - subject_filter_present_check_mode.previous == [] @@ -137,7 +137,7 @@ register: query_binding_non_existing_subject - name: query assertions - assert: + ansible.builtin.assert: that: - query_all is not changed - query_all.current | length > 1 @@ -176,7 +176,7 @@ state: absent - name: absent assertions - assert: + ansible.builtin.assert: that: - subject_filter_absent_check_mode is changed - subject_filter_absent_check_mode.proposed == {} @@ -283,7 +283,7 @@ ignore_errors: true - name: filter assertions - assert: + ansible.builtin.assert: that: - cm_filter1_present_default is changed - nm_filter1_present_default is changed @@ -337,7 +337,7 @@ register: filter_present_deny_non_cloud_c2p - name: filter subject with direction assertions - assert: + ansible.builtin.assert: that: - filter_present_deny_non_cloud_both is changed - filter_present_deny_non_cloud_both.current.0.vzRsSubjFiltAtt.attributes.action == "deny" @@ -373,7 +373,7 @@ ignore_errors: true - name: cloud assertions - assert: + ansible.builtin.assert: that: - filter_present_deny_cloud.msg.startswith("APIC Error 1: Invalid Configuration CLOUD_ONLY_PERMIT_ACTION_SUPPORTED") - filter_present_deny_cloud_p2c.msg.startswith("APIC Error 1: Invalid Configuration CLOUD_ONLY_PERMIT_ACTION_SUPPORTED") diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_contract_subject_to_service_graph/tasks/main.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_contract_subject_to_service_graph/tasks/main.yml index c9e41610f..186f93a13 100644 --- a/ansible_collections/cisco/aci/tests/integration/targets/aci_contract_subject_to_service_graph/tasks/main.yml +++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_contract_subject_to_service_graph/tasks/main.yml @@ -4,7 +4,7 @@ # GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) - name: Test that we have an ACI APIC host, ACI username and ACI password - fail: + ansible.builtin.fail: msg: 'Please define the following variables: aci_hostname, aci_username and aci_password.' when: aci_hostname is not defined or aci_username is not defined or aci_password is not defined @@ -71,7 +71,7 @@ register: present_missing_param - name: present assertions - assert: + ansible.builtin.assert: that: - subject_service_graph_present_check_mode is changed - subject_service_graph_present_check_mode.previous == [] @@ -101,7 +101,7 @@ register: query_binding - name: query assertions - assert: + ansible.builtin.assert: that: - query_all is not changed - query_all.current | length > 0 @@ -134,7 +134,7 @@ register: absent_missing_param - name: absent assertions - assert: + ansible.builtin.assert: that: - subject_service_graph_absent_check_mode is changed - subject_service_graph_absent_check_mode.proposed == {} diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_dhcp_option/aliases b/ansible_collections/cisco/aci/tests/integration/targets/aci_dhcp_option/aliases new file mode 100644 index 000000000..209b793f9 --- /dev/null +++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_dhcp_option/aliases @@ -0,0 +1,2 @@ +# No ACI simulator yet, so not enabled +# unsupported diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_dhcp_option/tasks/main.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_dhcp_option/tasks/main.yml new file mode 100644 index 000000000..6e0f2e32e --- /dev/null +++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_dhcp_option/tasks/main.yml @@ -0,0 +1,188 @@ +# Test code for the ACI modules +# Copyright: (c) 2023, Gaspard Micol (@gmicol) + +# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) + +- name: Test that we have an ACI APIC host, ACI username and ACI password + ansible.builtin.fail: + msg: 'Please define the following variables: aci_hostname, aci_username and aci_password.' + when: aci_hostname is not defined or aci_username is not defined or aci_password is not defined + +- name: Set vars + ansible.builtin.set_fact: + aci_info: &aci_info + host: "{{ aci_hostname }}" + username: "{{ aci_username }}" + password: "{{ aci_password }}" + validate_certs: '{{ aci_validate_certs | default(false) }}' + use_ssl: '{{ aci_use_ssl | default(true) }}' + use_proxy: '{{ aci_use_proxy | default(true) }}' + output_level: debug + +# CLEAN ENVIRONMENT BEFORE TESTS +- name: Remove the ansible_tenant + cisco.aci.aci_tenant: &aci_tenant_absent + <<: *aci_info + tenant: ansible_tenant + state: absent + +- name: Verify Cloud and Non-Cloud Sites in use. + ansible.builtin.include_tasks: ../../../../../../integration/targets/aci_cloud_provider/tasks/main.yml + +- name: Execute tasks only for non-cloud sites + when: query_cloud.current == [] # This condition will execute only non-cloud sites + block: # block specifies execution of tasks within, based on conditions + - name: Add a new tenant + cisco.aci.aci_tenant: &aci_tenant_present + <<: *aci_info + tenant: ansible_tenant + description: Ansible tenant + state: present + + - name: Add a new DHCP option policy + cisco.aci.aci_dhcp_option_policy: + <<: *aci_info + tenant: ansible_tenant + dhcp_option_policy: ansible_dhcp_option_policy_1 + description: DHCP option policy 1 for ansible_tenant tenant + state: present + + # CREATE DHCP OPTION + - name: Add a DHCP option (check_mode) + cisco.aci.aci_dhcp_option: &aci_dhcp_option_present + <<: *aci_info + tenant: ansible_tenant + dhcp_option_policy: ansible_dhcp_option_policy_1 + dhcp_option: ansible_dhcp_option_1 + id: 1 + data: 82 + state: present + check_mode: true + register: cm_add_dhcp_option + + - name: Add a DHCP option (normal_mode) + cisco.aci.aci_dhcp_option: + <<: *aci_dhcp_option_present + register: nm_add_dhcp_option + + - name: Add the first DHCP option again - testing idempotency + cisco.aci.aci_dhcp_option: + <<: *aci_dhcp_option_present + register: nm_add_dhcp_option_idempotency + + - name: Add a second DHCP option (normal_mode) + cisco.aci.aci_dhcp_option: + <<: *aci_info + tenant: ansible_tenant + dhcp_option_policy: ansible_dhcp_option_policy_1 + dhcp_option: ansible_dhcp_option_2 + id: 2 + data: 252 + state: present + register: nm_add_dhcp_option_2 + + - name: Asserts for DHCP option creation tasks + ansible.builtin.assert: + that: + - cm_add_dhcp_option is changed + - cm_add_dhcp_option.previous == [] + - cm_add_dhcp_option.current == [] + - nm_add_dhcp_option is changed + - nm_add_dhcp_option.current.0.dhcpOption.attributes.name == "ansible_dhcp_option_1" + - nm_add_dhcp_option.current.0.dhcpOption.attributes.id == "1" + - nm_add_dhcp_option.current.0.dhcpOption.attributes.data == "82" + - nm_add_dhcp_option_idempotency is not changed + - nm_add_dhcp_option_2 is changed + - nm_add_dhcp_option_2.previous == [] + - nm_add_dhcp_option_2.current.0.dhcpOption.attributes.name == "ansible_dhcp_option_2" + - nm_add_dhcp_option_2.current.0.dhcpOption.attributes.id == "2" + - nm_add_dhcp_option_2.current.0.dhcpOption.attributes.data == "252" + + # QUERY DHCP OPTION + - name: Query all DHCP options + cisco.aci.aci_dhcp_option: + <<: *aci_info + state: query + register: query_all_dhcp_option + + - name: Query ansible_dhcp_option_1 + cisco.aci.aci_dhcp_option: + <<: *aci_dhcp_option_present + state: query + register: query_ansible_dhcp_option_1 + + - name: Asserts query tasks + ansible.builtin.assert: + that: + - query_all_dhcp_option is not changed + - query_all_dhcp_option.current|length >= 2 + - query_ansible_dhcp_option_1 is not changed + - query_ansible_dhcp_option_1.current.0.dhcpOption.attributes.name == "ansible_dhcp_option_1" + - query_ansible_dhcp_option_1.current.0.dhcpOption.attributes.id == "1" + - query_ansible_dhcp_option_1.current.0.dhcpOption.attributes.data == "82" + + #UPDATING DHCP OPTION + - name: Update first DHCP option (check_mode) + cisco.aci.aci_dhcp_option: &aci_dhcp_option_update + <<: *aci_dhcp_option_present + id: 3 + data: 255 + state: present + check_mode: true + register: cm_update_dhcp_option + + - name: Update first DHCP option (normal_mode) + cisco.aci.aci_dhcp_option: + <<: *aci_dhcp_option_update + register: nm_update_dhcp_option + + - name: Update first DHCP option again - testing idempotency + cisco.aci.aci_dhcp_option: + <<: *aci_dhcp_option_update + register: nm_update_dhcp_option_idempotency + + - name: Asserts for DHCP option update tasks + ansible.builtin.assert: + that: + - cm_update_dhcp_option is changed + - cm_update_dhcp_option.previous == cm_update_dhcp_option.current + - nm_update_dhcp_option is changed + - nm_update_dhcp_option.current.0.dhcpOption.attributes.name == "ansible_dhcp_option_1" + - nm_update_dhcp_option.current.0.dhcpOption.attributes.id == "3" + - nm_update_dhcp_option.current.0.dhcpOption.attributes.data == "255" + - nm_update_dhcp_option_idempotency is not changed + + # DELETE DHCP OPTION + - name: Remove DHCP option (check_mode) + cisco.aci.aci_dhcp_option: &dhcp_option_absent + <<: *aci_dhcp_option_update + state: absent + check_mode: true + register: cm_remove_dhcp_option + + - name: Remove DHCP option (normal_mode) + cisco.aci.aci_dhcp_option: + <<: *dhcp_option_absent + register: nm_remove_dhcp_option + + - name: Remove DHCP option - testing idempotency + cisco.aci.aci_dhcp_option: + <<: *dhcp_option_absent + register: nm_remove_dhcp_option_idempotency + + - name: Asserts deletion tasks + ansible.builtin.assert: + that: + - cm_remove_dhcp_option is changed + - cm_remove_dhcp_option.proposed == {} + - nm_remove_dhcp_option is changed + - nm_remove_dhcp_option.previous != [] + - nm_remove_dhcp_option.method == "DELETE" + - nm_remove_dhcp_option_idempotency is not changed + - nm_remove_dhcp_option_idempotency.previous == [] + + # CLEAN ENVIRONMENT BEFORE ENDING TESTS + - name: Remove the ansible_tenant - cleanup before ending tests + cisco.aci.aci_tenant: + <<: *aci_tenant_present + state: absent diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_dhcp_option_policy/aliases b/ansible_collections/cisco/aci/tests/integration/targets/aci_dhcp_option_policy/aliases new file mode 100644 index 000000000..209b793f9 --- /dev/null +++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_dhcp_option_policy/aliases @@ -0,0 +1,2 @@ +# No ACI simulator yet, so not enabled +# unsupported diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_dhcp_option_policy/tasks/main.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_dhcp_option_policy/tasks/main.yml new file mode 100644 index 000000000..48e721254 --- /dev/null +++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_dhcp_option_policy/tasks/main.yml @@ -0,0 +1,139 @@ +# Test code for the ACI modules +# Copyright: (c) 2023, Gaspard Micol (@gmicol) + +# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) + +- name: Test that we have an ACI APIC host, ACI username and ACI password + ansible.builtin.fail: + msg: 'Please define the following variables: aci_hostname, aci_username and aci_password.' + when: aci_hostname is not defined or aci_username is not defined or aci_password is not defined + +- name: Set vars + ansible.builtin.set_fact: + aci_info: &aci_info + host: "{{ aci_hostname }}" + username: "{{ aci_username }}" + password: "{{ aci_password }}" + validate_certs: '{{ aci_validate_certs | default(false) }}' + use_ssl: '{{ aci_use_ssl | default(true) }}' + use_proxy: '{{ aci_use_proxy | default(true) }}' + output_level: debug + +# CLEAN ENVIRONMENT BEFORE TESTS +- name: Remove the ansible_tenant + cisco.aci.aci_tenant: &aci_tenant_absent + <<: *aci_info + tenant: ansible_tenant + state: absent + +- name: Verify Cloud and Non-Cloud Sites in use. + ansible.builtin.include_tasks: ../../../../../../integration/targets/aci_cloud_provider/tasks/main.yml + +- name: Execute tasks only for non-cloud sites + when: query_cloud.current == [] # This condition will execute only non-cloud sites + block: # block specifies execution of tasks within, based on conditions + - name: Add a new tenant + cisco.aci.aci_tenant: &aci_tenant_present + <<: *aci_info + tenant: ansible_tenant + description: Ansible tenant + state: present + + # CREATE DHCP OPTION POLICY + - name: Add a DHCP option policy (check_mode) + cisco.aci.aci_dhcp_option_policy: &aci_dhcp_option_policy_present + <<: *aci_info + tenant: ansible_tenant + dhcp_option_policy: ansible_dhcp_option_policy_1 + description: DHCP option policy 1 for ansible_tenant tenant + state: present + check_mode: true + register: cm_add_dhcp_option_policy + + - name: Add a DHCP option policy (normal_mode) + cisco.aci.aci_dhcp_option_policy: + <<: *aci_dhcp_option_policy_present + register: nm_add_dhcp_option_policy + + - name: Add the first DHCP option policy again - testing idempotency + cisco.aci.aci_dhcp_option_policy: + <<: *aci_dhcp_option_policy_present + register: nm_add_dhcp_option_policy_idempotency + + - name: Add a second DHCP option policy (normal_mode) + cisco.aci.aci_dhcp_option_policy: + <<: *aci_info + tenant: ansible_tenant + dhcp_option_policy: ansible_dhcp_option_policy_2 + description: DHCP option policy 2 for ansible_tenant tenant + state: present + register: nm_add_dhcp_option_policy_2 + + - name: Asserts for DHCP option policy creation tasks + ansible.builtin.assert: + that: + - cm_add_dhcp_option_policy is changed + - cm_add_dhcp_option_policy.previous == [] + - cm_add_dhcp_option_policy.current == [] + - nm_add_dhcp_option_policy is changed + - nm_add_dhcp_option_policy.current.0.dhcpOptionPol.attributes.name == "ansible_dhcp_option_policy_1" + - nm_add_dhcp_option_policy_idempotency is not changed + - nm_add_dhcp_option_policy_2 is changed + - nm_add_dhcp_option_policy_2.previous == [] + - nm_add_dhcp_option_policy_2.current.0.dhcpOptionPol.attributes.name == "ansible_dhcp_option_policy_2" + + # QUERY DHCP OPTION POLICY + - name: Query all DHCP option policies + cisco.aci.aci_dhcp_option_policy: + <<: *aci_info + state: query + register: query_all_dhcp_option_policy + + - name: Query ansible_dhcp_option_policy_1 + cisco.aci.aci_dhcp_option_policy: + <<: *aci_dhcp_option_policy_present + state: query + register: query_ansible_dhcp_option_policy_1 + + - name: Asserts query tasks + ansible.builtin.assert: + that: + - query_all_dhcp_option_policy is not changed + - query_all_dhcp_option_policy.current|length >= 2 + - query_ansible_dhcp_option_policy_1 is not changed + - query_ansible_dhcp_option_policy_1.current.0.dhcpOptionPol.attributes.name == "ansible_dhcp_option_policy_1" + + # DELETE DHCP OPTION POLICY + - name: Remove DHCP option policy (check_mode) + cisco.aci.aci_dhcp_option_policy: &dhcp_option_policy_absent + <<: *aci_dhcp_option_policy_present + state: absent + check_mode: true + register: cm_remove_dhcp_option_policy + + - name: Remove DHCP option policy (normal_mode) + cisco.aci.aci_dhcp_option_policy: + <<: *dhcp_option_policy_absent + register: nm_remove_dhcp_option_policy + + - name: Remove DHCP option policy - testing idempotency + cisco.aci.aci_dhcp_option_policy: + <<: *dhcp_option_policy_absent + register: nm_remove_dhcp_option_policy_idempotency + + - name: Asserts deletion tasks + ansible.builtin.assert: + that: + - cm_remove_dhcp_option_policy is changed + - cm_remove_dhcp_option_policy.proposed == {} + - nm_remove_dhcp_option_policy is changed + - nm_remove_dhcp_option_policy.previous != [] + - nm_remove_dhcp_option_policy.method == "DELETE" + - nm_remove_dhcp_option_policy_idempotency is not changed + - nm_remove_dhcp_option_policy_idempotency.previous == [] + + # CLEAN ENVIRONMENT BEFORE ENDING TESTS + - name: Remove the ansible_tenant - cleanup before ending tests + cisco.aci.aci_tenant: + <<: *aci_tenant_present + state: absent diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_dhcp_relay/tasks/main.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_dhcp_relay/tasks/main.yml index da10cc2d8..93048e853 100644 --- a/ansible_collections/cisco/aci/tests/integration/targets/aci_dhcp_relay/tasks/main.yml +++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_dhcp_relay/tasks/main.yml @@ -5,12 +5,12 @@ # GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) - name: Test that we have an ACI APIC host, ACI username and ACI password - fail: + ansible.builtin.fail: msg: 'Please define the following variables: aci_hostname, aci_username and aci_password.' when: aci_hostname is not defined or aci_username is not defined or aci_password is not defined - name: Set vars - set_fact: + ansible.builtin.set_fact: aci_info: &aci_info host: "{{ aci_hostname }}" username: "{{ aci_username }}" @@ -22,7 +22,7 @@ # CLEAN ENVIRONMENT - name: Remove the ansible_tenant - aci_tenant: + cisco.aci.aci_tenant: <<: *aci_info tenant: ansible_tenant state: absent @@ -34,7 +34,7 @@ state: absent - name: Add a new tenant - aci_tenant: + cisco.aci.aci_tenant: <<: *aci_info tenant: ansible_tenant description: Ansible tenant @@ -51,7 +51,7 @@ register: add_dhcp_relay - name: Verify DHCP Relay creation - assert: + ansible.builtin.assert: that: - add_dhcp_relay is changed - add_dhcp_relay.current.0.dhcpRelayP.attributes.annotation == 'orchestrator:ansible' @@ -71,7 +71,7 @@ register: add_dhcp_relay_again - name: Verify DHCP Relay idempotence - assert: + ansible.builtin.assert: that: - add_dhcp_relay_again is not changed - add_dhcp_relay_again.current.0.dhcpRelayP.attributes.dn == "uni/tn-ansible_tenant/relayp-ansible_dhcp_relay" @@ -90,7 +90,7 @@ register: update_dhcp_relay - name: Verify DHCP Relay change - assert: + ansible.builtin.assert: that: - update_dhcp_relay is changed - update_dhcp_relay.current.0.dhcpRelayP.attributes.dn == "uni/tn-ansible_tenant/relayp-ansible_dhcp_relay" @@ -115,7 +115,7 @@ register: add_global_dhcp_relay - name: Verify Global DHCP Relay creation - assert: + ansible.builtin.assert: that: - add_global_dhcp_relay is changed - add_global_dhcp_relay.current.0.dhcpRelayP.attributes.annotation == 'orchestrator:ansible' @@ -134,7 +134,7 @@ register: query_dhcp_relay - name: Verify DHCP Relay query - assert: + ansible.builtin.assert: that: - query_dhcp_relay is not changed - query_dhcp_relay.current.0.dhcpRelayP.attributes.dn == "uni/tn-ansible_tenant/relayp-ansible_dhcp_relay" @@ -150,7 +150,7 @@ register: query_dhcp_relay_all - name: Verify query idempotence - assert: + ansible.builtin.assert: that: - query_dhcp_relay_all is not changed - query_dhcp_relay_all.current.0.fvTenant.children | length >= 2 @@ -164,7 +164,7 @@ register: query_global_dhcp_relay - name: Verify Global DHCP Relay query - assert: + ansible.builtin.assert: that: - query_global_dhcp_relay is not changed - query_global_dhcp_relay.current.0.dhcpRelayP.attributes.dn == "uni/infra/relayp-ansible_global_dhcp_relay" @@ -179,7 +179,7 @@ register: query_global_dhcp_relay_all - name: Verify query idempotence for Global DHCP Relay - assert: + ansible.builtin.assert: that: - query_global_dhcp_relay_all is not changed - query_global_dhcp_relay_all.current | length >= 3 @@ -194,7 +194,7 @@ register: delete_dhcp_relay - name: Verify DHCP Relay deletion - assert: + ansible.builtin.assert: that: - delete_dhcp_relay is changed - delete_dhcp_relay.current == [] @@ -212,7 +212,7 @@ register: delete_dhcp_relay_again - name: Verify DHCP Relay deletion idempotence - assert: + ansible.builtin.assert: that: - delete_dhcp_relay_again is not changed @@ -225,7 +225,7 @@ register: delete_global_dhcp_relay - name: Verify Global DHCP Relay deletion - assert: + ansible.builtin.assert: that: - delete_global_dhcp_relay is changed - delete_global_dhcp_relay.current == [] @@ -236,7 +236,7 @@ # CLEAN ENVIRONMENT AGAIN - name: Remove the ansible_tenant - aci_tenant: + cisco.aci.aci_tenant: <<: *aci_info tenant: ansible_tenant state: absent diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_dhcp_relay_provider/tasks/main.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_dhcp_relay_provider/tasks/main.yml index c133e23ba..078be3f38 100644 --- a/ansible_collections/cisco/aci/tests/integration/targets/aci_dhcp_relay_provider/tasks/main.yml +++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_dhcp_relay_provider/tasks/main.yml @@ -5,12 +5,12 @@ # GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) - name: Test that we have an ACI APIC host, ACI username and ACI password - fail: + ansible.builtin.fail: msg: 'Please define the following variables: aci_hostname, aci_username and aci_password.' when: aci_hostname is not defined or aci_username is not defined or aci_password is not defined - name: Set vars - set_fact: + ansible.builtin.set_fact: aci_info: &aci_info host: "{{ aci_hostname }}" username: "{{ aci_username }}" @@ -21,11 +21,11 @@ output_level: debug - name: Verify Cloud and Non-Cloud Sites in use. - include_tasks: ../../../../../../integration/targets/aci_cloud_provider/tasks/main.yml + ansible.builtin.include_tasks: ../../../../../../integration/targets/aci_cloud_provider/tasks/main.yml # CLEAN ENVIRONMENT - name: Remove the ansible_tenant - aci_tenant: + cisco.aci.aci_tenant: <<: *aci_info tenant: ansible_tenant state: absent @@ -54,7 +54,7 @@ when: query_cloud.current == [] # This condition will execute only non-cloud sites block: # block specifies execution of tasks within, based on conditions - name: Add a new tenant - aci_tenant: + cisco.aci.aci_tenant: <<: *aci_info tenant: ansible_tenant description: Ansible tenant @@ -219,7 +219,7 @@ register: add_dn_relay_provider - name: Confirm DHCP relay provider creation - assert: + ansible.builtin.assert: that: - add_epg_relay_provider is changed - add_epg_relay_provider.current.0.dhcpRsProv.attributes.annotation == 'orchestrator:ansible' @@ -289,7 +289,7 @@ register: add_dn_relay_provider_again - name: Confirm DHCP relay provider idempotence - assert: + ansible.builtin.assert: that: - add_epg_relay_provider_again is not changed - add_epg_relay_provider_again.current.0.dhcpRsProv.attributes.dn == "uni/tn-ansible_tenant/relayp-ansible_dhcp_relay/rsprov-[uni/tn-ansible_tenant/ap-ansible_ap/epg-ansible_epg]" @@ -358,7 +358,7 @@ register: update_dn_relay_provider - name: Confirm DHCP relay provider update - assert: + ansible.builtin.assert: that: - update_epg_relay_provider is changed - update_epg_relay_provider.current.0.dhcpRsProv.attributes.dn == "uni/tn-ansible_tenant/relayp-ansible_dhcp_relay/rsprov-[uni/tn-ansible_tenant/ap-ansible_ap/epg-ansible_epg]" @@ -429,7 +429,7 @@ register: query_all_relay_provider - name: Confirm DHCP relay provider query - assert: + ansible.builtin.assert: that: - query_epg_relay_provider is not changed - query_epg_relay_provider.current.0.dhcpRsProv.attributes.dn == "uni/tn-ansible_tenant/relayp-ansible_dhcp_relay/rsprov-[uni/tn-ansible_tenant/ap-ansible_ap/epg-ansible_epg]" @@ -510,7 +510,7 @@ register: add_global_dn_relay_provider - name: Confirm Global DHCP relay provider creation - assert: + ansible.builtin.assert: that: - err_global_epg_relay_provider is failed - err_global_epg_relay_provider.msg == "provider_tenant is required when epg_type is epg" @@ -582,7 +582,7 @@ register: query_global_all_relay_provider - name: Confirm DHCP relay provider query - assert: + ansible.builtin.assert: that: - query_global_epg_relay_provider is not changed - query_global_epg_relay_provider.current.0.dhcpRsProv.attributes.dn == "uni/infra/relayp-ansible_global_dhcp_relay/rsprov-[uni/tn-ansible_tenant/ap-ansible_ap/epg-ansible_epg]" @@ -649,7 +649,7 @@ register: delete_dn_relay_provider - name: Confirm DHCP relay provider removal - assert: + ansible.builtin.assert: that: - delete_epg_relay_provider is changed - delete_epg_relay_provider.current == [] @@ -717,7 +717,7 @@ register: delete_dn_relay_provider_again - name: Confirm DHCP relay provider removal - assert: + ansible.builtin.assert: that: - delete_epg_relay_provider_again is not changed - delete_l2_relay_provider_again is not changed @@ -768,7 +768,7 @@ register: delete_global_dn_relay_provider - name: Confirm DHCP relay provider removal - assert: + ansible.builtin.assert: that: - delete_global_epg_relay_provider is changed - delete_global_epg_relay_provider.current == [] @@ -792,7 +792,7 @@ # CLEAN ENVIRONMENT AGAIN - name: Remove the ansible_tenant - aci_tenant: + cisco.aci.aci_tenant: <<: *aci_info tenant: ansible_tenant state: absent diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_dns_domain/tasks/main.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_dns_domain/tasks/main.yml index af9c1026b..d0fe0b29d 100644 --- a/ansible_collections/cisco/aci/tests/integration/targets/aci_dns_domain/tasks/main.yml +++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_dns_domain/tasks/main.yml @@ -4,13 +4,13 @@ # GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) - name: Test that we have an ACI APIC host, ACI username and ACI password - fail: + ansible.builtin.fail: msg: 'Please define the following variables: aci_hostname, aci_username and aci_password.' when: aci_hostname is not defined or aci_username is not defined or aci_password is not defined # GET Credentials from the inventory - name: Set vars - set_fact: + ansible.builtin.set_fact: aci_info: &aci_info host: "{{ aci_hostname }}" username: "{{ aci_username }}" @@ -45,7 +45,7 @@ register: add_dns_domain - name: Verify DNS domain creation - assert: + ansible.builtin.assert: that: - add_dns_domain is changed - add_dns_domain.current.0.dnsDomain.attributes.annotation == 'orchestrator:ansible' @@ -64,7 +64,7 @@ register: add_dns_domain_again - name: Verify DNS domain creation idempotence - assert: + ansible.builtin.assert: that: - add_dns_domain_again is not changed - add_dns_domain_again.current.0.dnsDomain.attributes.dn == "uni/fabric/dnsp-ansible_dns_profile/dom-example.com" @@ -82,7 +82,7 @@ register: update_dns_domain - name: Verify DNS domain update - assert: + ansible.builtin.assert: that: - update_dns_domain is changed - update_dns_domain.current.0.dnsDomain.attributes.dn == "uni/fabric/dnsp-ansible_dns_profile/dom-example.com" @@ -99,7 +99,7 @@ register: query_dns_domain - name: Verify DNS domain attributes - assert: + ansible.builtin.assert: that: - query_dns_domain is not changed - query_dns_domain.current.0.dnsDomain.attributes.dn == "uni/fabric/dnsp-ansible_dns_profile/dom-example.com" @@ -115,7 +115,7 @@ register: query_dns_domain_all - name: Verify DNS domain query idempotence - assert: + ansible.builtin.assert: that: - query_dns_domain_all is not changed @@ -129,7 +129,7 @@ register: delete_dns_domain - name: Verify DNS domain deletion - assert: + ansible.builtin.assert: that: - delete_dns_domain is changed - delete_dns_domain.current == [] @@ -147,7 +147,7 @@ register: delete_dns_domain_again - name: Verify DNS domain deletion idempotence - assert: + ansible.builtin.assert: that: - delete_dns_domain_again is not changed diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_dns_profile/tasks/main.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_dns_profile/tasks/main.yml index 126bb27a6..027532f63 100644 --- a/ansible_collections/cisco/aci/tests/integration/targets/aci_dns_profile/tasks/main.yml +++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_dns_profile/tasks/main.yml @@ -4,13 +4,13 @@ # GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) - name: Test that we have an ACI APIC host, ACI username and ACI password - fail: + ansible.builtin.fail: msg: 'Please define the following variables: aci_hostname, aci_username and aci_password.' when: aci_hostname is not defined or aci_username is not defined or aci_password is not defined # GET Credentials from the inventory - name: Set vars - set_fact: + ansible.builtin.set_fact: aci_info: &aci_info host: "{{ aci_hostname }}" username: "{{ aci_username }}" @@ -29,7 +29,7 @@ register: add_dns_profile - name: Verify that DNS profile has been created with correct attributes - assert: + ansible.builtin.assert: that: - add_dns_profile is changed - add_dns_profile.current.0.dnsProfile.attributes.annotation == 'orchestrator:ansible' @@ -45,7 +45,7 @@ register: add_dns_profile_again - name: Verify that DNS profile creation idempotence - assert: + ansible.builtin.assert: that: - add_dns_profile_again is not changed - add_dns_profile_again.current.0.dnsProfile.attributes.dn == "uni/fabric/dnsp-ansible_dns_profile" @@ -60,7 +60,7 @@ register: query_dns_profile - name: Verify DNS profile - assert: + ansible.builtin.assert: that: - query_dns_profile is not changed - query_dns_profile.current.0.dnsProfile.attributes.dn == "uni/fabric/dnsp-ansible_dns_profile" @@ -73,7 +73,7 @@ register: query_dns_profile_all - name: Verify query idempotence - assert: + ansible.builtin.assert: that: - query_dns_profile_all is not changed @@ -86,7 +86,7 @@ register: remove_dns_profile - name: Verify DNS profile removal - assert: + ansible.builtin.assert: that: - remove_dns_profile is changed - remove_dns_profile.current == [] @@ -102,6 +102,6 @@ register: remove_dns_profile_again - name: Verify DNS profile removal idempotence - assert: + ansible.builtin.assert: that: - remove_dns_profile_again is not changed diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_dns_provider/tasks/main.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_dns_provider/tasks/main.yml index 3e31d2b52..7f55e11c7 100644 --- a/ansible_collections/cisco/aci/tests/integration/targets/aci_dns_provider/tasks/main.yml +++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_dns_provider/tasks/main.yml @@ -4,13 +4,13 @@ # GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) - name: Test that we have an ACI APIC host, ACI username and ACI password - fail: + ansible.builtin.fail: msg: 'Please define the following variables: aci_hostname, aci_username and aci_password.' when: aci_hostname is not defined or aci_username is not defined or aci_password is not defined # GET Credentials from the inventory - name: Set vars - set_fact: + ansible.builtin.set_fact: aci_info: &aci_info host: "{{ aci_hostname }}" username: "{{ aci_username }}" @@ -45,7 +45,7 @@ register: add_dns_provider - name: Verify DNS provider creation - assert: + ansible.builtin.assert: that: - add_dns_provider is changed - add_dns_provider.current.0.dnsProv.attributes.annotation == 'orchestrator:ansible' @@ -64,7 +64,7 @@ register: add_dns_provider_again - name: Verify DNS provider creation idempotence - assert: + ansible.builtin.assert: that: - add_dns_provider_again is not changed - add_dns_provider_again.current.0.dnsProv.attributes.dn == "uni/fabric/dnsp-ansible_dns_profile/prov-[10.20.30.40]" @@ -82,7 +82,7 @@ register: update_dns_provider - name: Verify DNS provider update - assert: + ansible.builtin.assert: that: - update_dns_provider is changed - update_dns_provider.current.0.dnsProv.attributes.dn == "uni/fabric/dnsp-ansible_dns_profile/prov-[10.20.30.40]" @@ -99,7 +99,7 @@ register: query_dns_provider - name: Verify DNS provider attributes - assert: + ansible.builtin.assert: that: - query_dns_provider is not changed - query_dns_provider.current.0.dnsProv.attributes.dn == "uni/fabric/dnsp-ansible_dns_profile/prov-[10.20.30.40]" @@ -115,7 +115,7 @@ register: query_dns_provider_all - name: Verify DNS provider query idempotence - assert: + ansible.builtin.assert: that: - query_dns_provider_all is not changed @@ -129,7 +129,7 @@ register: delete_dns_provider - name: Verify DNS provider deletion - assert: + ansible.builtin.assert: that: - delete_dns_provider is changed - delete_dns_provider.current == [] @@ -147,7 +147,7 @@ register: delete_dns_provider_again - name: Verify DNS provider deletion idempotence - assert: + ansible.builtin.assert: that: - delete_dns_provider_again is not changed diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_domain/tasks/fc.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_domain/tasks/fc.yml index 2e2a8eb0b..ea27d4ba2 100644 --- a/ansible_collections/cisco/aci/tests/integration/targets/aci_domain/tasks/fc.yml +++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_domain/tasks/fc.yml @@ -40,7 +40,7 @@ register: nm_add_domain - name: Verify FC add_domain - assert: + ansible.builtin.assert: that: - cm_add_domain is changed - nm_add_domain is changed @@ -61,7 +61,7 @@ register: nm_add_domain_again - name: Verify FC add_domain_again - assert: + ansible.builtin.assert: that: - cm_add_domain_again is not changed - nm_add_domain_again is not changed @@ -172,7 +172,7 @@ register: nm_incorrect_enable_vm_folder - name: Verify incorrect parameter - assert: + ansible.builtin.assert: that: - cm_incorrect_vm_provider.msg == "Domain type 'fc' cannot have parameter 'vm_provider'" - nm_incorrect_vm_provider.msg == "Domain type 'fc' cannot have parameter 'vm_provider'" @@ -209,7 +209,7 @@ register: nm_query_all_domains - name: Verify FC query_all_domains - assert: + ansible.builtin.assert: that: - cm_query_all_domains is not changed - nm_query_all_domains is not changed @@ -232,7 +232,7 @@ register: nm_query_domain - name: Verify FC query_domain - assert: + ansible.builtin.assert: that: - cm_query_domain is not changed - nm_query_domain is not changed @@ -252,7 +252,7 @@ register: nm_remove_domain - name: Verify FC remove_domain - assert: + ansible.builtin.assert: that: - cm_remove_domain is changed - nm_remove_domain is changed @@ -270,7 +270,7 @@ register: nm_remove_domain_again - name: Verify FC remove_domain_again - assert: + ansible.builtin.assert: that: - cm_remove_domain_again is not changed - nm_remove_domain_again is not changed @@ -291,7 +291,7 @@ register: nm_query_non_domain - name: Verify FC query_non_domain - assert: + ansible.builtin.assert: that: - cm_query_non_domain is not changed - nm_query_non_domain is not changed diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_domain/tasks/l2dom.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_domain/tasks/l2dom.yml index 4f0084174..031944789 100644 --- a/ansible_collections/cisco/aci/tests/integration/targets/aci_domain/tasks/l2dom.yml +++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_domain/tasks/l2dom.yml @@ -40,7 +40,7 @@ register: nm_add_domain - name: Verify L2 add_domain - assert: + ansible.builtin.assert: that: - cm_add_domain is changed - nm_add_domain is changed @@ -61,7 +61,7 @@ register: nm_add_domain_again - name: Verify L2 add_domain_again - assert: + ansible.builtin.assert: that: - cm_add_domain_again is not changed - nm_add_domain_again is not changed @@ -127,7 +127,7 @@ register: nm_incorrect_vswitch - name: Verify incorrect parameter - assert: + ansible.builtin.assert: that: - cm_incorrect_vm_provider.msg == "Domain type 'l2dom' cannot have parameter 'vm_provider'" - nm_incorrect_vm_provider.msg == "Domain type 'l2dom' cannot have parameter 'vm_provider'" @@ -158,7 +158,7 @@ register: nm_query_all_domains - name: Verify L2 query_all_domains - assert: + ansible.builtin.assert: that: - cm_query_all_domains is not changed - nm_query_all_domains is not changed @@ -181,7 +181,7 @@ register: nm_query_domain - name: Verify L2 query_domain - assert: + ansible.builtin.assert: that: - cm_query_domain is not changed - nm_query_domain is not changed @@ -201,7 +201,7 @@ register: nm_remove_domain - name: Verify L2 remove_domain - assert: + ansible.builtin.assert: that: - cm_remove_domain is changed - nm_remove_domain is changed @@ -219,7 +219,7 @@ register: nm_remove_domain_again - name: Verify L2 remove_domain_again - assert: + ansible.builtin.assert: that: - cm_remove_domain_again is not changed - nm_remove_domain_again is not changed @@ -240,7 +240,7 @@ register: nm_query_non_domain - name: Verify L2 query_non_domain - assert: + ansible.builtin.assert: that: - cm_query_non_domain is not changed - nm_query_non_domain is not changed diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_domain/tasks/l3dom.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_domain/tasks/l3dom.yml index 61677d897..aaa55eae8 100644 --- a/ansible_collections/cisco/aci/tests/integration/targets/aci_domain/tasks/l3dom.yml +++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_domain/tasks/l3dom.yml @@ -40,7 +40,7 @@ register: nm_add_domain - name: Verify L3 add_domain - assert: + ansible.builtin.assert: that: - cm_add_domain is changed - nm_add_domain is changed @@ -61,7 +61,7 @@ register: nm_add_domain_again - name: Verify L3 add_domain_again - assert: + ansible.builtin.assert: that: - cm_add_domain_again is not changed - nm_add_domain_again is not changed @@ -127,7 +127,7 @@ register: nm_incorrect_vswitch - name: Verify incorrect parameter - assert: + ansible.builtin.assert: that: - cm_incorrect_vm_provider.msg == "Domain type 'l3dom' cannot have parameter 'vm_provider'" - nm_incorrect_vm_provider.msg == "Domain type 'l3dom' cannot have parameter 'vm_provider'" @@ -159,7 +159,7 @@ register: nm_query_all_domains - name: Verify query_all_domains - assert: + ansible.builtin.assert: that: - cm_query_all_domains is not changed - nm_query_all_domains is not changed @@ -182,7 +182,7 @@ register: nm_query_domain - name: Verify L3 query_domain - assert: + ansible.builtin.assert: that: - cm_query_domain is not changed - nm_query_domain is not changed @@ -202,7 +202,7 @@ register: nm_remove_domain - name: Verify L3 remove_domain - assert: + ansible.builtin.assert: that: - cm_remove_domain is changed - nm_remove_domain is changed @@ -220,7 +220,7 @@ register: nm_remove_domain_again - name: Verify L3 remove_domain_again - assert: + ansible.builtin.assert: that: - cm_remove_domain_again is not changed - nm_remove_domain_again is not changed @@ -241,7 +241,7 @@ register: nm_query_non_domain - name: Verify L3 query_non_domain - assert: + ansible.builtin.assert: that: - cm_query_non_domain is not changed - nm_query_non_domain is not changed diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_domain/tasks/main.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_domain/tasks/main.yml index be6c9712d..591c01b22 100644 --- a/ansible_collections/cisco/aci/tests/integration/targets/aci_domain/tasks/main.yml +++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_domain/tasks/main.yml @@ -4,7 +4,7 @@ # GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) - name: Test that we have an ACI APIC host, ACI username and ACI password - fail: + ansible.builtin.fail: msg: 'Please define the following variables: aci_hostname, aci_username and aci_password.' when: aci_hostname is not defined or aci_username is not defined or aci_password is not defined diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_domain/tasks/phys.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_domain/tasks/phys.yml index 39f87a6f0..c12b09ace 100644 --- a/ansible_collections/cisco/aci/tests/integration/targets/aci_domain/tasks/phys.yml +++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_domain/tasks/phys.yml @@ -40,7 +40,7 @@ register: nm_add_domain - name: Verify physical add_domain - assert: + ansible.builtin.assert: that: - cm_add_domain is changed - nm_add_domain is changed @@ -61,7 +61,7 @@ register: nm_add_domain_again - name: Verify physical add_domain_again - assert: + ansible.builtin.assert: that: - cm_add_domain_again is not changed - nm_add_domain_again is not changed @@ -127,7 +127,7 @@ register: nm_incorrect_vswitch - name: Verify incorrect parameter - assert: + ansible.builtin.assert: that: - cm_incorrect_vm_provider.msg == "Domain type 'phys' cannot have parameter 'vm_provider'" - nm_incorrect_vm_provider.msg == "Domain type 'phys' cannot have parameter 'vm_provider'" @@ -158,7 +158,7 @@ register: nm_query_all_domains - name: Verify physical query_all_domains - assert: + ansible.builtin.assert: that: - cm_query_all_domains is not changed - nm_query_all_domains is not changed @@ -181,7 +181,7 @@ register: nm_query_domain - name: Verify physical query_domain - assert: + ansible.builtin.assert: that: - cm_query_domain is not changed - nm_query_domain is not changed @@ -201,7 +201,7 @@ register: nm_remove_domain - name: Verify physical remove_domain - assert: + ansible.builtin.assert: that: - cm_remove_domain is changed - nm_remove_domain is changed @@ -219,7 +219,7 @@ register: nm_remove_domain_again - name: Verify physical remove_domain_again - assert: + ansible.builtin.assert: that: - cm_remove_domain_again is not changed - nm_remove_domain_again is not changed @@ -240,7 +240,7 @@ register: nm_query_non_domain - name: Verify physical query_non_domain - assert: + ansible.builtin.assert: that: - cm_query_non_domain is not changed - nm_query_non_domain is not changed diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_domain/tasks/vmm-vmware.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_domain/tasks/vmm-vmware.yml index 03d82788c..2f0372186 100644 --- a/ansible_collections/cisco/aci/tests/integration/targets/aci_domain/tasks/vmm-vmware.yml +++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_domain/tasks/vmm-vmware.yml @@ -19,7 +19,7 @@ state: absent - name: Verify Cloud and Non-Cloud Sites in use. - include_tasks: ../../../../../../integration/targets/aci_cloud_provider/tasks/main.yml + ansible.builtin.include_tasks: ../../../../../../integration/targets/aci_cloud_provider/tasks/main.yml - name: Execute tasks only for non-cloud sites when: query_cloud.current == [] # This condition will skip execution for cloud sites @@ -48,7 +48,7 @@ register: nm_add_domain - name: Verify VMM add_domain - assert: + ansible.builtin.assert: that: - cm_add_domain is changed - nm_add_domain is changed @@ -69,7 +69,7 @@ register: nm_add_domain_again - name: Verify VMM add_domain_again - assert: + ansible.builtin.assert: that: - cm_add_domain_again is not changed - nm_add_domain_again is not changed @@ -92,7 +92,7 @@ when: version.current.0.topSystem.attributes.version is version('4.1', '>=') - name: Verify update_domain - assert: + ansible.builtin.assert: that: - cm_update_domain is changed - nm_update_domain is changed @@ -123,7 +123,7 @@ register: nm_query_all_domains - name: Verify query_all_domains - assert: + ansible.builtin.assert: that: - cm_query_all_domains is not changed - nm_query_all_domains is not changed @@ -148,7 +148,7 @@ register: nm_query_domain - name: Verify VMM query_domain - assert: + ansible.builtin.assert: that: - cm_query_domain is not changed - nm_query_domain is not changed @@ -167,7 +167,7 @@ register: nm_remove_domain - name: Verify VMM remove_domain - assert: + ansible.builtin.assert: that: - cm_remove_domain is changed - nm_remove_domain is changed @@ -186,7 +186,7 @@ register: nm_remove_domain_again - name: Verify VMM remove_domain_again - assert: + ansible.builtin.assert: that: - cm_remove_domain_again is not changed - nm_remove_domain_again is not changed @@ -209,7 +209,7 @@ register: nm_query_non_domain - name: Verify VMM query_non_domain - assert: + ansible.builtin.assert: that: - cm_query_non_domain is not changed - nm_query_non_domain is not changed diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_domain_to_encap_pool/tasks/main.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_domain_to_encap_pool/tasks/main.yml index f028e2c56..77c824300 100644 --- a/ansible_collections/cisco/aci/tests/integration/targets/aci_domain_to_encap_pool/tasks/main.yml +++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_domain_to_encap_pool/tasks/main.yml @@ -4,12 +4,12 @@ # GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) - name: Test that we have an ACI APIC host, ACI username and ACI password - fail: + ansible.builtin.fail: msg: 'Please define the following variables: aci_hostname, aci_username and aci_password.' when: aci_hostname is not defined or aci_username is not defined or aci_password is not defined - name: Set vars - set_fact: + ansible.builtin.set_fact: aci_info: &aci_info host: "{{ aci_hostname }}" username: "{{ aci_username }}" @@ -20,11 +20,11 @@ output_level: debug - name: Verify Cloud and Non-Cloud Sites in use. - include_tasks: ../../../../../../integration/targets/aci_cloud_provider/tasks/main.yml + ansible.builtin.include_tasks: ../../../../../../integration/targets/aci_cloud_provider/tasks/main.yml # Clean Environment - name: Remove domains - aci_domain: + cisco.aci.aci_domain: <<: *aci_info domain: '{{ item.name }}' domain_type: '{{ item.type }}' @@ -36,7 +36,7 @@ - { name: l3_dom, type: l3dom } - name: Remove domains - aci_domain: + cisco.aci.aci_domain: <<: *aci_info domain: vmm_dom domain_type: vmm @@ -56,7 +56,7 @@ block: # block specifies execution of tasks within, based on conditions # Add - name: Add physical domain - aci_domain: + cisco.aci.aci_domain: <<: *aci_info domain: phys_dom domain_type: phys @@ -64,7 +64,7 @@ register: phys_domain - name: Add l2 domain - aci_domain: + cisco.aci.aci_domain: <<: *aci_info domain: l2_dom domain_type: l2dom @@ -72,7 +72,7 @@ register: l2_domain - name: Add l3 domain - aci_domain: + cisco.aci.aci_domain: <<: *aci_info domain: l3_dom domain_type: l3dom @@ -80,7 +80,7 @@ register: l3_domain - name: Add FC domain - aci_domain: + cisco.aci.aci_domain: <<: *aci_info domain: fc_dom domain_type: fc @@ -88,7 +88,7 @@ register: fc_domain - name: Add vmm domain - aci_domain: + cisco.aci.aci_domain: <<: *aci_info domain: vmm_dom domain_type: vmm @@ -97,7 +97,7 @@ register: vmm_domain - name: Add domain to encap pool binding (phys, pool_type=vlan) - aci_domain_to_encap_pool: + cisco.aci.aci_domain_to_encap_pool: <<: *aci_info domain: phys_dom domain_type: phys @@ -108,7 +108,7 @@ register: phys_vlan - name: Add domain to encap pool binding (fc, pool_type=vsan) - aci_domain_to_encap_pool: + cisco.aci.aci_domain_to_encap_pool: <<: *aci_info domain: fc_dom domain_type: fc @@ -119,7 +119,7 @@ register: fc_vsan - name: Add domain to encap pool binding (domain_type=l2dom) - aci_domain_to_encap_pool: + cisco.aci.aci_domain_to_encap_pool: <<: *aci_info domain: l2_dom domain_type: l2dom @@ -130,7 +130,7 @@ register: l2dom - name: Add domain to encap pool binding (domain_type=l3dom) - aci_domain_to_encap_pool: + cisco.aci.aci_domain_to_encap_pool: <<: *aci_info domain: l3_dom domain_type: l3dom @@ -141,7 +141,7 @@ register: l3dom - name: Add domain to encap pool binding (domain_type=vmm, vm_provider=cloudfoundry) - aci_domain_to_encap_pool: + cisco.aci.aci_domain_to_encap_pool: <<: *aci_info domain: vmm_dom domain_type: vmm @@ -153,7 +153,7 @@ register: vmm_cloudfoundry - name: Add domain to encap pool binding (domain_type=vmm, vm_provider=kubernetes) - aci_domain_to_encap_pool: + cisco.aci.aci_domain_to_encap_pool: <<: *aci_info domain: vmm_dom domain_type: vmm @@ -165,7 +165,7 @@ register: vmm_kubernetes - name: Add domain to encap pool binding (domain_type=vmm, vm_provider=microsoft) - aci_domain_to_encap_pool: + cisco.aci.aci_domain_to_encap_pool: <<: *aci_info domain: vmm_dom domain_type: vmm @@ -177,7 +177,7 @@ register: vmm_microsoft - name: Add domain to encap pool binding (domain_type=vmm, vm_provider=openshift) - aci_domain_to_encap_pool: + cisco.aci.aci_domain_to_encap_pool: <<: *aci_info domain: vmm_dom domain_type: vmm @@ -189,7 +189,7 @@ register: vmm_openshift - name: Add domain to encap pool binding (domain_type=vmm, vm_provider=openstack) - aci_domain_to_encap_pool: + cisco.aci.aci_domain_to_encap_pool: <<: *aci_info domain: vmm_dom domain_type: vmm @@ -201,7 +201,7 @@ register: vmm_openstack - name: Add domain to encap pool binding (domain_type=vmm, vm_provider=redhat) - aci_domain_to_encap_pool: + cisco.aci.aci_domain_to_encap_pool: <<: *aci_info domain: vmm_dom domain_type: vmm @@ -213,7 +213,7 @@ register: vmm_redhat - name: Add domain to encap pool binding (domain_type=vmm, vm_provider=vmware) - aci_domain_to_encap_pool: + cisco.aci.aci_domain_to_encap_pool: <<: *aci_info domain: vmm_dom domain_type: vmm @@ -225,7 +225,7 @@ register: vmm_vmware - name: Add domain to encap pool binding (domain_type=vmm, vm_provider=vmware) again - aci_domain_to_encap_pool: + cisco.aci.aci_domain_to_encap_pool: <<: *aci_info domain: vmm_dom domain_type: vmm @@ -237,7 +237,7 @@ register: vmm_vmware_idemp - name: Add domain to encap pool binding (phys with vm_provider) - aci_domain_to_encap_pool: + cisco.aci.aci_domain_to_encap_pool: <<: *aci_info domain: phys_dom domain_type: phys @@ -250,7 +250,7 @@ register: phys_vlan_with_vmm - name: Add domain to encap pool binding (phys, pool_type=vlan, no allocation mode) - aci_domain_to_encap_pool: + cisco.aci.aci_domain_to_encap_pool: <<: *aci_info domain: phys_dom domain_type: phys @@ -261,7 +261,7 @@ 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: + cisco.aci.aci_domain_to_encap_pool: <<: *aci_info domain: vmm_dom domain_type: vmm @@ -274,7 +274,7 @@ register: vmm_vmware_vxlan - name: Add domain to encap pool binding (phys, pool_type=vlan) missing domain_type - aci_domain_to_encap_pool: + cisco.aci.aci_domain_to_encap_pool: <<: *aci_info domain: phys_dom pool: test_pool @@ -285,7 +285,7 @@ register: phys_missing_domain_type - name: Add domain to encap pool binding (phys, pool_type=vlan) missing pool_type - aci_domain_to_encap_pool: + cisco.aci.aci_domain_to_encap_pool: <<: *aci_info domain: phys_dom domain_type: phys @@ -296,7 +296,7 @@ register: phys_missing_pool_type - name: Verify add operation for All Sites - assert: + ansible.builtin.assert: that: - phys_vlan is changed - fc_vsan is changed @@ -316,7 +316,7 @@ - phys_missing_domain_type.msg is match("missing required arguments{{':'}} domain_type") - name: Verify add operation for Non-Cloud Sites - assert: + ansible.builtin.assert: that: - vmm_cloudfoundry is changed - vmm_openshift is changed @@ -333,7 +333,7 @@ # QUERY - name: Query all - aci_domain_to_encap_pool: + cisco.aci.aci_domain_to_encap_pool: <<: *aci_info domain_type: phys pool_type: vlan @@ -341,7 +341,7 @@ register: query_all - name: Query phys - aci_domain_to_encap_pool: + cisco.aci.aci_domain_to_encap_pool: <<: *aci_info domain: phys_dom domain_type: phys @@ -350,7 +350,7 @@ register: query_phys - name: Query fc - aci_domain_to_encap_pool: + cisco.aci.aci_domain_to_encap_pool: <<: *aci_info domain: fc_dom domain_type: fc @@ -359,7 +359,7 @@ register: query_fc - name: Query l2dom - aci_domain_to_encap_pool: + cisco.aci.aci_domain_to_encap_pool: <<: *aci_info domain: l2_dom domain_type: l2dom @@ -368,7 +368,7 @@ register: query_l2dom - name: Query l3dom - aci_domain_to_encap_pool: + cisco.aci.aci_domain_to_encap_pool: <<: *aci_info domain: l3_dom domain_type: l3dom @@ -377,7 +377,7 @@ register: query_l3dom - name: Query vmm - aci_domain_to_encap_pool: + cisco.aci.aci_domain_to_encap_pool: <<: *aci_info domain: vmm_dom domain_type: vmm @@ -387,7 +387,7 @@ register: query_vmm_microsoft - name: Query vmm - aci_domain_to_encap_pool: + cisco.aci.aci_domain_to_encap_pool: <<: *aci_info domain: vmm_dom domain_type: vmm @@ -397,7 +397,7 @@ register: query_vmm_cloudfoundry - name: Query vmm - aci_domain_to_encap_pool: + cisco.aci.aci_domain_to_encap_pool: <<: *aci_info domain: vmm_dom domain_type: vmm @@ -407,7 +407,7 @@ register: query_vmm_kubernetes - name: Query vmm - aci_domain_to_encap_pool: + cisco.aci.aci_domain_to_encap_pool: <<: *aci_info domain: vmm_dom domain_type: vmm @@ -417,7 +417,7 @@ register: query_vmm_openshift - name: Query vmm - aci_domain_to_encap_pool: + cisco.aci.aci_domain_to_encap_pool: <<: *aci_info domain: vmm_dom domain_type: vmm @@ -427,7 +427,7 @@ register: query_vmm_openstack - name: Query vmm - aci_domain_to_encap_pool: + cisco.aci.aci_domain_to_encap_pool: <<: *aci_info domain: vmm_dom domain_type: vmm @@ -437,7 +437,7 @@ register: query_vmm_redhat - name: Query vmm - aci_domain_to_encap_pool: + cisco.aci.aci_domain_to_encap_pool: <<: *aci_info domain: vmm_dom domain_type: vmm @@ -447,7 +447,7 @@ register: query_vmm_vmware - name: Query vmm - aci_domain_to_encap_pool: + cisco.aci.aci_domain_to_encap_pool: <<: *aci_info domain: vmm_dom domain_type: vmm @@ -457,7 +457,7 @@ register: query_vmm_vmware - name: Verify Query for Non-Cloud sites - assert: + ansible.builtin.assert: that: - query_all | length >=1 - query_phys.current.0.physDomP.children.0.infraRsVlanNs.attributes.tDn =='uni/infra/vlanns-[test_pool]-dynamic' @@ -468,7 +468,7 @@ - name: Verify Query for Cloud sites - assert: + ansible.builtin.assert: that: - query_vmm_cloudfoundry.current.0.vmmDomP.children.0.infraRsVlanNs.attributes.tDn == 'uni/infra/vlanns-[test_pool]-dynamic' - query_vmm_microsoft.current.0.vmmDomP.children.0.infraRsVlanNs.attributes.tDn == 'uni/infra/vlanns-[test_pool]-dynamic' @@ -479,7 +479,7 @@ # REMOVE - name: Remove phys - aci_domain_to_encap_pool: + cisco.aci.aci_domain_to_encap_pool: <<: *aci_info domain_type: phys domain: phys_dom @@ -490,7 +490,7 @@ register: remove_phys - name: Remove fc - aci_domain_to_encap_pool: + cisco.aci.aci_domain_to_encap_pool: <<: *aci_info domain_type: fc domain: fc_dom @@ -501,7 +501,7 @@ register: remove_fc - name: Remove l2dom - aci_domain_to_encap_pool: + cisco.aci.aci_domain_to_encap_pool: <<: *aci_info domain_type: l2dom domain: l2_dom @@ -512,7 +512,7 @@ register: remove_l2dom - name: Remove l3dom - aci_domain_to_encap_pool: + cisco.aci.aci_domain_to_encap_pool: <<: *aci_info domain_type: l3dom domain: l3_dom @@ -523,7 +523,7 @@ register: remove_l3dom - name: Remove vmm cloudfoundry - aci_domain_to_encap_pool: + cisco.aci.aci_domain_to_encap_pool: <<: *aci_info domain_type: vmm domain: vmm_dom @@ -535,7 +535,7 @@ register: remove_vmm_cloudfoundry - name: Remove vmm redhat kubernetes - aci_domain_to_encap_pool: + cisco.aci.aci_domain_to_encap_pool: <<: *aci_info domain_type: vmm domain: vmm_dom @@ -547,7 +547,7 @@ register: remove_vmm_kubernetes - name: Remove vmm microsoft - aci_domain_to_encap_pool: + cisco.aci.aci_domain_to_encap_pool: <<: *aci_info domain_type: vmm domain: vmm_dom @@ -559,7 +559,7 @@ register: remove_vmm_microsoft - name: Remove vmm redhat - aci_domain_to_encap_pool: + cisco.aci.aci_domain_to_encap_pool: <<: *aci_info domain_type: vmm domain: vmm_dom @@ -571,7 +571,7 @@ register: remove_vmm_redhat - name: Remove vmm openstack - aci_domain_to_encap_pool: + cisco.aci.aci_domain_to_encap_pool: <<: *aci_info domain_type: vmm domain: vmm_dom @@ -583,7 +583,7 @@ register: remove_vmm_openstack - name: Remove vmm openshift - aci_domain_to_encap_pool: + cisco.aci.aci_domain_to_encap_pool: <<: *aci_info domain_type: vmm domain: vmm_dom @@ -595,7 +595,7 @@ register: remove_vmm_openshift - name: Remove vmm vmware - aci_domain_to_encap_pool: + cisco.aci.aci_domain_to_encap_pool: <<: *aci_info domain_type: vmm domain: vmm_dom @@ -607,7 +607,7 @@ register: remove_vmm_vmware - name: Verify Remove for All Sites - assert: + ansible.builtin.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' @@ -616,7 +616,7 @@ - remove_vmm_kubernetes.previous.0.vmmDomP.children.0.infraRsVlanNs.attributes.tDn == 'uni/infra/vlanns-[test_pool]-dynamic' - name: Verify Remove for Non-Cloud Sites - assert: + ansible.builtin.assert: that: - remove_vmm_cloudfoundry.previous.0.vmmDomP.children.0.infraRsVlanNs.attributes.tDn == 'uni/infra/vlanns-[test_pool]-dynamic' - remove_vmm_microsoft.previous.0.vmmDomP.children.0.infraRsVlanNs.attributes.tDn == 'uni/infra/vlanns-[test_pool]-dynamic' @@ -627,7 +627,7 @@ # Clean Environment Again - name: Remove domains - aci_domain: + cisco.aci.aci_domain: <<: *aci_info domain: '{{ item.name }}' domain_type: '{{ item.type }}' @@ -639,7 +639,7 @@ - { name: l3_dom, type: l3dom } - name: Remove domains - aci_domain: + cisco.aci.aci_domain: <<: *aci_info domain: vmm_dom domain_type: vmm diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_domain_to_vlan_pool/tasks/main.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_domain_to_vlan_pool/tasks/main.yml index ab10856a8..e8c14fc55 100644 --- a/ansible_collections/cisco/aci/tests/integration/targets/aci_domain_to_vlan_pool/tasks/main.yml +++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_domain_to_vlan_pool/tasks/main.yml @@ -4,7 +4,7 @@ # GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) - name: Test that we have an ACI APIC host, ACI username and ACI password - fail: + ansible.builtin.fail: msg: 'Please define the following variables: aci_hostname, aci_username and aci_password.' when: aci_hostname is not defined or aci_username is not defined or aci_password is not defined @@ -20,7 +20,7 @@ output_level: '{{ aci_output_level | default("info") }}' - name: Verify Cloud and Non-Cloud Sites in use. - include_tasks: ../../../../../../integration/targets/aci_cloud_provider/tasks/main.yml + ansible.builtin.include_tasks: ../../../../../../integration/targets/aci_cloud_provider/tasks/main.yml - name: Execute tasks only for non-cloud sites when: query_cloud.current == [] # This condition will execute only non-cloud sites @@ -81,7 +81,7 @@ register: nm_add_binding - name: Verify add_binding - assert: + ansible.builtin.assert: that: - cm_add_binding is changed - nm_add_binding is changed @@ -105,7 +105,7 @@ register: nm_add_binding_again - name: Verify add_binding_again - assert: + ansible.builtin.assert: that: - cm_add_binding_again is not changed - nm_add_binding_again is not changed @@ -150,7 +150,7 @@ register: nm_vmm_type - name: Verify bindings with domain types - assert: + ansible.builtin.assert: that: - err_not_vmm_with_vm_provider is not changed - err_not_vmm_with_vm_provider.msg == "Domain type 'phys' cannot have a 'vm_provider'" @@ -182,7 +182,7 @@ register: nm_query_all_bindings - name: Verify query_all_bindings - assert: + ansible.builtin.assert: that: - cm_query_all_bindings is not changed - nm_query_all_bindings is not changed @@ -209,7 +209,7 @@ register: nm_query_binding - name: Verify query_binding - assert: + ansible.builtin.assert: that: - cm_query_binding is not changed - nm_query_binding is not changed @@ -231,7 +231,7 @@ register: nm_remove_binding - name: Verify remove_binding - assert: + ansible.builtin.assert: that: - cm_remove_binding is changed - nm_remove_binding is changed @@ -250,7 +250,7 @@ register: nm_remove_binding_again - name: Verify remove_binding_again - assert: + ansible.builtin.assert: that: - cm_remove_binding_again is not changed - nm_remove_binding_again is not changed @@ -275,7 +275,7 @@ register: nm_query_non_binding - name: Verify query_non_binding - assert: + ansible.builtin.assert: that: - cm_query_non_binding is not changed - nm_query_non_binding is not changed diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_encap_pool/tasks/main.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_encap_pool/tasks/main.yml index f0e61a7ef..4c5bd5578 100644 --- a/ansible_collections/cisco/aci/tests/integration/targets/aci_encap_pool/tasks/main.yml +++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_encap_pool/tasks/main.yml @@ -4,12 +4,12 @@ # GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) - name: test that we have an aci apic host, aci username and aci password - fail: + ansible.builtin.fail: msg: 'Please define the following variables: aci_hostname, aci_username and aci_password.' when: aci_hostname is not defined or aci_username is not defined or aci_password is not defined - name: Verify Cloud and Non-Cloud Sites in use. - include_tasks: ../../../../../../integration/targets/aci_cloud_provider/tasks/main.yml + ansible.builtin.include_tasks: ../../../../../../integration/targets/aci_cloud_provider/tasks/main.yml - name: Execute tasks only for non-cloud sites when: query_cloud.current == [] # This condition will execute only non-cloud sites diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_encap_pool/tasks/vlan.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_encap_pool/tasks/vlan.yml index 1354c149a..abfcda88f 100644 --- a/ansible_collections/cisco/aci/tests/integration/targets/aci_encap_pool/tasks/vlan.yml +++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_encap_pool/tasks/vlan.yml @@ -27,7 +27,7 @@ register: create_check_mode - name: assertion test - present - assert: + ansible.builtin.assert: that: - create_check_mode is changed - create_check_mode.sent.fvnsVlanInstP.attributes.allocMode == 'static' @@ -40,7 +40,7 @@ register: create_static - name: assertion test - present - assert: + ansible.builtin.assert: that: - create_static is changed - create_static.previous == [] @@ -54,7 +54,7 @@ register: create_dynamic - name: assertion test - present - assert: + ansible.builtin.assert: that: - create_dynamic is changed - create_dynamic.previous == [] @@ -69,7 +69,7 @@ register: idempotent_static - name: assertion test - present - assert: + ansible.builtin.assert: that: - idempotent_static is not changed - idempotent_static.previous.0.fvnsVlanInstP.attributes.allocMode == 'static' @@ -84,7 +84,7 @@ register: idempotent_dynamic - name: assertion test - present - assert: + ansible.builtin.assert: that: - idempotent_dynamic is not changed - idempotent_dynamic.previous.0.fvnsVlanInstP.attributes.allocMode == 'dynamic' @@ -100,7 +100,7 @@ register: update_static - name: assertion test - present - assert: + ansible.builtin.assert: that: - update_static is changed - update_static.sent.fvnsVlanInstP.attributes.descr == 'Ansible Test Change' @@ -112,7 +112,7 @@ register: update_dynamic - name: assertion test - present - assert: + ansible.builtin.assert: that: - update_dynamic is changed - update_dynamic.sent.fvnsVlanInstP.attributes.descr == 'Ansible Test Change' @@ -125,7 +125,7 @@ register: vlan_alloc_fail - name: assertion test - present - assert: + ansible.builtin.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'" @@ -138,7 +138,7 @@ register: vlan_pool_fail - name: assertion test - present - assert: + ansible.builtin.assert: that: - vlan_pool_fail is failed - 'vlan_pool_fail.msg == "state is present but all of the following are missing: pool"' @@ -151,7 +151,7 @@ register: vlan_pool_type_fail - name: assertion test - present - assert: + ansible.builtin.assert: that: - vlan_pool_type_fail is failed - 'vlan_pool_type_fail.msg == "missing required arguments: pool_type"' @@ -165,7 +165,7 @@ register: get_all_pools - name: assertion test - query - assert: + ansible.builtin.assert: that: - get_all_pools is not changed - get_all_pools.method == "GET" @@ -178,7 +178,7 @@ register: get_static_pool - name: assertion test - query - assert: + ansible.builtin.assert: that: - get_static_pool is not changed - get_static_pool.method == "GET" @@ -193,7 +193,7 @@ register: get_dynamic_pool - name: assertion test - query - assert: + ansible.builtin.assert: that: - get_dynamic_pool is not changed - get_dynamic_pool.method == "GET" @@ -210,7 +210,7 @@ register: vlan_query_pool_type_fail - name: assertion test - query - assert: + ansible.builtin.assert: that: - vlan_query_pool_type_fail is failed - 'vlan_query_pool_type_fail.msg == "missing required arguments: pool_type"' @@ -221,7 +221,7 @@ register: delete_static - name: assertion test - absent - assert: + ansible.builtin.assert: that: - delete_static is changed - delete_static.method == "DELETE" @@ -235,7 +235,7 @@ register: delete_check_mode - name: assertion test - absent - assert: + ansible.builtin.assert: that: - delete_check_mode is changed @@ -245,7 +245,7 @@ register: delete_dynamic - name: assertion test - absent - assert: + ansible.builtin.assert: that: - delete_dynamic is changed - delete_dynamic.method == "DELETE" @@ -258,7 +258,7 @@ register: idempotent_delete_static - name: assertion test - absent - assert: + ansible.builtin.assert: that: - idempotent_delete_static is not changed - idempotent_delete_static.previous == [] @@ -269,7 +269,7 @@ register: idempotent_delete_dynamic - name: assertion test - absent - assert: + ansible.builtin.assert: that: - idempotent_delete_dynamic is not changed - idempotent_delete_dynamic.previous == [] diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_encap_pool/tasks/vxlan.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_encap_pool/tasks/vxlan.yml index 6467af376..35b211233 100644 --- a/ansible_collections/cisco/aci/tests/integration/targets/aci_encap_pool/tasks/vxlan.yml +++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_encap_pool/tasks/vxlan.yml @@ -31,7 +31,7 @@ register: create_vxlan_check_mode - name: assertion test - present - assert: + ansible.builtin.assert: that: - create_vxlan_check_mode is changed - create_vxlan_check_mode.sent.fvnsVxlanInstP.attributes.descr == 'Ansible Test' @@ -43,7 +43,7 @@ register: create_vxlan - name: assertion test - present - assert: + ansible.builtin.assert: that: - create_vxlan is changed - create_vxlan.previous == [] @@ -56,7 +56,7 @@ register: idempotent_vxlan - name: assertion test - present - assert: + ansible.builtin.assert: that: - idempotent_vxlan is not changed - idempotent_vxlan.previous.0.fvnsVxlanInstP.attributes.name == 'anstest' @@ -69,7 +69,7 @@ register: update_vxlan - name: assertion test - present - assert: + ansible.builtin.assert: that: - update_vxlan is changed - update_vxlan.sent.fvnsVxlanInstP.attributes.descr == 'Ansible Test Change' @@ -81,7 +81,7 @@ register: create_vxlan_2 - name: assertion test - present - assert: + ansible.builtin.assert: that: - create_vxlan_2 is changed @@ -94,7 +94,7 @@ register: create_vxlan_alloc_mode - name: assertion test - present - assert: + ansible.builtin.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'" @@ -106,7 +106,7 @@ register: query_vxlan - name: assertion test - query - assert: + ansible.builtin.assert: that: - query_vxlan is not changed - query_vxlan.current | length == 1 @@ -119,7 +119,7 @@ register: query_vxlan_all - name: assertion test - query - assert: + ansible.builtin.assert: that: - query_vxlan_all is not changed - query_vxlan_all.current | length > 1 @@ -132,7 +132,7 @@ register: delete_vxlan_check_mode - name: assertion test - absent - assert: + ansible.builtin.assert: that: - delete_vxlan_check_mode is changed - delete_vxlan_check_mode.previous != [] @@ -143,7 +143,7 @@ register: delete_vxlan - name: assertion test - absent - assert: + ansible.builtin.assert: that: - delete_vxlan is changed - delete_vxlan.previous == delete_vxlan_check_mode.previous @@ -162,7 +162,7 @@ register: delete_vxlan_pool_fail - name: assertion test - absent - assert: + ansible.builtin.assert: that: - delete_vxlan_idempotent is not changed - delete_vxlan_idempotent.previous == [] @@ -173,7 +173,7 @@ pool: anstest_2 - name: assertion test - absent - assert: + ansible.builtin.assert: that: - delete_vxlan_pool_fail is failed - 'delete_vxlan_pool_fail.msg == "state is absent but all of the following are missing: pool"' diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_encap_pool_range/tasks/main.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_encap_pool_range/tasks/main.yml index 005628c5d..1b4c1a942 100644 --- a/ansible_collections/cisco/aci/tests/integration/targets/aci_encap_pool_range/tasks/main.yml +++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_encap_pool_range/tasks/main.yml @@ -4,12 +4,12 @@ # GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) - name: test that we have an aci apic host, aci username and aci password - fail: + ansible.builtin.fail: msg: 'Please define the following variables: aci_hostname, aci_username and aci_password.' when: aci_hostname is not defined or aci_username is not defined or aci_password is not defined - name: Verify Cloud and Non-Cloud Sites in use. - include_tasks: ../../../../../../integration/targets/aci_cloud_provider/tasks/main.yml + ansible.builtin.include_tasks: ../../../../../../integration/targets/aci_cloud_provider/tasks/main.yml - name: Execute tasks only for non-cloud sites when: query_cloud.current == [] # This condition will execute only non-cloud sites diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_encap_pool_range/tasks/vlan.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_encap_pool_range/tasks/vlan.yml index 6af58bf5d..e82623a3c 100644 --- a/ansible_collections/cisco/aci/tests/integration/targets/aci_encap_pool_range/tasks/vlan.yml +++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_encap_pool_range/tasks/vlan.yml @@ -43,7 +43,7 @@ register: range_present_check_mode - name: present assertions - assert: + ansible.builtin.assert: that: - range_present_check_mode is changed - range_present_check_mode.sent.fvnsEncapBlk.attributes.allocMode == 'inherit' @@ -58,7 +58,7 @@ register: range_present - name: present assertions - assert: + ansible.builtin.assert: that: - range_present is changed - range_present.previous == [] @@ -72,7 +72,7 @@ register: range_present_idempotent - name: present assertions - assert: + ansible.builtin.assert: that: - range_present_idempotent is not changed - range_present_idempotent.previous.0.fvnsEncapBlk.attributes.name == "anstest" @@ -85,7 +85,7 @@ register: range_present_update - name: present assertions - assert: + ansible.builtin.assert: that: - range_present_update is changed - range_present_update.previous != [] @@ -100,7 +100,7 @@ register: range_present_2 - name: present assertions - assert: + ansible.builtin.assert: that: - range_present_2 is changed - range_present_2.previous == [] @@ -113,7 +113,7 @@ register: range_start_low - name: present assertions - assert: + ansible.builtin.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' @@ -126,7 +126,7 @@ register: range_start_high - name: present assertions - assert: + ansible.builtin.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' @@ -139,7 +139,7 @@ register: range_end_low - name: present assertions - assert: + ansible.builtin.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' @@ -152,7 +152,7 @@ register: range_end_high - name: present assertions - assert: + ansible.builtin.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' @@ -165,7 +165,7 @@ register: range_start_end - name: present assertions - assert: + ansible.builtin.assert: that: - range_start_end is failed - range_start_end.msg == 'The "range_start" must be less than or equal to the "range_end"' @@ -178,7 +178,7 @@ register: range_present_pool_type - name: present assertions - assert: + ansible.builtin.assert: that: - range_present_pool_type is failed - "range_present_pool_type.msg == 'missing required arguments: pool_type'" @@ -190,7 +190,7 @@ register: range_present_missing_param - name: present assertions - assert: + ansible.builtin.assert: that: - range_present_missing_param is failed - "range_present_missing_param.msg == 'state is present but all of the following are missing: range_end, range_start'" @@ -203,7 +203,7 @@ register: range_present_allocation - name: present assertions - assert: + ansible.builtin.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' @@ -215,7 +215,7 @@ register: range_query - name: query assertions - assert: + ansible.builtin.assert: that: - range_query is not changed - range_query.url.endswith("infra/vlanns-[anstest]-static/from-[vlan-20]-to-[vlan-40].json") @@ -229,7 +229,7 @@ register: range_query_from_to_name - name: query assertions - assert: + ansible.builtin.assert: that: - range_query_from_to_name is not changed - range_query_from_to_name.url.endswith("class/fvnsEncapBlk.json") @@ -247,7 +247,7 @@ register: range_query_from_name - name: query assertions - assert: + ansible.builtin.assert: that: - range_query_from_name is not changed - range_query_from_name.url.endswith("class/fvnsEncapBlk.json") @@ -263,7 +263,7 @@ register: range_query_to_name - name: query assertions - assert: + ansible.builtin.assert: that: - range_query_to_name is not changed - range_query_to_name.url.endswith('class/fvnsEncapBlk.json') @@ -280,7 +280,7 @@ register: range_query_name - name: query assertions - assert: + ansible.builtin.assert: that: - range_query_name is not changed - range_query_name.url.endswith("class/fvnsEncapBlk.json") @@ -294,7 +294,7 @@ register: range_query_from_to - name: query assertions - assert: + ansible.builtin.assert: that: - range_query_from_to is not changed - range_query_from_to.url.endswith("class/fvnsEncapBlk.json") @@ -311,7 +311,7 @@ register: range_query_pool - name: query assertions - assert: + ansible.builtin.assert: that: - range_query_pool.current | length == 1 - range_query_pool.current.0.fvnsVlanInstP.attributes.name == "anstest" @@ -326,7 +326,7 @@ register: range_query_all - name: query assertions - assert: + ansible.builtin.assert: that: - range_query_all is not changed - range_query_all.current | length > 1 @@ -340,7 +340,7 @@ register: delete_range - name: absent assertions - assert: + ansible.builtin.assert: that: - delete_range is changed - delete_range.proposed == {} @@ -354,7 +354,7 @@ register: delete_check_mode - name: absent assertions - assert: + ansible.builtin.assert: that: - delete_check_mode is changed - delete_check_mode.previous != [] @@ -365,7 +365,7 @@ register: delete_range_2 - name: absent assertions - assert: + ansible.builtin.assert: that: - delete_range_2 is changed - delete_range_2.previous == delete_check_mode.previous @@ -376,7 +376,7 @@ register: delete_idempotent - name: absent assertions - assert: + ansible.builtin.assert: that: - delete_idempotent is not changed - delete_idempotent.previous == [] diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_epg/tasks/main.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_epg/tasks/main.yml index ffd3ac599..82587ec93 100644 --- a/ansible_collections/cisco/aci/tests/integration/targets/aci_epg/tasks/main.yml +++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_epg/tasks/main.yml @@ -1,22 +1,20 @@ # Test code for the ACI modules # Copyright: (c) 2017, Jacob McGill (@jmcgill298) # Copyright: (c) 2020, Shreyas Srish (@shrsr) +# Copyright: (c) 2023, Christian Kolrep (@Christian-Kolrep) +# Copyright: (c) 2024, Akini Ross (@akinross) +# Copyright: (c) 2024, Samita Bhattacharjee (@samiib) # GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) - name: Test that we have an ACI APIC host, ACI username and ACI password - fail: + ansible.builtin.fail: msg: 'Please define the following variables: aci_hostname, aci_username and aci_password.' when: aci_hostname is not defined or aci_username is not defined or aci_password is not defined -- name: Verify Cloud and Non-Cloud Sites in use. - include_tasks: ../../../../../../integration/targets/aci_cloud_provider/tasks/main.yml - -- name: Execute tasks only for non-cloud sites - when: query_cloud.current == [] # This condition will execute only non-cloud sites - block: # block specifies execution of tasks within, based on conditions - - name: ensure tenant exists for tests to kick off - cisco.aci.aci_tenant: &aci_tenant_present +- name: Set vars + ansible.builtin.set_fact: + aci_info: &aci_info host: "{{ aci_hostname }}" username: "{{ aci_username }}" password: "{{ aci_password }}" @@ -24,35 +22,57 @@ use_ssl: '{{ aci_use_ssl | default(true) }}' use_proxy: '{{ aci_use_proxy | default(true) }}' output_level: debug + +- name: Verify Cloud and Non-Cloud Sites in use. + ansible.builtin.include_tasks: ../../../../../../integration/targets/aci_cloud_provider/tasks/main.yml + +- name: Execute tasks only for non-cloud sites + when: query_cloud.current == [] # This condition will execute only non-cloud sites + block: # block specifies execution of tasks within, based on conditions + - name: Ensure tenant exists for tests to kick off + cisco.aci.aci_tenant: &aci_tenant_present + <<: *aci_info state: present tenant: ansible_test register: tenant_present - - name: ensure monitoring policy exists + - 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 + <<: *aci_info monitoring_policy: check tenant: ansible_test - - name: ensure bd exists for tests to kick off + - 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 + - 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 + - name: Ensure epg anstest dont exist for tests to kick off + cisco.aci.aci_epg: + <<: *aci_ap_present + epg: anstest + state: absent + + - name: Ensure epg anstest2 dont exist for tests to kick off + cisco.aci.aci_epg: + <<: *aci_ap_present + epg: anstest2 + state: absent + + - name: Ensure epg anstest_useg_epg dont exist for tests to kick off + cisco.aci.aci_epg: + <<: *aci_ap_present + epg: anstest_useg_epg + state: absent + + - name: Create epg - check mode works cisco.aci.aci_epg: &aci_epg_present <<: *aci_ap_present epg: anstest @@ -63,36 +83,36 @@ check_mode: true register: epg_present_check_mode - - name: create epg - creation works + - name: Create epg - creation works cisco.aci.aci_epg: <<: *aci_epg_present register: epg_present - - name: create epg - idempotency works + - name: Create epg - idempotency works cisco.aci.aci_epg: <<: *aci_epg_present register: epg_present_idempotent - - name: update epg - update works + - 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 + - name: Create epg - missing param cisco.aci.aci_epg: <<: *aci_epg_present ap: "{{ fakevar | default(omit) }}" ignore_errors: true register: epg_present_missing_param - - name: create epg - used for query + - name: Create epg - used for query cisco.aci.aci_epg: <<: *aci_epg_present epg: anstest2 - - name: present assertions - assert: + - name: Create and Update assertions + ansible.builtin.assert: that: - epg_present_check_mode is changed - epg_present_check_mode.previous == [] @@ -110,21 +130,90 @@ - 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 + # TEST NO VERIFICATION + - name: create epg with no verification (check mode) + cisco.aci.aci_epg: &aci_epg_no_verify + <<: *aci_epg_present + epg: anstest-no-verify + no_verification: true + check_mode: true + register: epg_present_no_verify_cm + + - name: create epg with no verification + cisco.aci.aci_epg: + <<: *aci_epg_no_verify + register: epg_present_no_verify + + - name: create epg with no verification again + cisco.aci.aci_epg: + <<: *aci_epg_no_verify + register: epg_present_no_verify_again + + - name: update epg with no verification + cisco.aci.aci_epg: + <<: *aci_epg_no_verify + description: Ansible Test No Verify + register: update_epg_present_no_verify + + - name: delete epg with no verification + cisco.aci.aci_epg: + <<: *aci_epg_no_verify + state: absent + register: delete_epg_present_no_verify + + - name: delete epg with no verification again + cisco.aci.aci_epg: + <<: *aci_epg_no_verify + state: absent + register: delete_epg_present_no_verify_again + + - name: no verification asserts + ansible.builtin.assert: + that: + - epg_present_no_verify_cm is changed + - epg_present_no_verify_cm.current_verified == false + - epg_present_no_verify_cm.current.0 == epg_present_no_verify_cm.proposed + - epg_present_no_verify is changed + - epg_present_no_verify.current_verified == false + - epg_present_no_verify.current.0 == epg_present_no_verify.proposed + - epg_present_no_verify.previous == [] + - epg_present_no_verify_again is not changed + - epg_present_no_verify_again.current_verified == true + - epg_present_no_verify_again.current.0.fvAEPg.attributes.name == "anstest-no-verify" + - epg_present_no_verify_again.current.0.fvAEPg.attributes.descr == "Ansible Test" + - epg_present_no_verify_again.previous.0.fvAEPg.attributes.name == "anstest-no-verify" + - epg_present_no_verify_again.previous.0.fvAEPg.attributes.descr == "Ansible Test" + - update_epg_present_no_verify is changed + - update_epg_present_no_verify.current_verified == false + - update_epg_present_no_verify.current.0 == update_epg_present_no_verify.proposed + - update_epg_present_no_verify.previous.0.fvAEPg.attributes.name == "anstest-no-verify" + - update_epg_present_no_verify.previous.0.fvAEPg.attributes.descr == "Ansible Test" + - delete_epg_present_no_verify is changed + - delete_epg_present_no_verify.current_verified == false + - delete_epg_present_no_verify.current.0 == delete_epg_present_no_verify.proposed + - delete_epg_present_no_verify.previous.0.fvAEPg.attributes.name == "anstest-no-verify" + - delete_epg_present_no_verify.previous.0.fvAEPg.attributes.descr == "Ansible Test No Verify" + - delete_epg_present_no_verify_again is not changed + - delete_epg_present_no_verify_again.current_verified == true + - delete_epg_present_no_verify_again.current == [] + - delete_epg_present_no_verify_again.previous == [] + - delete_epg_present_no_verify_again.proposed == {} + + - name: Query specific epg cisco.aci.aci_epg: <<: *aci_epg_present state: query register: epg_query - - name: get all epgs + - name: Query all epgs cisco.aci.aci_epg: <<: *aci_tenant_present state: query tenant: "{{ fakevar | default(omit) }}" register: epg_query_all - - name: query assertions - assert: + - name: Query assertions + ansible.builtin.assert: that: - epg_query is not changed - epg_query.current | length == 1 @@ -134,40 +223,40 @@ - '"tn-ansible_test/ap-anstest/epg-anstest.json" in epg_query.url' - epg_query_all is not changed - epg_query_all.current | length > 1 - - '"?rsp-subtree=full&rsp-subtree-class=fvRsAEPgMonPol,fvRsBd" in epg_query_all.filter_string' + - '"?rsp-subtree=full&rsp-subtree-class=fvCrtrn,fvRsAEPgMonPol,fvRsBd" in epg_query_all.filter_string' - '"class/fvAEPg.json" in epg_query_all.url' - - name: delete epg - check mode works + - name: Delete epg - check mode works cisco.aci.aci_epg: &aci_epg_absent <<: *aci_epg_present state: absent check_mode: true register: delete_epg_check_mode - - name: delete epg - delete works + - name: Delete epg - delete works cisco.aci.aci_epg: <<: *aci_epg_absent register: delete_epg - - name: delete epg - idempotency works + - name: Delete epg - idempotency works cisco.aci.aci_epg: <<: *aci_epg_absent register: delete_epg_idempotent - - name: delete epg - cleanup extra epg + - name: Delete epg - cleanup extra epg cisco.aci.aci_epg: <<: *aci_epg_absent epg: anstest2 - - name: delete epg - missing param fails + - name: Delete epg - missing param fails cisco.aci.aci_epg: <<: *aci_epg_absent tenant: "{{ fakevar | default(omit) }}" ignore_errors: true register: delete_epg_missing_param - - name: query assertions - assert: + - name: Delete assertions + ansible.builtin.assert: that: - delete_epg_check_mode is changed - delete_epg_check_mode.previous != [] @@ -178,7 +267,9 @@ - delete_epg_missing_param is failed - 'delete_epg_missing_param.msg == "state is absent but all of the following are missing: tenant"' - - name: create microsegmented epg with check mode + # USEG SPECIFIC TESTS + + - name: Create useg epg (check mode) cisco.aci.aci_epg: &cm_useg_epg_present <<: *aci_ap_present epg: anstest_useg_epg @@ -188,129 +279,137 @@ check_mode: true register: cm_useg_epg_present - - name: Assertions check for create microsegmented epg with check mode - assert: - that: - - cm_useg_epg_present is changed - - cm_useg_epg_present.current == [] - - cm_useg_epg_present.previous == [] - - cm_useg_epg_present.sent.fvAEPg.attributes.name == 'anstest_useg_epg' - - cm_useg_epg_present.sent.fvAEPg.attributes.isAttrBasedEPg == 'yes' - - cm_useg_epg_present.sent.fvAEPg.children.0.fvRsBd.attributes.tnFvBDName == 'anstest' - - - name: create microsegmented epg with normal mode + - name: Create useg epg (normal mode) cisco.aci.aci_epg: &nm_useg_epg_present <<: *cm_useg_epg_present register: nm_useg_epg_present - - name: Assertions check for create microsegmented epg with normal mode - assert: + - name: Create useg epg again + cisco.aci.aci_epg: + <<: *cm_useg_epg_present + register: nm_useg_epg_present_again + + - name: Assertions for creating useg epgs + ansible.builtin.assert: that: + - cm_useg_epg_present is changed + - cm_useg_epg_present.current == [] + - cm_useg_epg_present.previous == [] + - cm_useg_epg_present.proposed.fvAEPg.attributes.name == 'anstest_useg_epg' + - cm_useg_epg_present.proposed.fvAEPg.attributes.isAttrBasedEPg == 'yes' + - cm_useg_epg_present.proposed.fvAEPg.children.1.fvCrtrn.attributes.name == 'default' + - cm_useg_epg_present.proposed.fvAEPg.children.0.fvRsBd.attributes.tnFvBDName == 'anstest' - nm_useg_epg_present is changed - nm_useg_epg_present.current | length == 1 - nm_useg_epg_present.previous == [] - nm_useg_epg_present.current.0.fvAEPg.attributes.name == 'anstest_useg_epg' - nm_useg_epg_present.current.0.fvAEPg.attributes.isAttrBasedEPg == 'yes' - - nm_useg_epg_present.current.0.fvAEPg.children.0.fvRsBd.attributes.tnFvBDName == 'anstest' - - nm_useg_epg_present.sent.fvAEPg.attributes.name == 'anstest_useg_epg' - - nm_useg_epg_present.sent.fvAEPg.attributes.isAttrBasedEPg == 'yes' - - nm_useg_epg_present.sent.fvAEPg.children.0.fvRsBd.attributes.tnFvBDName == 'anstest' - - - name: create microsegmented epg with normal mode - idempotency works - cisco.aci.aci_epg: - <<: *cm_useg_epg_present - register: idempotency_nm_useg_epg_present - - - name: Idempotency assertions check for create microsegmented epg with normal mode - assert: - that: - - idempotency_nm_useg_epg_present is not changed - - idempotency_nm_useg_epg_present.current | length == 1 - - idempotency_nm_useg_epg_present.previous | length == 1 - - idempotency_nm_useg_epg_present.current.0.fvAEPg.attributes.name == 'anstest_useg_epg' - - idempotency_nm_useg_epg_present.previous.0.fvAEPg.attributes.name == 'anstest_useg_epg' - - idempotency_nm_useg_epg_present.current.0.fvAEPg.attributes.isAttrBasedEPg == 'yes' - - idempotency_nm_useg_epg_present.previous.0.fvAEPg.attributes.isAttrBasedEPg == 'yes' - - idempotency_nm_useg_epg_present.current.0.fvAEPg.children.0.fvRsBd.attributes.tnFvBDName == 'anstest' - - idempotency_nm_useg_epg_present.previous.0.fvAEPg.children.0.fvRsBd.attributes.tnFvBDName == 'anstest' - - - name: get anstest_useg_epg epg + - nm_useg_epg_present.current.0.fvAEPg.children.0.fvCrtrn.attributes.name == 'default' + - nm_useg_epg_present.current.0.fvAEPg.children.1.fvRsBd.attributes.tnFvBDName == 'anstest' + - nm_useg_epg_present_again is not changed + - nm_useg_epg_present_again.previous | length == 1 + - nm_useg_epg_present_again.previous.0.fvAEPg.attributes.name == 'anstest_useg_epg' + - nm_useg_epg_present_again.previous.0.fvAEPg.children.0.fvCrtrn.attributes.name == 'default' + - nm_useg_epg_present_again.previous.0.fvAEPg.children.1.fvRsBd.attributes.tnFvBDName == 'anstest' + - nm_useg_epg_present_again.previous.0.fvAEPg.attributes.isAttrBasedEPg == 'yes' + - nm_useg_epg_present_again.current | length == 1 + - nm_useg_epg_present_again.current.0.fvAEPg.attributes.name == 'anstest_useg_epg' + - nm_useg_epg_present_again.current.0.fvAEPg.children.0.fvCrtrn.attributes.name == 'default' + - nm_useg_epg_present_again.current.0.fvAEPg.children.1.fvRsBd.attributes.tnFvBDName == 'anstest' + - nm_useg_epg_present_again.current.0.fvAEPg.attributes.isAttrBasedEPg == 'yes' + + - name: Query useg epg cisco.aci.aci_epg: <<: *nm_useg_epg_present state: query register: useg_epg_present - - name: Assertions check for query microsegmented epg with normal mode - assert: + - name: Assertions check for query useg epg + ansible.builtin.assert: that: - useg_epg_present is not changed - useg_epg_present.current | length == 1 - useg_epg_present.current.0.fvAEPg.attributes.name == 'anstest_useg_epg' - useg_epg_present.current.0.fvAEPg.attributes.isAttrBasedEPg == 'yes' - - useg_epg_present.current.0.fvAEPg.children.0.fvRsBd.attributes.tnFvBDName == 'anstest' + - useg_epg_present.current.0.fvAEPg.children.0.fvCrtrn.attributes.name == 'default' + - useg_epg_present.current.0.fvAEPg.children.1.fvRsBd.attributes.tnFvBDName == 'anstest' + + - name: Update useg epg + cisco.aci.aci_epg: + <<: *cm_useg_epg_present + match: all + precedence: 1 + register: nm_useg_epg_update + + - name: Update useg epg (error) + cisco.aci.aci_epg: + <<: *cm_useg_epg_present + useg: no + ignore_errors: true + register: err_useg_epg_update - - name: delete microsegmented epg with check mode + - name: Assertions check for update useg epg + assert: + that: + - nm_useg_epg_update is changed + - nm_useg_epg_update.previous | length == 1 + - nm_useg_epg_update.previous.0.fvAEPg.children.0.fvCrtrn.attributes.name == 'default' + - nm_useg_epg_update.previous.0.fvAEPg.children.0.fvCrtrn.attributes.prec == '0' + - nm_useg_epg_update.previous.0.fvAEPg.children.0.fvCrtrn.attributes.match == 'any' + - nm_useg_epg_update.previous.0.fvAEPg.children.1.fvRsBd.attributes.tnFvBDName == 'anstest' + - nm_useg_epg_update.current.0.fvAEPg.attributes == nm_useg_epg_update.previous.0.fvAEPg.attributes + - nm_useg_epg_update.current | length == 1 + - nm_useg_epg_update.current.0.fvAEPg.children.0.fvCrtrn.attributes.name == 'default' + - nm_useg_epg_update.current.0.fvAEPg.children.0.fvCrtrn.attributes.prec == '1' + - nm_useg_epg_update.current.0.fvAEPg.children.0.fvCrtrn.attributes.match == 'all' + - nm_useg_epg_update.current.0.fvAEPg.children.1.fvRsBd.attributes.tnFvBDName == 'anstest' + - err_useg_epg_update is failed + - 'err_useg_epg_update.msg == "Changing attribute useg on existing EPG is not supported."' + + - name: Delete useg epg with (check mode) cisco.aci.aci_epg: &cm_useg_epg_absent <<: *nm_useg_epg_present state: absent check_mode: true register: cm_useg_epg_absent - - name: Assertions check for delete microsegmented epg with check mode - assert: + - name: Delete useg epg + cisco.aci.aci_epg: + <<: *cm_useg_epg_absent + register: nm_useg_epg_absent + + - name: Delete useg epg again + cisco.aci.aci_epg: + <<: *cm_useg_epg_absent + register: nm_useg_epg_absent_again + + - name: Assertions check for delete useg epg with check mode + ansible.builtin.assert: that: - cm_useg_epg_absent is changed - - cm_useg_epg_absent.current | length == 1 - cm_useg_epg_absent.previous | length == 1 - - cm_useg_epg_absent.current.0.fvAEPg.attributes.name == 'anstest_useg_epg' - - cm_useg_epg_absent.current.0.fvAEPg.attributes.isAttrBasedEPg == 'yes' - - cm_useg_epg_absent.current.0.fvAEPg.children.0.fvRsBd.attributes.tnFvBDName == 'anstest' - cm_useg_epg_absent.previous.0.fvAEPg.attributes.name == 'anstest_useg_epg' - cm_useg_epg_absent.previous.0.fvAEPg.attributes.isAttrBasedEPg == 'yes' - - cm_useg_epg_absent.previous.0.fvAEPg.children.0.fvRsBd.attributes.tnFvBDName == 'anstest' - - - name: delete microsegmented epg with normal mode - cisco.aci.aci_epg: &nm_useg_epg_absent - <<: *cm_useg_epg_absent - state: absent - register: nm_useg_epg_absent - - - name: Assertions check for delete microsegmented epg with normal mode - assert: - that: + - cm_useg_epg_absent.previous.0.fvAEPg.children.0.fvCrtrn.attributes.name == 'default' + - cm_useg_epg_absent.previous.0.fvAEPg.children.1.fvRsBd.attributes.tnFvBDName == 'anstest' + - cm_useg_epg_absent.current | length == 1 + - cm_useg_epg_absent.current.0.fvAEPg.attributes.name == 'anstest_useg_epg' + - cm_useg_epg_absent.current.0.fvAEPg.attributes.isAttrBasedEPg == 'yes' + - cm_useg_epg_absent.current.0.fvAEPg.children.0.fvCrtrn.attributes.name == 'default' + - cm_useg_epg_absent.current.0.fvAEPg.children.1.fvRsBd.attributes.tnFvBDName == 'anstest' + - cm_useg_epg_absent.proposed == {} - nm_useg_epg_absent is changed - - nm_useg_epg_absent.current | length == 0 + - nm_useg_epg_absent.current == [] - nm_useg_epg_absent.previous | length == 1 - nm_useg_epg_absent.previous.0.fvAEPg.attributes.name == 'anstest_useg_epg' - nm_useg_epg_absent.previous.0.fvAEPg.attributes.isAttrBasedEPg == 'yes' - - nm_useg_epg_absent.previous.0.fvAEPg.children.0.fvRsBd.attributes.tnFvBDName == 'anstest' - - - name: delete microsegmented epg with normal mode - idempotency works - cisco.aci.aci_epg: - <<: *nm_useg_epg_absent - register: idempotency_nm_useg_epg_absent - - - name: Idempotency assertions check for delete microsegmented epg with normal mode - assert: - that: - - idempotency_nm_useg_epg_absent is not changed - - idempotency_nm_useg_epg_absent.current | length == 0 - - idempotency_nm_useg_epg_absent.previous | length == 0 - - - name: cleanup bd - cisco.aci.aci_bd: - <<: *aci_bd_present - state: absent - when: bd_present.previous == [] - - - name: cleanup ap - cisco.aci.aci_ap: - <<: *aci_ap_present - state: absent - when: ap_present.previous == [] + - nm_useg_epg_absent.previous.0.fvAEPg.children.0.fvCrtrn.attributes.name == 'default' + - nm_useg_epg_absent.previous.0.fvAEPg.children.1.fvRsBd.attributes.tnFvBDName == 'anstest' + - nm_useg_epg_absent_again is not changed + - nm_useg_epg_absent_again.current == [] + - nm_useg_epg_absent_again.previous == [] - - name: cleanup tenant + - name: Cleanup tenant cisco.aci.aci_tenant: <<: *aci_tenant_present state: absent - when: tenant_present.previous == [] diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_epg_monitoring_policy/tasks/main.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_epg_monitoring_policy/tasks/main.yml index 1671e252e..dbcf8ed18 100644 --- a/ansible_collections/cisco/aci/tests/integration/targets/aci_epg_monitoring_policy/tasks/main.yml +++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_epg_monitoring_policy/tasks/main.yml @@ -18,7 +18,7 @@ use_ssl: '{{ aci_use_ssl | default(true) }}' use_proxy: '{{ aci_use_proxy | default(true) }}' output_level: '{{ aci_output_level | default("info") }}' - aci_tenant: ansible_test + cisco.aci.aci_tenant: ansible_test - name: Verify Cloud and Non-Cloud Sites in use. ansible.builtin.include_tasks: ../../../../../../integration/targets/aci_cloud_provider/tasks/main.yml diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_epg_subnet/tasks/main.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_epg_subnet/tasks/main.yml index 07fb1d304..ae194bb89 100644 --- a/ansible_collections/cisco/aci/tests/integration/targets/aci_epg_subnet/tasks/main.yml +++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_epg_subnet/tasks/main.yml @@ -5,12 +5,12 @@ # GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) - name: Test that we have an ACI APIC host, ACI username and ACI password - fail: + ansible.builtin.fail: msg: 'Please define the following variables: aci_hostname, aci_username and aci_password.' when: aci_hostname is not defined or aci_username is not defined or aci_password is not defined - name: Set vars - set_fact: + ansible.builtin.set_fact: aci_info: &aci_info host: "{{ aci_hostname }}" username: "{{ aci_username }}" @@ -21,14 +21,14 @@ output_level: debug - name: Query system information - aci_system: + cisco.aci.aci_system: <<: *aci_info id: 1 state: query register: version - name: Verify Cloud and Non-Cloud Sites in use. - include_tasks: ../../../../../../integration/targets/aci_cloud_provider/tasks/main.yml + ansible.builtin.include_tasks: ../../../../../../integration/targets/aci_cloud_provider/tasks/main.yml - name: ensure tenant does not exists cisco.aci.aci_tenant: &aci_tenant_absent @@ -138,7 +138,7 @@ ignore_errors: true - name: asserts for subnet creation tasks - assert: + ansible.builtin.assert: that: - create_check_mode is changed - create_check_mode.sent.fvSubnet.attributes.descr == create_subnet.sent.fvSubnet.attributes.descr == 'Ansible Test' @@ -155,7 +155,7 @@ - create_wrong_mask.msg == "Valid Subnet Masks are 0 to 32 for IPv4 Addresses and 0 to 128 for IPv6 addresses" - name: assert for subnet IpDPlearning tasks version >=5 - assert: + ansible.builtin.assert: that: - create_subnet2_5 is changed - create_subnet2_5.current.0.fvSubnet.attributes.ctrl == 'no-default-gateway' @@ -170,7 +170,7 @@ when: version.current.0.topSystem.attributes.version is version('5', '>=') - name: assert for subnet IpDPlearning tasks version < 5 - assert: + ansible.builtin.assert: that: - create_subnet2 is changed - create_subnet2.current.0.fvSubnet.attributes.ctrl == 'no-default-gateway' @@ -204,7 +204,7 @@ register: get_subnets_gateway - name: asserts for query tasks - assert: + ansible.builtin.assert: that: - get_all_epg is not changed - '"rsp-subtree-class=fvRsBDSubnetToProfile,fvRsNdPfxPol,fvSubnet" in get_all_epg.filter_string' @@ -241,7 +241,7 @@ register: delete_idempotency - name: asserts for deletion task - assert: + ansible.builtin.assert: that: - delete_check_mode is changed - delete_check_mode.proposed == {} diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_epg_to_contract/tasks/main.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_epg_to_contract/tasks/main.yml index ec97334ab..f7213c1e6 100644 --- a/ansible_collections/cisco/aci/tests/integration/targets/aci_epg_to_contract/tasks/main.yml +++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_epg_to_contract/tasks/main.yml @@ -1,15 +1,16 @@ # Test code for the ACI modules # Copyright: (c) 2017, Jacob McGill (@jmcgill298) +# Copyright: (c) 2023, Akini Ross (@akinross) # GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) - name: Test that we have an ACI APIC host, ACI username and ACI password - fail: + ansible.builtin.fail: msg: 'Please define the following variables: aci_hostname, aci_username and aci_password.' when: aci_hostname is not defined or aci_username is not defined or aci_password is not defined - name: Verify Cloud and Non-Cloud Sites in use. - include_tasks: ../../../../../../integration/targets/aci_cloud_provider/tasks/main.yml + ansible.builtin.include_tasks: ../../../../../../integration/targets/aci_cloud_provider/tasks/main.yml - name: Ensure contract binding does not exist prior to testing cisco.aci.aci_epg_to_contract: @@ -30,8 +31,8 @@ - name: Execute tasks only for non-cloud sites when: query_cloud.current == [] # This condition will execute only non-cloud sites block: # block specifies execution of tasks within, based on conditions - - name: ensure tenant exists for tests to kick off - cisco.aci.aci_tenant: &aci_tenant_present + - name: remove tenant for tests to kick off + cisco.aci.aci_tenant: &aci_tenant_absent host: "{{ aci_hostname }}" username: "{{ aci_username }}" password: "{{ aci_password }}" @@ -40,6 +41,12 @@ use_proxy: '{{ aci_use_proxy | default(true) }}' output_level: debug tenant: ansible_test + state: absent + register: tenant_present + + - name: ensure tenant exists for tests to kick off + cisco.aci.aci_tenant: &aci_tenant_present + <<: *aci_tenant_absent state: present register: tenant_present @@ -118,7 +125,7 @@ register: incompatible_present - name: present assertions - assert: + ansible.builtin.assert: that: - provide_present_check_mode is changed - provide_present_check_mode.sent.fvRsProv.attributes.tnVzBrCPName == 'anstest_http' @@ -138,6 +145,68 @@ - incompatible_present is failed - incompatible_present.msg == "the 'provider_match' is only configurable for Provided Contracts" + - name: bind taboo contract to epg + cisco.aci.aci_epg_to_contract: + <<: *aci_epg_present + contract: anstest_https + contract_type: taboo + register: taboo_present + + - name: bind interface contract to epg + cisco.aci.aci_epg_to_contract: + <<: *aci_epg_present + contract: anstest_https + contract_type: interface + register: interface_present + + - name: bind intra epg contract to epg + cisco.aci.aci_epg_to_contract: &aci_epg_intra_present + <<: *aci_epg_present + contract: anstest_https + contract_type: intra_epg + register: intra_epg_present + + - name: bind intra epg contract to epg (error contract label) + cisco.aci.aci_epg_to_contract: + <<: *aci_epg_intra_present + contract_label: anstest_contract_label + ignore_errors: true + register: err_contract_label + + - name: bind intra epg contract to epg (error subject label) + cisco.aci.aci_epg_to_contract: + <<: *aci_epg_intra_present + subject_label: anstest_subject_label + ignore_errors: true + register: err_subject_label + + - name: bind intra epg contract to epg (error subject and contract label) + cisco.aci.aci_epg_to_contract: + <<: *aci_epg_intra_present + contract_label: anstest_contract_label + subject_label: anstest_subject_label + ignore_errors: true + register: err_subject_and_contract_label + + - name: present assertions for taboo, interface and intra_epg contract types + assert: + that: + - taboo_present is changed + - taboo_present.previous == [] + - taboo_present.current.0.fvRsProtBy.attributes.tnVzTabooName == 'anstest_https' + - interface_present is changed + - interface_present.previous == [] + - interface_present.current.0.fvRsConsIf.attributes.tnVzCPIfName == 'anstest_https' + - intra_epg_present is changed + - intra_epg_present.previous == [] + - intra_epg_present.current.0.fvRsIntraEpg.attributes.tnVzBrCPName == 'anstest_https' + - err_contract_label is failed + - err_contract_label.msg == "the 'contract_label' and 'subject_label' are not configurable for intra_epg contracts" + - err_subject_label is failed + - err_subject_label.msg == "the 'contract_label' and 'subject_label' are not configurable for intra_epg contracts" + - err_subject_and_contract_label is failed + - err_subject_and_contract_label.msg == "the 'contract_label' and 'subject_label' are not configurable for intra_epg contracts" + - name: get binding cisco.aci.aci_epg_to_contract: <<: *aci_epg_provide_present2 @@ -166,7 +235,7 @@ register: missing_required_query - name: query assertions - assert: + ansible.builtin.assert: that: - query_provide_contract is not changed - query_provide_contract.current != [] @@ -223,7 +292,7 @@ register: missing_required_absent - name: absent assertions - assert: + ansible.builtin.assert: that: - consume_absent_check_mode is changed - consume_absent_check_mode.previous.0.fvRsCons is defined diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_epg_to_contract_interface/tasks/main.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_epg_to_contract_interface/tasks/main.yml index a7ba64768..04edb3030 100644 --- a/ansible_collections/cisco/aci/tests/integration/targets/aci_epg_to_contract_interface/tasks/main.yml +++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_epg_to_contract_interface/tasks/main.yml @@ -4,13 +4,13 @@ # GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) - name: Test that we have an ACI APIC host, ACI username and ACI password - fail: + ansible.builtin.fail: msg: 'Please define the following variables: aci_hostname, aci_username and aci_password.' when: aci_hostname is not defined or aci_username is not defined or aci_password is not defined # SET VARS - name: Set vars - set_fact: + ansible.builtin.set_fact: aci_info: &aci_info host: '{{ aci_hostname }}' username: '{{ aci_username }}' @@ -20,7 +20,7 @@ use_proxy: '{{ aci_use_proxy | default(true) }}' - name: Verify Cloud and Non-Cloud Sites in use. - include_tasks: ../../../../../../integration/targets/aci_cloud_provider/tasks/main.yml + ansible.builtin.include_tasks: ../../../../../../integration/targets/aci_cloud_provider/tasks/main.yml - name: Ensure ansible_test does not exist prior to testing cisco.aci.aci_tenant: &ansible_test_absent @@ -95,7 +95,7 @@ register: inter_tenant_contract_interface_present - name: Ensure inter_tenant_contract_interface binding with anstest1_epg - assert: + ansible.builtin.assert: that: - inter_tenant_contract_interface_present is changed - inter_tenant_contract_interface_present.current | length == 1 @@ -109,7 +109,7 @@ register: idempotency_check - name: Verfication of idempotency_check - assert: + ansible.builtin.assert: that: - idempotency_check is not changed @@ -124,7 +124,7 @@ register: single_object_query_result - name: Verification of single consumed contract interface - assert: + ansible.builtin.assert: that: - single_object_query_result is not changed - single_object_query_result.current.0.fvRsConsIf.attributes.tnVzCPIfName == 'inter_tenant_contract_interface' @@ -139,7 +139,7 @@ register: all_object_query_result - name: Verification of all consumed contract interface - assert: + ansible.builtin.assert: that: - all_object_query_result is not changed - inter_tenant_contract_interface_present.current | length >= 1 diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_epg_to_contract_master/tasks/main.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_epg_to_contract_master/tasks/main.yml index 08a956f96..5b21ec87f 100644 --- a/ansible_collections/cisco/aci/tests/integration/targets/aci_epg_to_contract_master/tasks/main.yml +++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_epg_to_contract_master/tasks/main.yml @@ -4,13 +4,13 @@ # GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) - name: Test that we have an ACI APIC host, ACI username and ACI password - fail: + ansible.builtin.fail: msg: 'Please define the following variables: aci_hostname, aci_username and aci_password.' when: aci_hostname is not defined or aci_username is not defined or aci_password is not defined # CLEAN ENVIRONMENT - name: Set vars - set_fact: + ansible.builtin.set_fact: aci_info: &aci_info host: '{{ aci_hostname }}' username: '{{ aci_username }}' @@ -21,10 +21,10 @@ output_level: '{{ aci_output_level | default("info") }}' - name: Verify Cloud and Non-Cloud Sites in use. - include_tasks: ../../../../../../integration/targets/aci_cloud_provider/tasks/main.yml + ansible.builtin.include_tasks: ../../../../../../integration/targets/aci_cloud_provider/tasks/main.yml - name: Ensure tenant doesn't exist - aci_tenant: + cisco.aci.aci_tenant: <<: *aci_info state: absent tenant: ansible_test @@ -34,7 +34,7 @@ when: query_cloud.current == [] # This condition will execute only non-cloud sites block: # block specifies execution of tasks within, based on conditions - name: Ensure tenant exists for tests to kick off - aci_tenant: &aci_tenant_present + cisco.aci.aci_tenant: &aci_tenant_present <<: *aci_info state: present tenant: ansible_test @@ -113,7 +113,7 @@ - {ap: 'anstest_2', epg: 'anstest_3'} - name: Verify add_contract_master - assert: + ansible.builtin.assert: that: - item is changed - item.current.0.fvRsSecInherited.attributes.tDn == "uni/tn-ansible_test/ap-anstest/epg-anstest" @@ -132,7 +132,7 @@ - {ap: 'anstest', epg: 'anstest_2'} - {ap: 'anstest_2', epg: 'anstest_3'} - name: Verify add_another_contract_master - assert: + ansible.builtin.assert: that: - item is changed - item.current.0.fvRsSecInherited.attributes.tDn == "uni/tn-ansible_test/ap-anstest_2/epg-anstest_4" @@ -159,7 +159,7 @@ register: query_specific_contract_master - name: Verify query_specific_contract_master - assert: + ansible.builtin.assert: that: - query_specific_contract_master is not changed - query_specific_contract_master.current.0.fvRsSecInherited.attributes.dn == "uni/tn-ansible_test/ap-anstest/epg-anstest_2/rssecInherited-[uni/tn-ansible_test/ap-anstest_2/epg-anstest_4]" @@ -177,7 +177,7 @@ register: query_another_specific_contract_master - name: Verify query_another_specific_contract_master - assert: + ansible.builtin.assert: that: - query_another_specific_contract_master is not changed - query_another_specific_contract_master.current.0.fvRsSecInherited.attributes.dn == "uni/tn-ansible_test/ap-anstest/epg-anstest_2/rssecInherited-[uni/tn-ansible_test/ap-anstest/epg-anstest]" @@ -195,14 +195,14 @@ register: remove_contract_master - name: Verify remove_contract_master - assert: + ansible.builtin.assert: that: - remove_contract_master is changed - remove_contract_master.current == [] # Clean up environment - name: Ensure tenant doesn't exist - aci_tenant: + cisco.aci.aci_tenant: <<: *aci_info state: absent tenant: ansible_test diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_epg_to_domain/tasks/main.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_epg_to_domain/tasks/main.yml index ea482f563..0903178ef 100644 --- a/ansible_collections/cisco/aci/tests/integration/targets/aci_epg_to_domain/tasks/main.yml +++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_epg_to_domain/tasks/main.yml @@ -4,13 +4,13 @@ # GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) - name: Test that we have an ACI APIC host, ACI username and ACI password - fail: + ansible.builtin.fail: msg: 'Please define the following variables: aci_hostname, aci_username and aci_password.' when: aci_hostname is not defined or aci_username is not defined or aci_password is not defined # CLEAN ENVIRONMENT - name: Set vars - set_fact: + ansible.builtin.set_fact: aci_info: &aci_info host: "{{ aci_hostname }}" username: "{{ aci_username }}" @@ -21,14 +21,14 @@ output_level: '{{ aci_output_level | default("debug") }}' - name: Query system information - aci_system: + cisco.aci.aci_system: <<: *aci_info id: 1 state: query register: version - name: Verify Cloud and Non-Cloud Sites in use. - include_tasks: ../../../../../../integration/targets/aci_cloud_provider/tasks/main.yml + ansible.builtin.include_tasks: ../../../../../../integration/targets/aci_cloud_provider/tasks/main.yml - name: Execute tasks only for non-cloud sites when: query_cloud.current == [] # This condition will execute only non-cloud sites @@ -237,7 +237,7 @@ register: vmm_uplink_change_active - name: vmm_uplink assertions - assert: + ansible.builtin.assert: that: - vmm_uplink is changed - vmm_uplink.current.0.fvRsDomAtt.children.0.fvUplinkOrderCont.attributes.active == "1,2" @@ -287,7 +287,7 @@ register: vmm_uplink_empty_value_standby - name: vmm_uplink assertions - assert: + ansible.builtin.assert: that: - vmm_uplink_0_value is changed - vmm_uplink_0_value.current.0.fvRsDomAtt.children.0.fvUplinkOrderCont.attributes.active == "0" @@ -324,14 +324,14 @@ register: vmm_uplink_33_value - name: vmm_uplink error assertions - assert: + ansible.builtin.assert: that: - 'vmm_uplink_change_active_same_as_standby.msg == "APIC Error 120: Invalid Configuration. Uplink Id entered more than once or delimiter was misused."' - 'vmm_uplink_empty_value_active.msg == "APIC Error 801: property active of uni/tn-ansible_test/ap-anstest/epg-anstest/rsdomAtt-[uni/vmmp-VMware/dom-anstest]/uplinkorder failed validation for value ''''"' - 'vmm_uplink_string_value.msg == "APIC Error 801: property active of uni/tn-ansible_test/ap-anstest/epg-anstest/rsdomAtt-[uni/vmmp-VMware/dom-anstest]/uplinkorder failed validation for value ''testing''"' - name: vmm_uplink error assertions for non-cloud - assert: + ansible.builtin.assert: that: - 'vmm_uplink_33_value.msg == "APIC Error 120: Invalid Configuration. Uplink Id can not be higher than 32."' @@ -344,7 +344,7 @@ register: custom_epg_name - name: Verify custom epg name - assert: + ansible.builtin.assert: that: - custom_epg_name.current.0.fvRsDomAtt.attributes.customEpgName == "anstest_epg" @@ -386,7 +386,7 @@ loop: "{{ range(0, 7, 1)|list }}" - name: domains with delimiter assertions - assert: + ansible.builtin.assert: that: - delimeter.results.0 is changed - delimeter.results.0.current.0.fvRsDomAtt.attributes.delimiter == "|" @@ -403,7 +403,7 @@ - delimeter.results.6 is changed - delimeter.results.6.current.0.fvRsDomAtt.attributes.delimiter == "=" - delimiter_not_allowed is not changed - - 'delimiter_not_allowed.msg == "value of delimiter must be one of: |, ~, !, @, ^, +, =, got: not_allowed"' + - 'delimiter_not_allowed.msg == "value of delimiter must be one of: |, ~, !, @, ^, +, =, _, got: not_allowed"' - delimeter_absent.results.0 is changed - delimeter_absent.results.0.current == [] - delimeter_absent.results.1 is changed @@ -441,7 +441,7 @@ register: untagged_vlan_absent - name: domains with untagged vlan assertions - assert: + ansible.builtin.assert: that: - untagged_vlan_true is changed - untagged_vlan_true.current.0.fvRsDomAtt.attributes.untagged == "yes" @@ -489,7 +489,7 @@ register: port_binding_absent - name: domains with port binding assertions - assert: + ansible.builtin.assert: that: - port_binding_dynamic is changed - port_binding_dynamic.current.0.fvRsDomAtt.attributes.bindingType == "dynamicBinding" @@ -532,7 +532,7 @@ register: port_allocation_absent - name: domains with port allocation assertions - assert: + ansible.builtin.assert: that: - port_allocation_elastic is changed - port_allocation_elastic.current.0.fvRsDomAtt.attributes.portAllocation == "elastic" @@ -565,7 +565,7 @@ register: number_of_ports_absent - name: domains with number of ports assertions - assert: + ansible.builtin.assert: that: - number_of_ports_2 is changed - number_of_ports_2.current.0.fvRsDomAtt.attributes.numPorts == "2" @@ -598,7 +598,7 @@ register: forged_transmits_and_mac_changes_absent - name: domains with forged transmits and mac changes assertions - assert: + ansible.builtin.assert: that: - forged_transmits_and_mac_changes_accept is changed - forged_transmits_and_mac_changes_accept.current.0.fvRsDomAtt.children.0.vmmSecP.attributes.forgedTransmits == "accept" @@ -610,7 +610,7 @@ - forged_transmits_and_mac_changes_absent.current == [] - name: present assertions - assert: + ansible.builtin.assert: that: - phys_check_mode_present is changed - phys_present is changed @@ -649,7 +649,7 @@ register: binding_query - name: query assertions - assert: + ansible.builtin.assert: that: - binding_query is not changed - binding_query.current | length > 1 @@ -686,7 +686,7 @@ register: absent_missing_param - name: absent assertions - assert: + ansible.builtin.assert: that: - epg_domain_check_mode_absent is changed - epg_domain_check_mode_absent.previous != [] @@ -732,4 +732,46 @@ cisco.aci.aci_tenant: <<: *aci_tenant_present state: absent - when: tenant_present is changed \ No newline at end of file + when: tenant_present is changed + + # Seperate underscore delimiter tests + # All other tests use underscore delimiters in naming of parents whiches causes tests fail + # Error: 400 - Validation failed: Tenant/Application/EPG name contains _. Please use another delimiter or rename + - name: Ensure tenant exists for testing underscore delimiter + cisco.aci.aci_tenant: &underscore_tenant + <<: *aci_info + tenant: underscore + state: present + register: tenant_present + + - name: Ensure ap exists for testing underscore delimiter + cisco.aci.aci_ap: &underscore_ap + <<: *underscore_tenant + ap: underscore + register: ap_present + + - name: Ensure epg exists for testing underscore delimiter + cisco.aci.aci_epg: &underscore_epg + <<: *underscore_ap + epg: underscore + + - name: Create domain with underscore delimiter delimiter + cisco.aci.aci_epg_to_domain: + <<: *underscore_epg + domain: anstest + domain_type: vmm + vm_provider: vmware + delimiter: "_" + register: underscore + + - name: Assert underscore delimiter + ansible.builtin.assert: + that: + - underscore is changed + - underscore.current.0.fvRsDomAtt.attributes.delimiter == "_" + + - name: Remove tenant used for testing underscore delimiter + cisco.aci.aci_tenant: + <<: *underscore_tenant + state: absent + register: tenant_present \ No newline at end of file diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_epg_useg_attribute_block_statement/aliases b/ansible_collections/cisco/aci/tests/integration/targets/aci_epg_useg_attribute_block_statement/aliases new file mode 100644 index 000000000..209b793f9 --- /dev/null +++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_epg_useg_attribute_block_statement/aliases @@ -0,0 +1,2 @@ +# No ACI simulator yet, so not enabled +# unsupported diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_epg_useg_attribute_block_statement/tasks/main.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_epg_useg_attribute_block_statement/tasks/main.yml new file mode 100644 index 000000000..75bd9b2e6 --- /dev/null +++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_epg_useg_attribute_block_statement/tasks/main.yml @@ -0,0 +1,251 @@ +# Test code for the ACI modules +# Copyright: (c) 2024, Akini Ross (@akinross) + +# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) + +- name: Test that we have an ACI APIC host, ACI username and ACI password + ansible.builtin.fail: + msg: 'Please define the following variables: aci_hostname, aci_username and aci_password.' + when: aci_hostname is not defined or aci_username is not defined or aci_password is not defined + +- name: Set vars + ansible.builtin.set_fact: + aci_info: &aci_info + host: "{{ aci_hostname }}" + username: "{{ aci_username }}" + password: "{{ aci_password }}" + validate_certs: '{{ aci_validate_certs | default(false) }}' + use_ssl: '{{ aci_use_ssl | default(true) }}' + use_proxy: '{{ aci_use_proxy | default(true) }}' + output_level: '{{ aci_output_level | default("info") }}' + +- name: Verify Cloud and Non-Cloud Sites in use. + ansible.builtin.include_tasks: ../../../../../../integration/targets/aci_cloud_provider/tasks/main.yml + +- name: Execute tasks only for non-cloud sites ( clean after ) + when: + - query_cloud.current == [] + block: + + # CLEAN TEST ENVIRONMENT + - name: Ensure tenant removed + cisco.aci.aci_tenant: &aci_tenant_absent + <<: *aci_info + state: absent + tenant: ansible_test + + # SETUP TEST ENVIRONMENT + - name: Create tenant + cisco.aci.aci_tenant: &aci_tenant_present + <<: *aci_tenant_absent + state: present + + - name: Create AP + cisco.aci.aci_ap: &aci_ap + <<: *aci_tenant_present + ap: ansible_test + + - name: Create uSeg EPG + cisco.aci.aci_epg: + <<: *aci_ap + epg: ansible_test_1 + bd: ansible_test + useg: yes + + # CREATE AND UPDATE TESTS + - name: Create block statement in default block (check mode) + cisco.aci.aci_epg_useg_attribute_block_statement: &block_a_parent_default_present + <<: *aci_ap + epg: ansible_test_1 + name: block_a + check_mode: true + register: cm_create_block_a_parent_default + + - name: Create block statement in default block + cisco.aci.aci_epg_useg_attribute_block_statement: + <<: *block_a_parent_default_present + register: nm_create_block_a_parent_default + + - name: Create block statement in default block again + cisco.aci.aci_epg_useg_attribute_block_statement: + <<: *block_a_parent_default_present + register: nm_create_block_a_parent_default_again + + - name: Assert create block statement in default block + ansible.builtin.assert: + that: + - cm_create_block_a_parent_default is changed + - cm_create_block_a_parent_default.previous == [] + - cm_create_block_a_parent_default.current == [] + - cm_create_block_a_parent_default.proposed.fvSCrtrn.attributes.name == "block_a" + - cm_create_block_a_parent_default.proposed.fvSCrtrn.attributes.dn == "uni/tn-ansible_test/ap-ansible_test/epg-ansible_test_1/crtrn/crtrn-block_a" + - nm_create_block_a_parent_default is changed + - nm_create_block_a_parent_default.previous == [] + - nm_create_block_a_parent_default.current.0.fvSCrtrn.attributes.name == "block_a" + - nm_create_block_a_parent_default.current.0.fvSCrtrn.attributes.match == "any" + - nm_create_block_a_parent_default.current.0.fvSCrtrn.attributes.dn == "uni/tn-ansible_test/ap-ansible_test/epg-ansible_test_1/crtrn/crtrn-block_a" + - nm_create_block_a_parent_default_again is not changed + - nm_create_block_a_parent_default_again.previous.0.fvSCrtrn.attributes.name == "block_a" + - nm_create_block_a_parent_default_again.previous.0.fvSCrtrn.attributes.match == "any" + - nm_create_block_a_parent_default_again.previous.0.fvSCrtrn.attributes.dn == "uni/tn-ansible_test/ap-ansible_test/epg-ansible_test_1/crtrn/crtrn-block_a" + - nm_create_block_a_parent_default_again.current.0.fvSCrtrn.attributes.name == "block_a" + - nm_create_block_a_parent_default_again.current.0.fvSCrtrn.attributes.match == "any" + - nm_create_block_a_parent_default_again.current.0.fvSCrtrn.attributes.dn == "uni/tn-ansible_test/ap-ansible_test/epg-ansible_test_1/crtrn/crtrn-block_a" + + - name: Update block statement in default block + cisco.aci.aci_epg_useg_attribute_block_statement: + <<: *block_a_parent_default_present + match: all + state: present + register: nm_update_block_a_parent_default + + - name: Assert update block statement match + ansible.builtin.assert: + that: + - nm_update_block_a_parent_default is changed + - nm_update_block_a_parent_default.previous.0.fvSCrtrn.attributes.name == "block_a" + - nm_update_block_a_parent_default.previous.0.fvSCrtrn.attributes.match == "any" + - nm_update_block_a_parent_default.previous.0.fvSCrtrn.attributes.dn == "uni/tn-ansible_test/ap-ansible_test/epg-ansible_test_1/crtrn/crtrn-block_a" + - nm_update_block_a_parent_default.current.0.fvSCrtrn.attributes.name == "block_a" + - nm_update_block_a_parent_default.current.0.fvSCrtrn.attributes.match == "all" + - nm_update_block_a_parent_default.current.0.fvSCrtrn.attributes.dn == "uni/tn-ansible_test/ap-ansible_test/epg-ansible_test_1/crtrn/crtrn-block_a" + + - name: Create block statement in block_a + cisco.aci.aci_epg_useg_attribute_block_statement: &block_b_parent_block_a + <<: *block_a_parent_default_present + name: block_b + match: all + parent_block_statements: + - block_a + register: nm_create_block_b_parent_block_a + + - name: Create block statement in block_b + cisco.aci.aci_epg_useg_attribute_block_statement: &block_c_parent_block_b + <<: *block_a_parent_default_present + name: block_c + match: any + parent_block_statements: + - block_a + - block_b + register: nm_create_block_c_parent_block_b + + - name: Assert create block statement in default block + ansible.builtin.assert: + that: + - nm_create_block_b_parent_block_a is changed + - nm_create_block_b_parent_block_a.previous == [] + - nm_create_block_b_parent_block_a.current.0.fvSCrtrn.attributes.name == "block_b" + - nm_create_block_b_parent_block_a.current.0.fvSCrtrn.attributes.match == "all" + - nm_create_block_b_parent_block_a.current.0.fvSCrtrn.attributes.dn == "uni/tn-ansible_test/ap-ansible_test/epg-ansible_test_1/crtrn/crtrn-block_a/crtrn-block_b" + - nm_create_block_c_parent_block_b is changed + - nm_create_block_c_parent_block_b.previous == [] + - nm_create_block_c_parent_block_b.current.0.fvSCrtrn.attributes.name == "block_c" + - nm_create_block_c_parent_block_b.current.0.fvSCrtrn.attributes.match == "any" + - nm_create_block_c_parent_block_b.current.0.fvSCrtrn.attributes.dn == "uni/tn-ansible_test/ap-ansible_test/epg-ansible_test_1/crtrn/crtrn-block_a/crtrn-block_b/crtrn-block_c" + + - name: Create block statement in block_c (error) + cisco.aci.aci_epg_useg_attribute_block_statement: + <<: *block_a_parent_default_present + name: block_d + match: any + parent_block_statements: + - block_a + - block_b + - block_c + register: err_too_many_blocks + ignore_errors: true + + - name: Assert create block statement in default block + ansible.builtin.assert: + that: + - err_too_many_blocks is failed + - err_too_many_blocks.msg == "3 block statements are provided but the maximum amount of parent_block_statements is 2" + + # QUERY TESTS + - name: Query block statement in default block + cisco.aci.aci_epg_useg_attribute_block_statement: + <<: *block_a_parent_default_present + state: query + register: query_block_a_parent_default + + - name: Query all block statements + cisco.aci.aci_epg_useg_attribute_block_statement: + <<: *aci_info + state: query + register: query_all_blocks + + - name: Assert query block statements + ansible.builtin.assert: + that: + - query_block_a_parent_default is not changed + - query_block_a_parent_default.current | length == 1 + - query_block_a_parent_default.current.0.fvSCrtrn.attributes.name == "block_a" + - query_block_a_parent_default.current.0.fvSCrtrn.attributes.match == "all" + - query_block_a_parent_default.current.0.fvSCrtrn.attributes.dn == "uni/tn-ansible_test/ap-ansible_test/epg-ansible_test_1/crtrn/crtrn-block_a" + - query_all_blocks is not changed + - query_all_blocks.current | length >= 3 + + # REMOVE TESTS + - name: Remove block statement from block_b + cisco.aci.aci_epg_useg_attribute_block_statement: + <<: *block_c_parent_block_b + state: absent + register: rm_block_c_parent_block_b + + - name: Remove block statement from block_a + cisco.aci.aci_epg_useg_attribute_block_statement: + <<: *block_b_parent_block_a + state: absent + register: rm_block_b_parent_block_a + + - name: Remove block statement from default (check mode) + cisco.aci.aci_epg_useg_attribute_block_statement: &block_a_parent_default_absent + <<: *block_a_parent_default_present + state: absent + register: cm_remove_block_a_parent_default + check_mode: true + + - name: Remove block statement from default + cisco.aci.aci_epg_useg_attribute_block_statement: + <<: *block_a_parent_default_absent + register: nm_remove_block_a_parent_default + + - name: Remove block statement from default again + cisco.aci.aci_epg_useg_attribute_block_statement: + <<: *block_a_parent_default_absent + register: nm_remove_block_a_parent_default_again + + - name: Assert remove block statements + ansible.builtin.assert: + that: + - rm_block_c_parent_block_b is changed + - rm_block_c_parent_block_b.previous.0.fvSCrtrn.attributes.name == "block_c" + - rm_block_c_parent_block_b.previous.0.fvSCrtrn.attributes.match == "any" + - rm_block_c_parent_block_b.previous.0.fvSCrtrn.attributes.dn == "uni/tn-ansible_test/ap-ansible_test/epg-ansible_test_1/crtrn/crtrn-block_a/crtrn-block_b/crtrn-block_c" + - rm_block_c_parent_block_b.current == [] + - rm_block_b_parent_block_a is changed + - rm_block_b_parent_block_a.previous.0.fvSCrtrn.attributes.name == "block_b" + - rm_block_b_parent_block_a.previous.0.fvSCrtrn.attributes.match == "all" + - rm_block_b_parent_block_a.previous.0.fvSCrtrn.attributes.dn == "uni/tn-ansible_test/ap-ansible_test/epg-ansible_test_1/crtrn/crtrn-block_a/crtrn-block_b" + - rm_block_b_parent_block_a.current == [] + - cm_remove_block_a_parent_default is changed + - cm_remove_block_a_parent_default.previous.0.fvSCrtrn.attributes.name == "block_a" + - cm_remove_block_a_parent_default.previous.0.fvSCrtrn.attributes.match == "all" + - cm_remove_block_a_parent_default.previous.0.fvSCrtrn.attributes.dn == "uni/tn-ansible_test/ap-ansible_test/epg-ansible_test_1/crtrn/crtrn-block_a" + - cm_remove_block_a_parent_default.current.0.fvSCrtrn.attributes.name == "block_a" + - cm_remove_block_a_parent_default.current.0.fvSCrtrn.attributes.match == "all" + - cm_remove_block_a_parent_default.current.0.fvSCrtrn.attributes.dn == "uni/tn-ansible_test/ap-ansible_test/epg-ansible_test_1/crtrn/crtrn-block_a" + - cm_remove_block_a_parent_default.proposed == {} + - nm_remove_block_a_parent_default is changed + - nm_remove_block_a_parent_default.previous.0.fvSCrtrn.attributes.name == "block_a" + - nm_remove_block_a_parent_default.previous.0.fvSCrtrn.attributes.match == "all" + - nm_remove_block_a_parent_default.previous.0.fvSCrtrn.attributes.dn == "uni/tn-ansible_test/ap-ansible_test/epg-ansible_test_1/crtrn/crtrn-block_a" + - nm_remove_block_a_parent_default.current == [] + - nm_remove_block_a_parent_default_again is not changed + - nm_remove_block_a_parent_default_again.previous == [] + - nm_remove_block_a_parent_default_again.current == [] + + # CLEAN TEST ENVIRONMENT + - name: Remove tenant + cisco.aci.aci_tenant: + <<: *aci_tenant_absent diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_epg_useg_attribute_simple_statement/aliases b/ansible_collections/cisco/aci/tests/integration/targets/aci_epg_useg_attribute_simple_statement/aliases new file mode 100644 index 000000000..209b793f9 --- /dev/null +++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_epg_useg_attribute_simple_statement/aliases @@ -0,0 +1,2 @@ +# No ACI simulator yet, so not enabled +# unsupported diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_epg_useg_attribute_simple_statement/tasks/main.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_epg_useg_attribute_simple_statement/tasks/main.yml new file mode 100644 index 000000000..32e4c37b8 --- /dev/null +++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_epg_useg_attribute_simple_statement/tasks/main.yml @@ -0,0 +1,261 @@ +# Test code for the ACI modules +# Copyright: (c) 2023, Christian Kolrep (@Christian-Kolrep) +# Copyright: (c) 2024, Akini Ross (@akinross) + +# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) + +- name: Test that we have an ACI APIC host, ACI username and ACI password + ansible.builtin.fail: + msg: 'Please define the following variables: aci_hostname, aci_username and aci_password.' + when: aci_hostname is not defined or aci_username is not defined or aci_password is not defined + +- name: Set vars + ansible.builtin.set_fact: + aci_info: &aci_info + host: "{{ aci_hostname }}" + username: "{{ aci_username }}" + password: "{{ aci_password }}" + validate_certs: '{{ aci_validate_certs | default(false) }}' + use_ssl: '{{ aci_use_ssl | default(true) }}' + use_proxy: '{{ aci_use_proxy | default(true) }}' + output_level: '{{ aci_output_level | default("debug") }}' + +- name: Verify Cloud and Non-Cloud Sites in use. + ansible.builtin.include_tasks: ../../../../../../integration/targets/aci_cloud_provider/tasks/main.yml + +- name: Execute tasks only for non-cloud sites ( clean after ) + when: + - query_cloud.current == [] + block: + + # CLEAN TEST ENVIRONMENT + - name: Ensure tenant removed + cisco.aci.aci_tenant: &aci_tenant_absent + <<: *aci_info + state: absent + tenant: ansible_test + + # SETUP TEST ENVIRONMENT + - name: Create tenant + cisco.aci.aci_tenant: &aci_tenant_present + <<: *aci_tenant_absent + state: present + + - name: Create AP + cisco.aci.aci_ap: &aci_ap + <<: *aci_tenant_present + ap: ansible_test + + - name: Create uSeg EPG + cisco.aci.aci_epg: + <<: *aci_ap + epg: ansible_test_1 + bd: ansible_test + useg: yes + + - name: Create block statement block_a + cisco.aci.aci_epg_useg_attribute_block_statement: &block + <<: *aci_ap + epg: ansible_test_1 + name: block_a + + - name: Create block statement block_b + cisco.aci.aci_epg_useg_attribute_block_statement: + <<: *block + name: block_b + parent_block_statements: + - block_a + + - name: Create block statement block_c + cisco.aci.aci_epg_useg_attribute_block_statement: + <<: *block + name: block_c + parent_block_statements: + - block_a + - block_b + + # TEST THAT ALL LEVELS OF BLOCK STATEMENTS WORK WITH THE VM_NAME SIMPLE STATEMENT TYPE + - name: Execute tests for each block statement + ansible.builtin.include_tasks: simple_block_levels.yml + loop: + - [] + - [block_a] + - [block_a, block_b] + - [block_a, block_b, block_c] + loop_control: + loop_var: parent_block_statements + + # INPUT TEST FOR OPERATOR INPUT + - name: Create simple statement with all operator input options + cisco.aci.aci_epg_useg_attribute_simple_statement: + <<: *aci_ap + epg: ansible_test_1 + name: ansible_test_vm_name + type: vm_name + operator: "{{ item }}" + value: ansible_test_vm_name_value + register: nm_operators + loop: + - contains + - equals + - starts_with + - ends_with + + - name: Assert simple statement with all operator input options + ansible.builtin.assert: + that: + - nm_operators.results | length == 4 + - nm_operators.results.0.changed == true + - nm_operators.results.0.current.0.fvVmAttr.attributes.operator == "contains" + - nm_operators.results.1.changed == true + - nm_operators.results.1.current.0.fvVmAttr.attributes.operator == "equals" + - nm_operators.results.2.changed == true + - nm_operators.results.2.current.0.fvVmAttr.attributes.operator == "startsWith" + - nm_operators.results.3.changed == true + - nm_operators.results.3.current.0.fvVmAttr.attributes.operator == "endsWith" + + # INPUT TESTS FOR TYPES + - name: Create simple statement with all type input options + cisco.aci.aci_epg_useg_attribute_simple_statement: + <<: *aci_ap + epg: ansible_test_1 + name: "{{ item.name }}" + type: "{{ item.type }}" + operator: "{{ item.operator }}" + category: "{{ item.category }}" + value: "{{ item.value }}" + use_subnet: "{{ item.use_subnet | default(omit) }}" + register: nm_types + loop: + - { name: ansible_test_ip_1, type: ip, operator: "{{ fake_var | default(omit) }}", category: "{{ fake_var | default(omit) }}", use_subnet: "{{ fake_var | default(omit) }}", value: 10.0.0.1 } + - { name: ansible_test_ip_2, type: ip, operator: "{{ fake_var | default(omit) }}", category: "{{ fake_var | default(omit) }}", use_subnet: true, value: "{{ fake_var | default(omit) }}" } + - { name: ansible_test_mac, type: mac, operator: "{{ fake_var | default(omit) }}", category: "{{ fake_var | default(omit) }}", use_subnet: "{{ fake_var | default(omit) }}", value: "aa:bb:cc:dd:ee:ff" } + - { name: ansible_test_dns, type: dns, operator: "{{ fake_var | default(omit) }}", category: "{{ fake_var | default(omit) }}", use_subnet: "{{ fake_var | default(omit) }}", value: "dns_filter" } + - { name: ansible_test_ad_group, type: ad_group, operator: "{{ fake_var | default(omit) }}", category: "{{ fake_var | default(omit) }}", use_subnet: "{{ fake_var | default(omit) }}", value: "ad_group_selector" } + - { name: ansible_test_vm_custom_attr, type: vm_custom_attr, operator: "contains", category: "custom_attribute", use_subnet: "{{ fake_var | default(omit) }}", value: "custom_attribute_value" } + - { name: ansible_test_vm_vmm_domain, type: vm_vmm_domain, operator: "contains", category: "{{ fake_var | default(omit) }}", use_subnet: "{{ fake_var | default(omit) }}", value: "vm_vmm_domain_value" } + - { name: ansible_test_vm_operating_system, type: vm_operating_system, operator: "contains", category: "{{ fake_var | default(omit) }}", use_subnet: "{{ fake_var | default(omit) }}", value: "vm_operating_system_value" } + - { name: ansible_test_vm_hypervisor_id, type: vm_hypervisor_id, operator: "contains", category: "{{ fake_var | default(omit) }}", use_subnet: "{{ fake_var | default(omit) }}", value: "vm_hypervisor_id_value" } + - { name: ansible_test_vm_datacenter, type: vm_datacenter, operator: "contains", category: "{{ fake_var | default(omit) }}", use_subnet: "{{ fake_var | default(omit) }}", value: "vm_datacenter_value" } + - { name: ansible_test_vm_id, type: vm_id, operator: "contains", category: "{{ fake_var | default(omit) }}", use_subnet: "{{ fake_var | default(omit) }}", value: "vm_id_value" } + - { name: ansible_test_vm_name, type: vm_name, operator: "contains", category: "{{ fake_var | default(omit) }}", use_subnet: "{{ fake_var | default(omit) }}", value: "vm_name_value" } + - { name: ansible_test_vm_folder, type: vm_folder, operator: "contains", category: "{{ fake_var | default(omit) }}", use_subnet: "{{ fake_var | default(omit) }}", value: "vm_folder_value" } + - { name: ansible_test_vm_folder_path, type: vm_folder_path, operator: "{{ fake_var | default(omit) }}", category: "{{ fake_var | default(omit) }}", use_subnet: "{{ fake_var | default(omit) }}", value: "vm_folder_path_value" } + - { name: ansible_test_vm_vnic, type: vm_vnic, operator: "contains", category: "{{ fake_var | default(omit) }}", use_subnet: "{{ fake_var | default(omit) }}", value: "vm_vnic_value" } + - { name: ansible_test_vm_tag, type: vm_tag, operator: "equals", category: "vm_attribute", use_subnet: "{{ fake_var | default(omit) }}", value: "vm_attribute_value" } + ignore_errors: true # ignore errors is set to handle the ad group configuration which is not configurable in the lab environment, so error message is expected to ensure payload is sent + + - name: Assert create simple statement with all type input options + ansible.builtin.assert: + that: + - nm_types.results | length == 16 + - nm_types.results.0.changed == true + - nm_types.results.0.current.0.fvIpAttr.attributes.name == "ansible_test_ip_1" + - nm_types.results.0.current.0.fvIpAttr.attributes.ip == "10.0.0.1" + - nm_types.results.0.current.0.fvIpAttr.attributes.usefvSubnet == "no" + - nm_types.results.1.changed == true + - nm_types.results.1.current.0.fvIpAttr.attributes.name == "ansible_test_ip_2" + - nm_types.results.1.current.0.fvIpAttr.attributes.ip == "0.0.0.0" + - nm_types.results.1.current.0.fvIpAttr.attributes.usefvSubnet == "yes" + - nm_types.results.2.changed == true + - nm_types.results.2.current.0.fvMacAttr.attributes.name == "ansible_test_mac" + - nm_types.results.2.current.0.fvMacAttr.attributes.mac == "AA:BB:CC:DD:EE:FF" + - nm_types.results.3.changed == true + - nm_types.results.3.current.0.fvDnsAttr.attributes.name == "ansible_test_dns" + - nm_types.results.3.current.0.fvDnsAttr.attributes.filter == "dns_filter" + - nm_types.results.4.failed == true + - nm_types.results.4.msg == "APIC Error 400{{":"}} Invalid request. Can not contain child 'idgattr-[ad_group_selector]' under parent 'uni/tn-ansible_test/ap-ansible_test/epg-ansible_test_1/crtrn/idgattr-[ansible_test_ad_group]'" + - nm_types.results.5.changed == true + - nm_types.results.5.current.0.fvVmAttr.attributes.name == "ansible_test_vm_custom_attr" + - nm_types.results.5.current.0.fvVmAttr.attributes.labelName == "custom_attribute" + - nm_types.results.5.current.0.fvVmAttr.attributes.operator == "contains" + - nm_types.results.5.current.0.fvVmAttr.attributes.type == "custom-label" + - nm_types.results.5.current.0.fvVmAttr.attributes.value == "custom_attribute_value" + - nm_types.results.6.changed == true + - nm_types.results.6.current.0.fvVmAttr.attributes.name == "ansible_test_vm_vmm_domain" + - nm_types.results.6.current.0.fvVmAttr.attributes.labelName == "" + - nm_types.results.6.current.0.fvVmAttr.attributes.operator == "contains" + - nm_types.results.6.current.0.fvVmAttr.attributes.type == "domain" + - nm_types.results.6.current.0.fvVmAttr.attributes.value == "vm_vmm_domain_value" + - nm_types.results.7.changed == true + - nm_types.results.7.current.0.fvVmAttr.attributes.name == "ansible_test_vm_operating_system" + - nm_types.results.7.current.0.fvVmAttr.attributes.labelName == "" + - nm_types.results.7.current.0.fvVmAttr.attributes.operator == "contains" + - nm_types.results.7.current.0.fvVmAttr.attributes.type == "guest-os" + - nm_types.results.7.current.0.fvVmAttr.attributes.value == "vm_operating_system_value" + - nm_types.results.8.changed == true + - nm_types.results.8.current.0.fvVmAttr.attributes.name == "ansible_test_vm_hypervisor_id" + - nm_types.results.8.current.0.fvVmAttr.attributes.labelName == "" + - nm_types.results.8.current.0.fvVmAttr.attributes.operator == "contains" + - nm_types.results.8.current.0.fvVmAttr.attributes.type == "hv" + - nm_types.results.8.current.0.fvVmAttr.attributes.value == "vm_hypervisor_id_value" + - nm_types.results.9.changed == true + - nm_types.results.9.current.0.fvVmAttr.attributes.name == "ansible_test_vm_datacenter" + - nm_types.results.9.current.0.fvVmAttr.attributes.labelName == "" + - nm_types.results.9.current.0.fvVmAttr.attributes.operator == "contains" + - nm_types.results.9.current.0.fvVmAttr.attributes.type == "rootContName" + - nm_types.results.9.current.0.fvVmAttr.attributes.value == "vm_datacenter_value" + - nm_types.results.10.changed == true + - nm_types.results.10.current.0.fvVmAttr.attributes.name == "ansible_test_vm_id" + - nm_types.results.10.current.0.fvVmAttr.attributes.labelName == "" + - nm_types.results.10.current.0.fvVmAttr.attributes.operator == "contains" + - nm_types.results.10.current.0.fvVmAttr.attributes.type == "vm" + - nm_types.results.10.current.0.fvVmAttr.attributes.value == "vm_id_value" + - nm_types.results.11.changed == true + - nm_types.results.11.current.0.fvVmAttr.attributes.name == "ansible_test_vm_name" + - nm_types.results.11.current.0.fvVmAttr.attributes.labelName == "" + - nm_types.results.11.current.0.fvVmAttr.attributes.operator == "contains" + - nm_types.results.11.current.0.fvVmAttr.attributes.type == "vm-name" + - nm_types.results.11.current.0.fvVmAttr.attributes.value == "vm_name_value" + - nm_types.results.12.changed == true + - nm_types.results.12.current.0.fvVmAttr.attributes.name == "ansible_test_vm_folder" + - nm_types.results.12.current.0.fvVmAttr.attributes.labelName == "" + - nm_types.results.12.current.0.fvVmAttr.attributes.operator == "contains" + - nm_types.results.12.current.0.fvVmAttr.attributes.type == "vm-folder" + - nm_types.results.12.current.0.fvVmAttr.attributes.value == "vm_folder_value" + - nm_types.results.13.changed == true + - nm_types.results.13.current.0.fvVmAttr.attributes.name == "ansible_test_vm_folder_path" + - nm_types.results.13.current.0.fvVmAttr.attributes.labelName == "" + - nm_types.results.13.current.0.fvVmAttr.attributes.operator == "equals" + - nm_types.results.13.current.0.fvVmAttr.attributes.type == "vmfolder-path" + - nm_types.results.13.current.0.fvVmAttr.attributes.value == "vm_folder_path_value" + - nm_types.results.14.changed == true + - nm_types.results.14.current.0.fvVmAttr.attributes.name == "ansible_test_vm_vnic" + - nm_types.results.14.current.0.fvVmAttr.attributes.labelName == "" + - nm_types.results.14.current.0.fvVmAttr.attributes.operator == "contains" + - nm_types.results.14.current.0.fvVmAttr.attributes.type == "vnic" + - nm_types.results.14.current.0.fvVmAttr.attributes.value == "vm_vnic_value" + - nm_types.results.15.changed == true + - nm_types.results.15.current.0.fvVmAttr.attributes.name == "ansible_test_vm_tag" + - nm_types.results.15.current.0.fvVmAttr.attributes.labelName == "" + - nm_types.results.15.current.0.fvVmAttr.attributes.operator == "equals" + - nm_types.results.15.current.0.fvVmAttr.attributes.type == "tag" + - nm_types.results.15.current.0.fvVmAttr.attributes.value == "vm_attribute_value" + + # ERROR TESTS + - name: Create simple statement with too many parents (error) + cisco.aci.aci_epg_useg_attribute_simple_statement: + <<: *aci_ap + epg: ansible_test_1 + parent_block_statements: + - block_a + - block_b + - block_c + - block_d + name: ansible_test_vm_name + type: vm_name + operator: contains + value: ansible_test_vm_name_value + register: err_too_many_blocks + ignore_errors: true + + - name: Assert create block statement in default block + ansible.builtin.assert: + that: + - err_too_many_blocks is failed + - err_too_many_blocks.msg == "4 block statements are provided but the maximum amount of parent_block_statements is 3" + + # CLEAN TEST ENVIRONMENT + - name: Remove tenant + cisco.aci.aci_tenant: + <<: *aci_tenant_absent diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_epg_useg_attribute_simple_statement/tasks/simple_block_levels.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_epg_useg_attribute_simple_statement/tasks/simple_block_levels.yml new file mode 100644 index 000000000..b37a5c7d5 --- /dev/null +++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_epg_useg_attribute_simple_statement/tasks/simple_block_levels.yml @@ -0,0 +1,156 @@ +- name: Set vars + ansible.builtin.set_fact: + aci_info: &aci_info + host: "{{ aci_hostname }}" + username: "{{ aci_username }}" + password: "{{ aci_password }}" + validate_certs: '{{ aci_validate_certs | default(false) }}' + use_ssl: '{{ aci_use_ssl | default(true) }}' + use_proxy: '{{ aci_use_proxy | default(true) }}' + output_level: '{{ aci_output_level | default("debug") }}' + aci_epg: &aci_epg + tenant: ansible_test + ap: ansible_test + epg: ansible_test_1 + +# CREATE AND UPDATE TESTS +- name: Create simple statement in block statement (check mode) + cisco.aci.aci_epg_useg_attribute_simple_statement: &simple_present + <<: *aci_info + <<: *aci_epg + parent_block_statements: "{{ parent_block_statements }}" + name: ansible_test_vm_name + type: vm_name + operator: contains + value: ansible_test_vm_name_value + check_mode: true + register: cm_create_simple + +- name: Create simple statement in block statement + cisco.aci.aci_epg_useg_attribute_simple_statement: + <<: *simple_present + register: nm_create_simple + +- name: Create simple statement in block statement again + cisco.aci.aci_epg_useg_attribute_simple_statement: + <<: *simple_present + register: nm_create_simple_again + +- name: Assert create simple statement in block statement + ansible.builtin.assert: + that: + - cm_create_simple is changed + - cm_create_simple.previous == [] + - cm_create_simple.current == [] + - cm_create_simple.proposed.fvVmAttr.attributes.name == "ansible_test_vm_name" + - cm_create_simple.proposed.fvVmAttr.attributes.type == "vm-name" + - cm_create_simple.proposed.fvVmAttr.attributes.operator == "contains" + - cm_create_simple.proposed.fvVmAttr.attributes.value == "ansible_test_vm_name_value" + - nm_create_simple is changed + - nm_create_simple.previous == [] + - nm_create_simple.current.0.fvVmAttr.attributes.name == "ansible_test_vm_name" + - nm_create_simple.current.0.fvVmAttr.attributes.type == "vm-name" + - nm_create_simple.current.0.fvVmAttr.attributes.operator == "contains" + - nm_create_simple.current.0.fvVmAttr.attributes.value == "ansible_test_vm_name_value" + - nm_create_simple_again is not changed + - nm_create_simple_again.previous.0.fvVmAttr.attributes.name == "ansible_test_vm_name" + - nm_create_simple_again.previous.0.fvVmAttr.attributes.type == "vm-name" + - nm_create_simple_again.previous.0.fvVmAttr.attributes.operator == "contains" + - nm_create_simple_again.previous.0.fvVmAttr.attributes.value == "ansible_test_vm_name_value" + - nm_create_simple_again.current.0.fvVmAttr.attributes.name == "ansible_test_vm_name" + - nm_create_simple_again.current.0.fvVmAttr.attributes.type == "vm-name" + - nm_create_simple_again.current.0.fvVmAttr.attributes.operator == "contains" + - nm_create_simple_again.current.0.fvVmAttr.attributes.value == "ansible_test_vm_name_value" + +# QUERY TESTS +- name: Create another simple statement in block statement + cisco.aci.aci_epg_useg_attribute_simple_statement: &simple_present_update + <<: *simple_present + name: ansible_test_vm_name_2 + type: vm_name + operator: contains + value: ansible_test_vm_name_value_2 + register: nm_create_simple_2 + +- name: Create another simple statement in block statement + cisco.aci.aci_epg_useg_attribute_simple_statement: + <<: *simple_present_update + operator: equals + value: ansible_test_vm_name_value_3 + register: nm_create_simple_2_update + +- name: Assert updates + ansible.builtin.assert: + that: + - nm_create_simple_2.current.0.fvVmAttr.attributes.name == "ansible_test_vm_name_2" + - nm_create_simple_2.current.0.fvVmAttr.attributes.type == "vm-name" + - nm_create_simple_2.current.0.fvVmAttr.attributes.operator == "contains" + - nm_create_simple_2.current.0.fvVmAttr.attributes.value == "ansible_test_vm_name_value_2" + - nm_create_simple_2_update.current.0.fvVmAttr.attributes.name == "ansible_test_vm_name_2" + - nm_create_simple_2_update.current.0.fvVmAttr.attributes.type == "vm-name" + - nm_create_simple_2_update.current.0.fvVmAttr.attributes.operator == "equals" + - nm_create_simple_2_update.current.0.fvVmAttr.attributes.value == "ansible_test_vm_name_value_3" + +- name: Query simple statement in block statement + cisco.aci.aci_epg_useg_attribute_simple_statement: + <<: *simple_present + state: query + register: query_one + +- name: Query all simple statements of type vm_name + cisco.aci.aci_epg_useg_attribute_simple_statement: + <<: *aci_info + type: vm_name + state: query + register: query_all + +- name: Assert queries + ansible.builtin.assert: + that: + - query_one.current | length == 1 + - query_one.current.0.fvVmAttr.attributes.name == "ansible_test_vm_name" + - query_one.current.0.fvVmAttr.attributes.type == "vm-name" + - query_one.current.0.fvVmAttr.attributes.operator == "contains" + - query_one.current.0.fvVmAttr.attributes.value == "ansible_test_vm_name_value" + - query_all.current | length >= 2 + +# REMOVE TESTS +- name: Remove simple statement from block statement (check mode) + cisco.aci.aci_epg_useg_attribute_simple_statement: &simple_absent + <<: *simple_present + state: absent + check_mode: true + register: cm_remove_simple + +- name: Remove simple statement from block statement + cisco.aci.aci_epg_useg_attribute_simple_statement: + <<: *simple_absent + register: nm_remove_simple + +- name: Remove simple statement from block statement again + cisco.aci.aci_epg_useg_attribute_simple_statement: + <<: *simple_absent + register: nm_remove_simple_again + +- name: Assert remove simple statement from block statement + ansible.builtin.assert: + that: + - cm_remove_simple is changed + - cm_remove_simple.previous.0.fvVmAttr.attributes.name == "ansible_test_vm_name" + - cm_remove_simple.previous.0.fvVmAttr.attributes.type == "vm-name" + - cm_remove_simple.previous.0.fvVmAttr.attributes.operator == "contains" + - cm_remove_simple.previous.0.fvVmAttr.attributes.value == "ansible_test_vm_name_value" + - cm_remove_simple.current.0.fvVmAttr.attributes.name == "ansible_test_vm_name" + - cm_remove_simple.current.0.fvVmAttr.attributes.type == "vm-name" + - cm_remove_simple.current.0.fvVmAttr.attributes.operator == "contains" + - cm_remove_simple.current.0.fvVmAttr.attributes.value == "ansible_test_vm_name_value" + - cm_remove_simple.proposed == {} + - nm_remove_simple is changed + - nm_remove_simple.previous.0.fvVmAttr.attributes.name == "ansible_test_vm_name" + - nm_remove_simple.previous.0.fvVmAttr.attributes.type == "vm-name" + - nm_remove_simple.previous.0.fvVmAttr.attributes.operator == "contains" + - nm_remove_simple.previous.0.fvVmAttr.attributes.value == "ansible_test_vm_name_value" + - nm_remove_simple.current == [] + - nm_remove_simple_again is not changed + - nm_remove_simple_again.previous == [] + - nm_remove_simple_again.current == [] diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_esg/tasks/main.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_esg/tasks/main.yml index 34a482fa9..3716bd7e8 100644 --- a/ansible_collections/cisco/aci/tests/integration/targets/aci_esg/tasks/main.yml +++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_esg/tasks/main.yml @@ -4,13 +4,13 @@ # GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) - name: Test that we have an ACI APIC host, ACI username and ACI password - fail: + ansible.builtin.fail: msg: 'Please define the following variables: aci_hostname, aci_username and aci_password.' when: aci_hostname is not defined or aci_username is not defined or aci_password is not defined # SET VARS - name: Set vars - set_fact: + ansible.builtin.set_fact: aci_info: &aci_info host: '{{ aci_hostname }}' username: '{{ aci_username }}' @@ -28,7 +28,7 @@ register: version - name: Verify Cloud and Non-Cloud Sites in use. - include_tasks: ../../../../../../integration/targets/aci_cloud_provider/tasks/main.yml + ansible.builtin.include_tasks: ../../../../../../integration/targets/aci_cloud_provider/tasks/main.yml - name: Ensure tenant - ansible_test does not exists before testing cisco.aci.aci_tenant: &tenant_absent @@ -71,7 +71,7 @@ register: cm_web_esg_0_present - name: Assertions check for add web_esg_0 with check mode - assert: + ansible.builtin.assert: that: - cm_web_esg_0_present is changed - cm_web_esg_0_present.current | length == 0 @@ -83,7 +83,7 @@ register: nm_web_esg_0_present - name: Assertions check for add web_esg_0 with normal mode - assert: + ansible.builtin.assert: that: - nm_web_esg_0_present is changed - nm_web_esg_0_present.current | length == 1 @@ -96,7 +96,7 @@ - nm_web_esg_0_present.current.0.fvESg.children[0].fvRsScope.attributes.tnFvCtxName == 'default' - name: Assertions check for add web_esg_0 with normal mode (v5.2+) - assert: + ansible.builtin.assert: that: - nm_web_esg_0_present.current.0.fvESg.attributes.shutdown == 'no' when: version.current.0.topSystem.attributes.version is version('5.2', '>=') @@ -107,7 +107,7 @@ register: idempotency_web_esg_0_present - name: Idempotency assertions check for add web_esg_0 with normal mode - assert: + ansible.builtin.assert: that: - idempotency_web_esg_0_present is not changed - idempotency_web_esg_0_present.current | length == 1 @@ -123,7 +123,7 @@ register: ap_1_web_esg_0_present - name: Assertions check for add web_esg_0 under ap(anstest_ap_1_present) - assert: + ansible.builtin.assert: that: - ap_1_web_esg_0_present is changed - ap_1_web_esg_0_present.current | length == 1 @@ -142,7 +142,7 @@ when: version.current.0.topSystem.attributes.version is version('5.2', '>=') - name: Assertions check for add web_esg_1 - assert: + ansible.builtin.assert: that: - web_esg_1_present is changed - web_esg_1_present.current | length == 1 @@ -164,7 +164,7 @@ when: version.current.0.topSystem.attributes.version is version('5.2', '>=') - name: Assertions check for add web_esg_2 - assert: + ansible.builtin.assert: that: - web_esg_2_present is changed - web_esg_2_present.current | length == 1 @@ -183,7 +183,7 @@ register: query_web_esg_0 - name: Assertions check for query an ESG(web_esg_0) under ap(anstest_ap) - assert: + ansible.builtin.assert: that: - query_web_esg_0 is not changed - query_web_esg_0.current | length == 1 @@ -191,7 +191,7 @@ - query_web_esg_0.current.0.fvESg.attributes.dn == "uni/tn-ansible_test/ap-anstest_ap/esg-web_esg_0" - name: Assertions check for query an ESG(web_esg_0) under ap(anstest_ap) (v5.2+) - assert: + ansible.builtin.assert: that: - query_web_esg_0.current.0.fvESg.attributes.shutdown == 'no' when: version.current.0.topSystem.attributes.version is version('5.2', '>=') @@ -203,14 +203,14 @@ register: query_all_esg - name: Assertions check for query all ESGs - assert: + ansible.builtin.assert: that: - query_all_esg is not changed - query_all_esg.current | length >= 2 # Count of ESGs added in the above tasks when: version.current.0.topSystem.attributes.version is version('5.2', '<') - name: Assertions check for query all ESGs - assert: + ansible.builtin.assert: that: - query_all_esg is not changed - query_all_esg.current | length >= 4 # Count of ESGs added in the above tasks @@ -224,7 +224,7 @@ register: query_all_esg_with_name - name: Assertions check for query all ESGs with a Specific Name - assert: + ansible.builtin.assert: that: - query_all_esg_with_name is not changed - query_all_esg_with_name.current | length >= 2 @@ -237,7 +237,7 @@ register: query_all_ap_esg - name: Assertions check for query all ESGs of an App Profile (=v5.2) - assert: + ansible.builtin.assert: that: - query_all_ap_esg is not changed - query_all_ap_esg.current.0.fvAp.attributes.name == 'anstest_ap' @@ -261,7 +261,7 @@ check_mode: true - name: Assertions check for remove an ESG with check mode - assert: + ansible.builtin.assert: that: - cm_web_esg_0_absent is changed - cm_web_esg_0_absent.current | length == 1 @@ -275,7 +275,7 @@ register: nm_web_esg_0_absent - name: Assertions check for remove an ESG with normal mode - assert: + ansible.builtin.assert: that: - nm_web_esg_0_absent is changed - nm_web_esg_0_absent.current == [] @@ -288,7 +288,7 @@ register: idempotency_web_esg_0_absent - name: Idempotency assertions check for remove an ESG with normal mode - assert: + ansible.builtin.assert: that: - idempotency_web_esg_0_absent is not changed - idempotency_web_esg_0_absent.current == [] diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_esg_contract_master/tasks/main.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_esg_contract_master/tasks/main.yml index debc3ec47..820e4be56 100644 --- a/ansible_collections/cisco/aci/tests/integration/targets/aci_esg_contract_master/tasks/main.yml +++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_esg_contract_master/tasks/main.yml @@ -4,13 +4,13 @@ # GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) - name: Test that we have an ACI APIC host, ACI username and ACI password - fail: + ansible.builtin.fail: msg: 'Please define the following variables: aci_hostname, aci_username and aci_password.' when: aci_hostname is not defined or aci_username is not defined or aci_password is not defined # CLEAN ENVIRONMENT - name: Set vars - set_fact: + ansible.builtin.set_fact: aci_info: &aci_info host: '{{ aci_hostname }}' username: '{{ aci_username }}' @@ -28,7 +28,7 @@ register: version - name: Verify Cloud and Non-Cloud Sites in use. - include_tasks: ../../../../../../integration/targets/aci_cloud_provider/tasks/main.yml + ansible.builtin.include_tasks: ../../../../../../integration/targets/aci_cloud_provider/tasks/main.yml - name: Ensure tenant - ansible_test does not exists before testing cisco.aci.aci_tenant: &tenant_absent @@ -88,7 +88,7 @@ register: cm_contract_esg_present - name: Assertions check for add an ESG contract master to web_esg with check mode - assert: + ansible.builtin.assert: that: - cm_contract_esg_present is changed - cm_contract_esg_present.current == [] @@ -102,7 +102,7 @@ register: nm_contract_esg_present - name: Assertions check for add an ESG contract master to web_esg with normal mode - assert: + ansible.builtin.assert: that: - nm_contract_esg_present is changed - nm_contract_esg_present.current | length == 1 @@ -115,7 +115,7 @@ register: idempotency_contract_esg_present - name: Idempotency assertions check for add an ESG contract master to web_esg with normal mode - assert: + ansible.builtin.assert: that: - idempotency_contract_esg_present is not changed - idempotency_contract_esg_present.current | length == 1 @@ -133,7 +133,7 @@ register: query_result_contract_master_esg - name: Assertions check for query an ESG contract master - assert: + ansible.builtin.assert: that: - query_result_contract_master_esg is not changed - query_result_contract_master_esg.current | length == 1 @@ -149,7 +149,7 @@ register: query_all_contract_master - name: Assertions check for query_all_contract_master - assert: + ansible.builtin.assert: that: - query_all_contract_master is not changed - query_all_contract_master.current | length == 1 @@ -168,7 +168,7 @@ register: cm_contract_esg_absent - name: Assertions check for remove an ESG contract master with check mode - assert: + ansible.builtin.assert: that: - cm_contract_esg_absent is changed - cm_contract_esg_absent.current != [] @@ -182,7 +182,7 @@ register: nm_contract_esg_absent - name: Assertions check for remove an ESG contract master with normal mode - assert: + ansible.builtin.assert: that: - nm_contract_esg_absent is changed - nm_contract_esg_absent.current == [] @@ -195,7 +195,7 @@ register: idempotency_contract_esg_absent - name: Idempotency assertions check for remove an ESG contract master with normal mode - assert: + ansible.builtin.assert: that: - idempotency_contract_esg_absent is not changed - idempotency_contract_esg_absent.current == [] diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_esg_epg_selector/tasks/main.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_esg_epg_selector/tasks/main.yml index 599828ae7..39087a37d 100644 --- a/ansible_collections/cisco/aci/tests/integration/targets/aci_esg_epg_selector/tasks/main.yml +++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_esg_epg_selector/tasks/main.yml @@ -4,13 +4,13 @@ # GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) - name: Test that we have an ACI APIC host, ACI username and ACI password - fail: + ansible.builtin.fail: msg: 'Please define the following variables: aci_hostname, aci_username and aci_password.' when: aci_hostname is not defined or aci_username is not defined or aci_password is not defined # SET VARS - name: Set vars - set_fact: + ansible.builtin.set_fact: aci_info: &aci_info host: '{{ aci_hostname }}' username: '{{ aci_username }}' @@ -28,7 +28,7 @@ register: version - name: Verify Cloud and Non-Cloud Sites in use. - include_tasks: ../../../../../../integration/targets/aci_cloud_provider/tasks/main.yml + ansible.builtin.include_tasks: ../../../../../../integration/targets/aci_cloud_provider/tasks/main.yml - name: Ensure tenant - ansible_test does not exists before testing cisco.aci.aci_tenant: &tenant_absent @@ -88,7 +88,7 @@ register: cm_epg_selector_present - name: Assertions check for add an EPG selector with check mode - assert: + ansible.builtin.assert: that: - cm_epg_selector_present is changed - cm_epg_selector_present.current | length == 0 @@ -101,7 +101,7 @@ register: nm_epg_selector_present - name: Assertions check for add an EPG selector with normal mode - assert: + ansible.builtin.assert: that: - nm_epg_selector_present is changed - nm_epg_selector_present.current | length == 1 @@ -114,7 +114,7 @@ register: cm_idempotency_epg_selector_present - name: Idempotency assertions check for add an EPG selector with check mode - assert: + ansible.builtin.assert: that: - cm_idempotency_epg_selector_present is not changed - cm_idempotency_epg_selector_present.current | length == 1 @@ -125,7 +125,7 @@ register: nm_idempotency_epg_selector_present - name: Idempotency assertions check for add an EPG selector with normal mode - assert: + ansible.builtin.assert: that: - nm_idempotency_epg_selector_present is not changed - nm_idempotency_epg_selector_present.current | length == 1 @@ -142,7 +142,7 @@ register: query_single_epg_selector - name: Assertions check for query an EPG selector with esg and epg name - assert: + ansible.builtin.assert: that: - query_single_epg_selector is not changed - query_single_epg_selector.current | length == 1 @@ -158,7 +158,7 @@ register: query_all_epg_selectors_under_ap - name: Assertions check for query all EPG selectors under an application profile - assert: + ansible.builtin.assert: that: - query_all_epg_selectors_under_ap is not changed - query_all_epg_selectors_under_ap.current | length == 1 @@ -173,7 +173,7 @@ register: query_all_epg_selectors - name: Assertions check for query all EPG selectors - assert: + ansible.builtin.assert: that: - query_all_epg_selectors is not changed - query_all_epg_selectors.current | length >= 1 @@ -191,7 +191,7 @@ register: cm_epg_selector_absent - name: Assertions check for remove an EPG selector with check mode - assert: + ansible.builtin.assert: that: - cm_epg_selector_absent is changed - cm_epg_selector_absent.current != [] @@ -204,7 +204,7 @@ register: nm_epg_selector_absent - name: Assertions check for remove an EPG selector with normal mode - assert: + ansible.builtin.assert: that: - nm_epg_selector_absent is changed - nm_epg_selector_absent.current == [] @@ -217,7 +217,7 @@ register: cm_idempotency_epg_selector_absent - name: Idempotency assertions check for EPG selector with check mode - assert: + ansible.builtin.assert: that: - cm_idempotency_epg_selector_absent is not changed - cm_idempotency_epg_selector_absent.current == [] @@ -228,7 +228,7 @@ register: nm_idempotency_epg_selector_absent - name: Idempotency assertions check for EPG selector with normal mode - assert: + ansible.builtin.assert: that: - nm_idempotency_epg_selector_absent is not changed - nm_idempotency_epg_selector_absent.current == [] diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_esg_ip_subnet_selector/tasks/main.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_esg_ip_subnet_selector/tasks/main.yml index f96391704..3564330aa 100644 --- a/ansible_collections/cisco/aci/tests/integration/targets/aci_esg_ip_subnet_selector/tasks/main.yml +++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_esg_ip_subnet_selector/tasks/main.yml @@ -4,13 +4,13 @@ # GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) - name: Test that we have an ACI APIC host, ACI username and ACI password - fail: + ansible.builtin.fail: msg: 'Please define the following variables: aci_hostname, aci_username and aci_password.' when: aci_hostname is not defined or aci_username is not defined or aci_password is not defined # SET VARS - name: Set vars - set_fact: + ansible.builtin.set_fact: aci_info: &aci_info host: '{{ aci_hostname }}' username: '{{ aci_username }}' @@ -28,7 +28,7 @@ register: version - name: Verify Cloud and Non-Cloud Sites in use. - include_tasks: ../../../../../../integration/targets/aci_cloud_provider/tasks/main.yml + ansible.builtin.include_tasks: ../../../../../../integration/targets/aci_cloud_provider/tasks/main.yml - name: Ensure tenant - ansible_test does not exists before testing cisco.aci.aci_tenant: &tenant_absent @@ -74,7 +74,7 @@ register: cm_subnet_ip_present - name: Assertions check for add IP Subnet selector with check mode - assert: + ansible.builtin.assert: that: - cm_subnet_ip_present is changed - cm_subnet_ip_present.current == [] @@ -87,7 +87,7 @@ register: nm_subnet_ip_present - name: Assertions check for add IP Subnet selector with normal mode - assert: + ansible.builtin.assert: that: - nm_subnet_ip_present is changed - nm_subnet_ip_present.current | length == 1 @@ -103,7 +103,7 @@ register: idempotency_nm_subnet_ip_present - name: Idempotency assertions check for add IP Subnet selectors with normal mode - assert: + ansible.builtin.assert: that: - idempotency_nm_subnet_ip_present is not changed - idempotency_nm_subnet_ip_present.current.0.fvEPSelector.attributes.matchExpression == "ip=='10.0.0.1'" @@ -118,7 +118,7 @@ register: query_result - name: Assertions check for query all IP Subnet selectors - assert: + ansible.builtin.assert: that: - query_result is not changed - query_result.current | length >= 1 @@ -131,7 +131,7 @@ register: cm_subnet_ip_absent - name: Assertions check for remove IP Subnet selector with check mode - assert: + ansible.builtin.assert: that: - cm_subnet_ip_absent is changed - cm_subnet_ip_absent.current != [] @@ -146,7 +146,7 @@ register: nm_subnet_ip_absent - name: Assertions check for remove IP Subnet selector with normal mode - assert: + ansible.builtin.assert: that: - nm_subnet_ip_absent is changed - nm_subnet_ip_absent.current == [] @@ -159,7 +159,7 @@ register: idempotency_nm_subnet_ip_absent - name: Idempotency assertions check for remove IP Subnet selector with normal mode - assert: + ansible.builtin.assert: that: - idempotency_nm_subnet_ip_absent is not changed - idempotency_nm_subnet_ip_absent.current == [] diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_esg_tag_selector/tasks/main.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_esg_tag_selector/tasks/main.yml index 5df3b0754..f48e5f38c 100644 --- a/ansible_collections/cisco/aci/tests/integration/targets/aci_esg_tag_selector/tasks/main.yml +++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_esg_tag_selector/tasks/main.yml @@ -4,13 +4,13 @@ # GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) - name: Test that we have an ACI APIC host, ACI username and ACI password - fail: + ansible.builtin.fail: msg: 'Please define the following variables: aci_hostname, aci_username and aci_password.' when: aci_hostname is not defined or aci_username is not defined or aci_password is not defined # SET VARS - name: Set vars - set_fact: + ansible.builtin.set_fact: aci_info: &aci_info host: '{{ aci_hostname }}' username: '{{ aci_username }}' @@ -28,7 +28,7 @@ register: version - name: Verify Cloud and Non-Cloud Sites in use. - include_tasks: ../../../../../../integration/targets/aci_cloud_provider/tasks/main.yml + ansible.builtin.include_tasks: ../../../../../../integration/targets/aci_cloud_provider/tasks/main.yml - name: Ensure tenant - ansible_test does not exists before testing cisco.aci.aci_tenant: &tenant_absent @@ -79,7 +79,7 @@ register: selector_0_nm_present - name: present assertions for Tag Selector - tag-selector-0 - assert: + ansible.builtin.assert: that: - selector_0_cm_present is changed - selector_0_nm_present is changed @@ -97,7 +97,7 @@ register: query_result - name: Verification of query all Tag Selectors - query_result - assert: + ansible.builtin.assert: that: - query_result is not changed - query_result.current | length >= 1 @@ -111,7 +111,7 @@ register: result_with_name_and_value - name: Verification of query - Tag Selectors with a name and value - assert: + ansible.builtin.assert: that: - result_with_name_and_value is not changed - result_with_name_and_value.current | length == 1 @@ -127,7 +127,7 @@ register: result_with_name - name: Verification of query - Tag Selectors with only name - assert: + ansible.builtin.assert: that: - result_with_name is not changed - result_with_name.current | length == 1 @@ -151,7 +151,7 @@ register: selector_0_nm_absent_with_name_and_value - name: Verification of selector_0_nm_absent_with_name - Tag Selectors under web_esg - assert: + ansible.builtin.assert: that: - selector_0_cm_absent_with_name_and_value is changed - selector_0_cm_absent_with_name_and_value.current | length == 1 @@ -166,7 +166,7 @@ register: idempotency_selector_0_nm_absent_with_name_and_value - name: Verification of idempotency_selector_0_nm_absent_with_name_and_value - Tag Selectors under web_esg - assert: + ansible.builtin.assert: that: - idempotency_selector_0_nm_absent_with_name_and_value is not changed - idempotency_selector_0_nm_absent_with_name_and_value.current | length == 0 diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_fabric_external_connection_profile/aliases b/ansible_collections/cisco/aci/tests/integration/targets/aci_fabric_external_connection_profile/aliases new file mode 100644 index 000000000..209b793f9 --- /dev/null +++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_fabric_external_connection_profile/aliases @@ -0,0 +1,2 @@ +# No ACI simulator yet, so not enabled +# unsupported diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_fabric_external_connection_profile/tasks/main.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_fabric_external_connection_profile/tasks/main.yml new file mode 100644 index 000000000..b51aaf08a --- /dev/null +++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_fabric_external_connection_profile/tasks/main.yml @@ -0,0 +1,222 @@ +# Test code for the ACI modules +# Copyright: (c) 2024, Samita Bhattacharjee (@samitab) + +# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) + +- name: Test that we have an ACI APIC host, ACI username and ACI password + ansible.builtin.fail: + msg: 'Please define the following variables: aci_hostname, aci_username and aci_password.' + when: aci_hostname is not defined or aci_username is not defined or aci_password is not defined + +# GET Credentials from the inventory +- name: Set vars + ansible.builtin.set_fact: + aci_info: &aci_info + host: "{{ aci_hostname }}" + username: "{{ aci_username }}" + password: "{{ aci_password }}" + validate_certs: "{{ aci_validate_certs | default(false) }}" + use_ssl: "{{ aci_use_ssl | default(true) }}" + use_proxy: "{{ aci_use_proxy | default(true) }}" + output_level: "{{ aci_output_level | default('info') }}" + +- name: Query system information + cisco.aci.aci_system: + <<: *aci_info + id: 1 + state: query + register: version + +- name: Verify Cloud and Non-Cloud Sites in use. + ansible.builtin.include_tasks: ../../../../../../integration/targets/aci_cloud_provider/tasks/main.yml + +- name: Execute tasks only for non-cloud sites + when: query_cloud.current == [] + block: + + # CLEAN ENVIRONMENT + - name: Ensure ansible_fabric_ext_conn_profile is absent before testing + cisco.aci.aci_fabric_external_connection_profile: &delete_fabric_external_connection_profile + <<: *aci_info + fabric_id: 1 + state: absent + + # CREATE FABRIC EXTERNAL CONNECTION PROFILE + - name: Create ansible_fabric_ext_conn_profile with check mode + cisco.aci.aci_fabric_external_connection_profile: &create_fabric_external_connection_profile + <<: *aci_info + fabric_id: "1" + name: "ansible_fabric_ext_conn_profile" + description: "Fabric External Connection Profile" + community: "extended:as2-nn4:5:16" + site_id: "1" + peering_type: "automatic_with_rr" + peering_password: "abcd" + state: present + check_mode: true + register: add_fabric_external_connection_profile_cm + + - name: Create ansible_fabric_ext_conn_profile + cisco.aci.aci_fabric_external_connection_profile: + <<: *create_fabric_external_connection_profile + state: present + register: add_fabric_external_connection_profile + + # CREATE FABRIC EXTERNAL CONNECTION PROFILE AGAIN TO TEST IDEMPOTENCE + - name: Create ansible_fabric_ext_conn_profile again + cisco.aci.aci_fabric_external_connection_profile: + <<: *create_fabric_external_connection_profile + state: present + register: add_fabric_external_connection_profile_again + + - name: Verify creation + ansible.builtin.assert: + that: + - add_fabric_external_connection_profile is changed + - add_fabric_external_connection_profile.previous == [] + - add_fabric_external_connection_profile.current.0.fvFabricExtConnP.attributes.dn == "uni/tn-infra/fabricExtConnP-1" + - add_fabric_external_connection_profile.current.0.fvFabricExtConnP.attributes.name == "ansible_fabric_ext_conn_profile" + - add_fabric_external_connection_profile.current.0.fvFabricExtConnP.attributes.descr == "Fabric External Connection Profile" + - add_fabric_external_connection_profile.current.0.fvFabricExtConnP.attributes.annotation == 'orchestrator:ansible' + - add_fabric_external_connection_profile.current.0.fvFabricExtConnP.attributes.rt == "extended:as2-nn4:5:16" + - add_fabric_external_connection_profile.current.0.fvFabricExtConnP.attributes.siteId == "1" + - add_fabric_external_connection_profile.current.0.fvFabricExtConnP.children.0.fvPeeringP.attributes.type == "automatic_with_rr" + - add_fabric_external_connection_profile.current.0.fvFabricExtConnP.children.0.fvPeeringP.attributes.password is undefined + - add_fabric_external_connection_profile_cm is changed + - add_fabric_external_connection_profile_cm.previous == [] + - add_fabric_external_connection_profile_cm.current == [] + - add_fabric_external_connection_profile_cm.proposed.fvFabricExtConnP.attributes.dn == "uni/tn-infra/fabricExtConnP-1" + - add_fabric_external_connection_profile_cm.proposed.fvFabricExtConnP.attributes.name == "ansible_fabric_ext_conn_profile" + - add_fabric_external_connection_profile_cm.proposed.fvFabricExtConnP.attributes.descr == "Fabric External Connection Profile" + - add_fabric_external_connection_profile_cm.proposed.fvFabricExtConnP.attributes.annotation == 'orchestrator:ansible' + - add_fabric_external_connection_profile_cm.proposed.fvFabricExtConnP.attributes.rt == "extended:as2-nn4:5:16" + - add_fabric_external_connection_profile_cm.proposed.fvFabricExtConnP.attributes.siteId == "1" + - add_fabric_external_connection_profile_cm.proposed.fvFabricExtConnP.children.0.fvPeeringP.attributes.type == "automatic_with_rr" + - add_fabric_external_connection_profile_cm.proposed.fvFabricExtConnP.children.0.fvPeeringP.attributes.password == "VALUE_SPECIFIED_IN_NO_LOG_PARAMETER" + - add_fabric_external_connection_profile_again is changed # Idempotence is not supported when peering_password is set + - add_fabric_external_connection_profile_again.current == add_fabric_external_connection_profile_again.previous + - add_fabric_external_connection_profile_again.current.0.fvFabricExtConnP.attributes.dn == "uni/tn-infra/fabricExtConnP-1" + - add_fabric_external_connection_profile_again.current.0.fvFabricExtConnP.attributes.name == "ansible_fabric_ext_conn_profile" + - add_fabric_external_connection_profile_again.current.0.fvFabricExtConnP.attributes.descr == "Fabric External Connection Profile" + - add_fabric_external_connection_profile_again.current.0.fvFabricExtConnP.attributes.annotation == 'orchestrator:ansible' + - add_fabric_external_connection_profile_again.current.0.fvFabricExtConnP.attributes.rt == "extended:as2-nn4:5:16" + - add_fabric_external_connection_profile_again.current.0.fvFabricExtConnP.attributes.siteId == "1" + - add_fabric_external_connection_profile_again.current.0.fvFabricExtConnP.children.0.fvPeeringP.attributes.type == "automatic_with_rr" + - add_fabric_external_connection_profile_again.current.0.fvFabricExtConnP.children.0.fvPeeringP.attributes.password is undefined + - add_fabric_external_connection_profile_again.previous.0.fvFabricExtConnP.attributes.dn == "uni/tn-infra/fabricExtConnP-1" + - add_fabric_external_connection_profile_again.previous.0.fvFabricExtConnP.attributes.name == "ansible_fabric_ext_conn_profile" + - add_fabric_external_connection_profile_again.previous.0.fvFabricExtConnP.attributes.descr == "Fabric External Connection Profile" + - add_fabric_external_connection_profile_again.previous.0.fvFabricExtConnP.attributes.rt == "extended:as2-nn4:5:16" + - add_fabric_external_connection_profile_again.previous.0.fvFabricExtConnP.attributes.siteId == "1" + - add_fabric_external_connection_profile_again.previous.0.fvFabricExtConnP.children.0.fvPeeringP.attributes.type == "automatic_with_rr" + - add_fabric_external_connection_profile_again.previous.0.fvFabricExtConnP.children.0.fvPeeringP.attributes.password is undefined + + # QUERY FABRIC EXTERNAL CONNECTION PROFILE + - name: Query fabric external connection profile + cisco.aci.aci_fabric_external_connection_profile: + <<: *aci_info + fabric_id: 1 + state: query + register: query_fabric_external_connection_profile + + # QUERY ALL FABRIC EXTERNAL CONNECTION PROFILE + - name: Query all fabric external connection profile + cisco.aci.aci_fabric_external_connection_profile: + <<: *aci_info + state: query + register: query_fabric_external_connection_profile_all + + - name: Verify query + ansible.builtin.assert: + that: + - query_fabric_external_connection_profile is not changed + - query_fabric_external_connection_profile.current.0.fvFabricExtConnP.attributes.dn == "uni/tn-infra/fabricExtConnP-1" + - query_fabric_external_connection_profile.current.0.fvFabricExtConnP.attributes.name == "ansible_fabric_ext_conn_profile" + - query_fabric_external_connection_profile.current.0.fvFabricExtConnP.attributes.descr == "Fabric External Connection Profile" + - query_fabric_external_connection_profile.current.0.fvFabricExtConnP.attributes.rt == "extended:as2-nn4:5:16" + - query_fabric_external_connection_profile.current.0.fvFabricExtConnP.attributes.siteId == "1" + - query_fabric_external_connection_profile.current.0.fvFabricExtConnP.children.0.fvPeeringP.attributes.type == "automatic_with_rr" + - query_fabric_external_connection_profile.current.0.fvFabricExtConnP.children.0.fvPeeringP.attributes.password is undefined + - query_fabric_external_connection_profile_all is not changed + - query_fabric_external_connection_profile_all.current | length == 1 + - query_fabric_external_connection_profile_all.current.0.fvFabricExtConnP.attributes.dn == "uni/tn-infra/fabricExtConnP-1" + - query_fabric_external_connection_profile_all.current.0.fvFabricExtConnP.attributes.name == "ansible_fabric_ext_conn_profile" + - query_fabric_external_connection_profile_all.current.0.fvFabricExtConnP.attributes.descr == "Fabric External Connection Profile" + - query_fabric_external_connection_profile_all.current.0.fvFabricExtConnP.attributes.rt == "extended:as2-nn4:5:16" + - query_fabric_external_connection_profile_all.current.0.fvFabricExtConnP.attributes.siteId == "1" + - query_fabric_external_connection_profile_all.current.0.fvFabricExtConnP.children.0.fvPeeringP.attributes.type == "automatic_with_rr" + - query_fabric_external_connection_profile_all.current.0.fvFabricExtConnP.children.0.fvPeeringP.attributes.password is undefined + + # UPDATE PEERING PROFILE + - name: Update ansible_fabric_ext_conn_profile peering password + cisco.aci.aci_fabric_external_connection_profile: + <<: *aci_info + fabric_id: "1" + peering_password: "abcd" + state: present + register: update_fabric_external_connection_profile_1 + + - name: Update ansible_fabric_ext_conn_profile peering type + cisco.aci.aci_fabric_external_connection_profile: + <<: *aci_info + fabric_id: "1" + peering_type: "automatic_with_full_mesh" + state: present + register: update_fabric_external_connection_profile_2 + + - name: Verity updates + ansible.builtin.assert: + that: + - update_fabric_external_connection_profile_1 is changed + - update_fabric_external_connection_profile_1.proposed.fvFabricExtConnP.children.0.fvPeeringP.attributes.password == "VALUE_SPECIFIED_IN_NO_LOG_PARAMETER" + - update_fabric_external_connection_profile_1.proposed.fvFabricExtConnP.children.0.fvPeeringP.attributes.type is undefined + - update_fabric_external_connection_profile_1.current.0.fvFabricExtConnP.children.0.fvPeeringP.attributes.type == "automatic_with_rr" + - update_fabric_external_connection_profile_2 is changed + - update_fabric_external_connection_profile_2.proposed.fvFabricExtConnP.children.0.fvPeeringP.attributes.password is undefined + - update_fabric_external_connection_profile_2.proposed.fvFabricExtConnP.children.0.fvPeeringP.attributes.type == "automatic_with_full_mesh" + - update_fabric_external_connection_profile_2.current.0.fvFabricExtConnP.children.0.fvPeeringP.attributes.type == "automatic_with_full_mesh" + - update_fabric_external_connection_profile_2.previous.0.fvFabricExtConnP.children.0.fvPeeringP.attributes.type == "automatic_with_rr" + + # DELETE FABRIC EXTERNAL CONNECTION PROFILE + - name: Delete ansible_fabric_ext_conn_profile with check mode + cisco.aci.aci_fabric_external_connection_profile: + <<: *delete_fabric_external_connection_profile + check_mode: true + register: delete_fabric_external_connection_profile_cm + + - name: Delete ansible_fabric_ext_conn_profile + cisco.aci.aci_fabric_external_connection_profile: + <<: *delete_fabric_external_connection_profile + register: delete_fabric_external_connection_profile + + # DELETE FABRIC EXTERNAL CONNECTION PROFILE AGAIN TO TEST IDEMPOTENCE + - name: Delete ansible_fabric_ext_conn_profile again + cisco.aci.aci_fabric_external_connection_profile: + <<: *delete_fabric_external_connection_profile + register: delete_fabric_external_connection_profile_again + + - name: Verify deletion + ansible.builtin.assert: + that: + - delete_fabric_external_connection_profile is changed + - delete_fabric_external_connection_profile.current == [] + - delete_fabric_external_connection_profile.previous.0.fvFabricExtConnP.attributes.dn == "uni/tn-infra/fabricExtConnP-1" + - delete_fabric_external_connection_profile.previous.0.fvFabricExtConnP.attributes.name == "ansible_fabric_ext_conn_profile" + - delete_fabric_external_connection_profile.previous.0.fvFabricExtConnP.attributes.descr == "Fabric External Connection Profile" + - delete_fabric_external_connection_profile.previous.0.fvFabricExtConnP.attributes.rt == "extended:as2-nn4:5:16" + - delete_fabric_external_connection_profile.previous.0.fvFabricExtConnP.attributes.siteId == "1" + - delete_fabric_external_connection_profile.previous.0.fvFabricExtConnP.children.0.fvPeeringP.attributes.type == "automatic_with_full_mesh" + - delete_fabric_external_connection_profile.previous.0.fvFabricExtConnP.children.0.fvPeeringP.attributes.password is undefined + - delete_fabric_external_connection_profile_cm is changed + - delete_fabric_external_connection_profile_cm.proposed == {} + - delete_fabric_external_connection_profile_cm.current != [] + - delete_fabric_external_connection_profile_cm.previous.0.fvFabricExtConnP.attributes.dn == "uni/tn-infra/fabricExtConnP-1" + - delete_fabric_external_connection_profile_cm.previous.0.fvFabricExtConnP.attributes.name == "ansible_fabric_ext_conn_profile" + - delete_fabric_external_connection_profile_cm.previous.0.fvFabricExtConnP.attributes.descr == "Fabric External Connection Profile" + - delete_fabric_external_connection_profile_cm.previous.0.fvFabricExtConnP.attributes.rt == "extended:as2-nn4:5:16" + - delete_fabric_external_connection_profile_cm.previous.0.fvFabricExtConnP.attributes.siteId == "1" + - delete_fabric_external_connection_profile_cm.previous.0.fvFabricExtConnP.children.0.fvPeeringP.attributes.type == "automatic_with_full_mesh" + - delete_fabric_external_connection_profile_cm.previous.0.fvFabricExtConnP.children.0.fvPeeringP.attributes.password is undefined + - delete_fabric_external_connection_profile_again is not changed + - delete_fabric_external_connection_profile_again.current == [] + - delete_fabric_external_connection_profile_again.previous == [] diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_fabric_external_routing_profile/aliases b/ansible_collections/cisco/aci/tests/integration/targets/aci_fabric_external_routing_profile/aliases new file mode 100644 index 000000000..209b793f9 --- /dev/null +++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_fabric_external_routing_profile/aliases @@ -0,0 +1,2 @@ +# No ACI simulator yet, so not enabled +# unsupported diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_fabric_external_routing_profile/tasks/main.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_fabric_external_routing_profile/tasks/main.yml new file mode 100644 index 000000000..8aa053186 --- /dev/null +++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_fabric_external_routing_profile/tasks/main.yml @@ -0,0 +1,278 @@ +# Test code for the ACI modules +# Copyright: (c) 2024, Samita Bhattacharjee (@samitab) + +# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) + +- name: Test that we have an ACI APIC host, ACI username and ACI password + ansible.builtin.fail: + msg: 'Please define the following variables: aci_hostname, aci_username and aci_password.' + when: aci_hostname is not defined or aci_username is not defined or aci_password is not defined + +# GET Credentials from the inventory +- name: Set vars + ansible.builtin.set_fact: + aci_info: &aci_info + host: "{{ aci_hostname }}" + username: "{{ aci_username }}" + password: "{{ aci_password }}" + validate_certs: "{{ aci_validate_certs | default(false) }}" + use_ssl: "{{ aci_use_ssl | default(true) }}" + use_proxy: "{{ aci_use_proxy | default(true) }}" + output_level: "{{ aci_output_level | default('info') }}" + +- name: Query system information + cisco.aci.aci_system: + <<: *aci_info + id: 1 + state: query + register: version + +- name: Verify Cloud and Non-Cloud Sites in use. + ansible.builtin.include_tasks: ../../../../../../integration/targets/aci_cloud_provider/tasks/main.yml + +- name: Execute tasks only for non-cloud sites + when: query_cloud.current == [] + block: + + # CLEAN ENVIRONMENT + - name: Ensure fabric external connection profile is absent before testing + cisco.aci.aci_fabric_external_connection_profile: &delete_fabric_external_connection_profile + <<: *aci_info + fabric_id: "1" + name: "ansible_fabric_ext_conn_profile" + community: "extended:as2-nn4:5:16" + state: absent + register: cleaned + + - name: Sleep for 15 seconds and continue + ansible.builtin.wait_for: + timeout: 15 + delegate_to: localhost + when: cleaned is changed + + - name: Ensure ansible_fabric_ext_routing_profile is absent before testing + cisco.aci.aci_fabric_external_routing_profile: &delete_fabric_external_routing_profile + <<: *aci_info + fabric_id: 1 + name: ansible_fabric_ext_routing_profile + state: absent + + - name: Create fabric external connection profile + cisco.aci.aci_fabric_external_connection_profile: + <<: *delete_fabric_external_connection_profile + state: present + + # CREATE FABRIC EXTERNAL ROUTING PROFILE + - name: Create ansible_fabric_ext_routing_profile with check mode + cisco.aci.aci_fabric_external_routing_profile: &create_fabric_external_routing_profile + <<: *aci_info + fabric_id: "1" + description: "Fabric external routing profile" + name: "ansible_fabric_ext_routing_profile" + subnets: + # Intentional duplicate subnet test + - 1.2.3.4/24 + - 1.2.3.4/24 + - 5.6.7.8/24 + state: present + check_mode: true + register: add_fabric_external_routing_profile_cm + + - name: Create ansible_fabric_ext_routing_profile + cisco.aci.aci_fabric_external_routing_profile: + <<: *create_fabric_external_routing_profile + state: present + register: add_fabric_external_routing_profile + + - name: Sleep for 15 seconds and continue + ansible.builtin.wait_for: + timeout: 15 + delegate_to: localhost + when: add_fabric_external_routing_profile is changed + + # CREATE FABRIC EXTERNAL ROUTING PROFILE AGAIN TO TEST IDEMPOTENCE + - name: Create ansible_fabric_ext_routing_profile again + cisco.aci.aci_fabric_external_routing_profile: + <<: *create_fabric_external_routing_profile + state: present + register: add_fabric_external_routing_profile_again + + - name: Verify creation + ansible.builtin.assert: + that: + - add_fabric_external_routing_profile is changed + - add_fabric_external_routing_profile.previous == [] + - add_fabric_external_routing_profile.current.0.l3extFabricExtRoutingP.attributes.dn == "uni/tn-infra/fabricExtConnP-1/fabricExtRoutingP-ansible_fabric_ext_routing_profile" + - add_fabric_external_routing_profile.current.0.l3extFabricExtRoutingP.attributes.descr == "Fabric external routing profile" + - add_fabric_external_routing_profile.current.0.l3extFabricExtRoutingP.attributes.annotation == 'orchestrator:ansible' + - add_fabric_external_routing_profile.current.0.l3extFabricExtRoutingP.attributes.name == "ansible_fabric_ext_routing_profile" + - add_fabric_external_routing_profile.current.0.l3extFabricExtRoutingP.children.1.l3extSubnet.attributes.ip == "1.2.3.4/24" + - add_fabric_external_routing_profile.current.0.l3extFabricExtRoutingP.children.0.l3extSubnet.attributes.ip == "5.6.7.8/24" + - add_fabric_external_routing_profile_cm is changed + - add_fabric_external_routing_profile_cm.previous == [] + - add_fabric_external_routing_profile_cm.current == [] + - add_fabric_external_routing_profile_cm.proposed.l3extFabricExtRoutingP.attributes.dn == "uni/tn-infra/fabricExtConnP-1/fabricExtRoutingP-ansible_fabric_ext_routing_profile" + - add_fabric_external_routing_profile_cm.proposed.l3extFabricExtRoutingP.attributes.descr == "Fabric external routing profile" + - add_fabric_external_routing_profile_cm.proposed.l3extFabricExtRoutingP.attributes.annotation == 'orchestrator:ansible' + - add_fabric_external_routing_profile_cm.proposed.l3extFabricExtRoutingP.attributes.name == "ansible_fabric_ext_routing_profile" + - add_fabric_external_routing_profile_cm.proposed.l3extFabricExtRoutingP.children.0.l3extSubnet.attributes.ip == "1.2.3.4/24" + - add_fabric_external_routing_profile_cm.proposed.l3extFabricExtRoutingP.children.1.l3extSubnet.attributes.ip == "5.6.7.8/24" + - add_fabric_external_routing_profile_again is not changed + - add_fabric_external_routing_profile_again.current == add_fabric_external_routing_profile_again.previous + - add_fabric_external_routing_profile_again.current.0.l3extFabricExtRoutingP.attributes.dn == "uni/tn-infra/fabricExtConnP-1/fabricExtRoutingP-ansible_fabric_ext_routing_profile" + - add_fabric_external_routing_profile_again.current.0.l3extFabricExtRoutingP.attributes.descr == "Fabric external routing profile" + - add_fabric_external_routing_profile_again.current.0.l3extFabricExtRoutingP.attributes.annotation == 'orchestrator:ansible' + - add_fabric_external_routing_profile_again.current.0.l3extFabricExtRoutingP.attributes.name == "ansible_fabric_ext_routing_profile" + - add_fabric_external_routing_profile_again.current.0.l3extFabricExtRoutingP.children.1.l3extSubnet.attributes.ip == "1.2.3.4/24" + - add_fabric_external_routing_profile_again.current.0.l3extFabricExtRoutingP.children.0.l3extSubnet.attributes.ip == "5.6.7.8/24" + - add_fabric_external_routing_profile_again.previous.0.l3extFabricExtRoutingP.attributes.dn == "uni/tn-infra/fabricExtConnP-1/fabricExtRoutingP-ansible_fabric_ext_routing_profile" + - add_fabric_external_routing_profile_again.previous.0.l3extFabricExtRoutingP.attributes.descr == "Fabric external routing profile" + - add_fabric_external_routing_profile_again.previous.0.l3extFabricExtRoutingP.attributes.name == "ansible_fabric_ext_routing_profile" + - add_fabric_external_routing_profile_again.previous.0.l3extFabricExtRoutingP.children.1.l3extSubnet.attributes.ip == "1.2.3.4/24" + - add_fabric_external_routing_profile_again.previous.0.l3extFabricExtRoutingP.children.0.l3extSubnet.attributes.ip == "5.6.7.8/24" + + # QUERY FABRIC EXTERNAL ROUTING PROFILE + - name: Query fabric external routing profile + cisco.aci.aci_fabric_external_routing_profile: + <<: *aci_info + fabric_id: 1 + name: ansible_fabric_ext_routing_profile + state: query + register: query_fabric_external_routing_profile + + # QUERY ALL FABRIC EXTERNAL ROUTING PROFILE + - name: Query all fabric external routing profile + cisco.aci.aci_fabric_external_routing_profile: + <<: *aci_info + state: query + register: query_fabric_external_routing_profile_all + + - name: Verify query + ansible.builtin.assert: + that: + - query_fabric_external_routing_profile is not changed + - query_fabric_external_routing_profile.current.0.l3extFabricExtRoutingP.attributes.dn == "uni/tn-infra/fabricExtConnP-1/fabricExtRoutingP-ansible_fabric_ext_routing_profile" + - query_fabric_external_routing_profile.current.0.l3extFabricExtRoutingP.attributes.descr == "Fabric external routing profile" + - query_fabric_external_routing_profile.current.0.l3extFabricExtRoutingP.attributes.name == "ansible_fabric_ext_routing_profile" + - query_fabric_external_routing_profile.current.0.l3extFabricExtRoutingP.children.1.l3extSubnet.attributes.ip == "1.2.3.4/24" + - query_fabric_external_routing_profile.current.0.l3extFabricExtRoutingP.children.0.l3extSubnet.attributes.ip == "5.6.7.8/24" + - query_fabric_external_routing_profile_all is not changed + - query_fabric_external_routing_profile_all.current | length == 1 + - query_fabric_external_routing_profile_all.current.0.l3extFabricExtRoutingP.attributes.dn == "uni/tn-infra/fabricExtConnP-1/fabricExtRoutingP-ansible_fabric_ext_routing_profile" + - query_fabric_external_routing_profile_all.current.0.l3extFabricExtRoutingP.attributes.descr == "Fabric external routing profile" + - query_fabric_external_routing_profile_all.current.0.l3extFabricExtRoutingP.attributes.name == "ansible_fabric_ext_routing_profile" + - query_fabric_external_routing_profile_all.current.0.l3extFabricExtRoutingP.children.1.l3extSubnet.attributes.ip == "1.2.3.4/24" + - query_fabric_external_routing_profile_all.current.0.l3extFabricExtRoutingP.children.0.l3extSubnet.attributes.ip == "5.6.7.8/24" + + # UPDATE SUBNETS + - name: Update fabric external routing profile - change subnets + cisco.aci.aci_fabric_external_routing_profile: + <<: *create_fabric_external_routing_profile + subnets: + - 5.6.7.8/24 + - 9.10.11.12/24 + state: present + register: update_fabric_external_routing_profile_1 + + - name: Sleep for 15 seconds and continue + ansible.builtin.wait_for: + timeout: 15 + delegate_to: localhost + + - name: Update fabric external routing profile - remove 1 subnet + cisco.aci.aci_fabric_external_routing_profile: + <<: *create_fabric_external_routing_profile + subnets: + - 9.10.11.12/24 + state: present + register: update_fabric_external_routing_profile_2 + + - name: Sleep for 15 seconds and continue + ansible.builtin.wait_for: + timeout: 15 + delegate_to: localhost + + - name: Update fabric external routing profile - remove all subnets + cisco.aci.aci_fabric_external_routing_profile: + <<: *create_fabric_external_routing_profile + subnets: null + state: present + register: update_fabric_external_routing_profile_3 + + - name: Sleep for 15 seconds and continue + ansible.builtin.wait_for: + timeout: 15 + delegate_to: localhost + + - name: Verify subnet update + ansible.builtin.assert: + that: + - update_fabric_external_routing_profile_1 is changed + - update_fabric_external_routing_profile_1.proposed.l3extFabricExtRoutingP.children | length == 3 + - update_fabric_external_routing_profile_1.proposed.l3extFabricExtRoutingP.children.0.l3extSubnet.attributes.ip == "1.2.3.4/24" + - update_fabric_external_routing_profile_1.proposed.l3extFabricExtRoutingP.children.0.l3extSubnet.attributes.status == "deleted" + - update_fabric_external_routing_profile_1.proposed.l3extFabricExtRoutingP.children.1.l3extSubnet.attributes.ip == "5.6.7.8/24" + - update_fabric_external_routing_profile_1.proposed.l3extFabricExtRoutingP.children.2.l3extSubnet.attributes.ip == "9.10.11.12/24" + - update_fabric_external_routing_profile_1.current.0.l3extFabricExtRoutingP.children | length == 2 + - update_fabric_external_routing_profile_1.current.0.l3extFabricExtRoutingP.children.1.l3extSubnet.attributes.ip == "5.6.7.8/24" + - update_fabric_external_routing_profile_1.current.0.l3extFabricExtRoutingP.children.0.l3extSubnet.attributes.ip == "9.10.11.12/24" + - update_fabric_external_routing_profile_2 is changed + - update_fabric_external_routing_profile_2.proposed.l3extFabricExtRoutingP.children | length == 2 + - update_fabric_external_routing_profile_2.proposed.l3extFabricExtRoutingP.children.0.l3extSubnet.attributes.ip == "5.6.7.8/24" + - update_fabric_external_routing_profile_2.proposed.l3extFabricExtRoutingP.children.0.l3extSubnet.attributes.status == "deleted" + - update_fabric_external_routing_profile_2.proposed.l3extFabricExtRoutingP.children.1.l3extSubnet.attributes.ip == "9.10.11.12/24" + - update_fabric_external_routing_profile_2.current.0.l3extFabricExtRoutingP.children | length == 1 + - update_fabric_external_routing_profile_2.current.0.l3extFabricExtRoutingP.children.0.l3extSubnet.attributes.ip == "9.10.11.12/24" + - update_fabric_external_routing_profile_3 is changed + - update_fabric_external_routing_profile_3.proposed.l3extFabricExtRoutingP.children | length == 1 + - update_fabric_external_routing_profile_3.proposed.l3extFabricExtRoutingP.children.0.l3extSubnet.attributes.ip == "9.10.11.12/24" + - update_fabric_external_routing_profile_3.proposed.l3extFabricExtRoutingP.children.0.l3extSubnet.attributes.status == "deleted" + - update_fabric_external_routing_profile_3.current.0.l3extFabricExtRoutingP.children is undefined + + # DELETE FABRIC EXTERNAL ROUTING PROFILE + - name: Delete ansible_fabric_ext_routing_profile with check mode + cisco.aci.aci_fabric_external_routing_profile: + <<: *delete_fabric_external_routing_profile + check_mode: true + register: delete_fabric_external_routing_profile_cm + + - name: Delete ansible_fabric_ext_routing_profile + cisco.aci.aci_fabric_external_routing_profile: + <<: *delete_fabric_external_routing_profile + register: delete_fabric_external_routing_profile + + - name: Sleep for 15 seconds and continue + ansible.builtin.wait_for: + timeout: 15 + delegate_to: localhost + when: delete_fabric_external_routing_profile is changed + + # DELETE FABRIC EXTERNAL ROUTING PROFILE AGAIN TO TEST IDEMPOTENCE + - name: Delete ansible_fabric_ext_routing_profile again + cisco.aci.aci_fabric_external_routing_profile: + <<: *delete_fabric_external_routing_profile + retries: 4 + delay: 5 + register: delete_fabric_external_routing_profile_again + + - name: Verify deletion + ansible.builtin.assert: + that: + - delete_fabric_external_routing_profile is changed + - delete_fabric_external_routing_profile.current == [] + - delete_fabric_external_routing_profile.previous.0.l3extFabricExtRoutingP.attributes.dn == "uni/tn-infra/fabricExtConnP-1/fabricExtRoutingP-ansible_fabric_ext_routing_profile" + - delete_fabric_external_routing_profile.previous.0.l3extFabricExtRoutingP.attributes.descr == "Fabric external routing profile" + - delete_fabric_external_routing_profile.previous.0.l3extFabricExtRoutingP.attributes.name == "ansible_fabric_ext_routing_profile" + - delete_fabric_external_routing_profile_cm is changed + - delete_fabric_external_routing_profile_cm.proposed == {} + - delete_fabric_external_routing_profile_cm.current != [] + - delete_fabric_external_routing_profile_cm.previous.0.l3extFabricExtRoutingP.attributes.dn == "uni/tn-infra/fabricExtConnP-1/fabricExtRoutingP-ansible_fabric_ext_routing_profile" + - delete_fabric_external_routing_profile_cm.previous.0.l3extFabricExtRoutingP.attributes.descr == "Fabric external routing profile" + - delete_fabric_external_routing_profile_cm.previous.0.l3extFabricExtRoutingP.attributes.name == "ansible_fabric_ext_routing_profile" + - delete_fabric_external_routing_profile_again is not changed + - delete_fabric_external_routing_profile_again.current == [] + - delete_fabric_external_routing_profile_again.previous == [] + + - name: Clean up fabric external connection profile + cisco.aci.aci_fabric_external_connection_profile: + <<: *delete_fabric_external_connection_profile \ No newline at end of file diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_fabric_interface_policy_group/tasks/main.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_fabric_interface_policy_group/tasks/main.yml index 9f871da6b..a591d6435 100644 --- a/ansible_collections/cisco/aci/tests/integration/targets/aci_fabric_interface_policy_group/tasks/main.yml +++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_fabric_interface_policy_group/tasks/main.yml @@ -4,13 +4,13 @@ # GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) - name: Test that we have an ACI APIC host, ACI username and ACI password - fail: + ansible.builtin.fail: msg: "Please define the following variables: aci_hostname, aci_username and aci_password." when: aci_hostname is not defined or aci_username is not defined or aci_password is not defined # SET VARS - name: Set vars - set_fact: + ansible.builtin.set_fact: aci_info: &aci_info host: "{{ aci_hostname }}" username: "{{ aci_username }}" @@ -28,21 +28,21 @@ register: version - name: Ensure leaf_policy_group does not exist - aci_fabric_interface_policy_group: + cisco.aci.aci_fabric_interface_policy_group: <<: *aci_info name: leaf_policy_group type: leaf state: absent - name: Ensure spine_policy_group does not exist - aci_fabric_interface_policy_group: + cisco.aci.aci_fabric_interface_policy_group: <<: *aci_info name: spine_policy_group type: spine state: absent - name: Add a leaf fabric interface policy group with check mode - aci_fabric_interface_policy_group: &cm_leaf_policy_group_present + cisco.aci.aci_fabric_interface_policy_group: &cm_leaf_policy_group_present <<: *aci_info name: leaf_policy_group type: leaf @@ -52,7 +52,7 @@ register: cm_leaf_policy_group_present - name: Add a leaf fabric interface policy group with normal mode - aci_fabric_interface_policy_group: &nm_leaf_policy_group_present + cisco.aci.aci_fabric_interface_policy_group: &nm_leaf_policy_group_present <<: *cm_leaf_policy_group_present dwdm_policy: default link_level_policy: default @@ -63,12 +63,12 @@ register: nm_leaf_policy_group_present - name: Add a leaf fabric interface policy group with normal mode again - aci_fabric_interface_policy_group: + cisco.aci.aci_fabric_interface_policy_group: <<: *nm_leaf_policy_group_present register: nm_leaf_policy_group_present_again - name: Add a spine fabric interface policy group with check mode - aci_fabric_interface_policy_group: &cm_spine_policy_group_present + cisco.aci.aci_fabric_interface_policy_group: &cm_spine_policy_group_present <<: *aci_info name: spine_policy_group type: spine @@ -87,7 +87,7 @@ when: version.current.0.topSystem.attributes.version is version('6.0(2h)', '>=') block: - name: Add a spine fabric interface policy group with transceiver_policy_tdn - aci_fabric_interface_policy_group: &tp_spine_policy_group_present + cisco.aci.aci_fabric_interface_policy_group: &tp_spine_policy_group_present <<: *aci_info name: spine_policy_group type: spine @@ -97,7 +97,7 @@ register: tp_spine_policy_group_present - name: Remove the transceiver_policy from the spine fabric interface policy group - aci_fabric_interface_policy_group: + cisco.aci.aci_fabric_interface_policy_group: <<: *aci_info name: spine_policy_group type: spine @@ -107,7 +107,7 @@ register: tp_spine_policy_group_absent - name: Assertions check for add fabric interface policy groups - assert: + ansible.builtin.assert: that: - tp_spine_policy_group_present is changed - tp_spine_policy_group_absent is changed @@ -115,17 +115,17 @@ - tp_spine_policy_group_absent.current.0.fabricSpPortPGrp.children | selectattr('fabricRsOpticsFabIfPol.attributes.tDn', 'defined') | selectattr('fabricRsOpticsFabIfPol.attributes.tDn', 'equalto', "") - name: Add a spine fabric interface policy group with normal mode - aci_fabric_interface_policy_group: + cisco.aci.aci_fabric_interface_policy_group: <<: *cm_spine_policy_group_present register: nm_spine_policy_group_present - name: Add a spine fabric interface policy group with normal mode again - aci_fabric_interface_policy_group: + cisco.aci.aci_fabric_interface_policy_group: <<: *cm_spine_policy_group_present register: nm_spine_policy_group_present_again - name: Update a spine fabric interface policy group with check mode - aci_fabric_interface_policy_group: &cm_spine_policy_group_update + cisco.aci.aci_fabric_interface_policy_group: &cm_spine_policy_group_update <<: *cm_spine_policy_group_present descr: spine_policy_group updated dwdm_policy: "" @@ -138,17 +138,17 @@ register: cm_spine_policy_group_update - name: Update a spine fabric interface policy group with normal mode - aci_fabric_interface_policy_group: + cisco.aci.aci_fabric_interface_policy_group: <<: *cm_spine_policy_group_update register: nm_spine_policy_group_update - name: Update a spine fabric interface policy group with normal mode again - aci_fabric_interface_policy_group: + cisco.aci.aci_fabric_interface_policy_group: <<: *cm_spine_policy_group_update register: nm_spine_policy_group_update_again - name: Assertions check for add fabric interface policy groups - assert: + ansible.builtin.assert: that: - cm_leaf_policy_group_present is changed - cm_leaf_policy_group_present.current == [] @@ -214,7 +214,7 @@ - nm_spine_policy_group_update_again.current.0.fabricSpPortPGrp.attributes.descr == "spine_policy_group updated" - name: Invalid test - add a fabric interface policy group without type - aci_fabric_interface_policy_group: + cisco.aci.aci_fabric_interface_policy_group: <<: *aci_info name: nt_spine_policy_group descr: negative test nt_spine_policy_group @@ -223,7 +223,7 @@ ignore_errors: true - name: Invalid test - add a fabric interface policy group without name - aci_fabric_interface_policy_group: + cisco.aci.aci_fabric_interface_policy_group: <<: *aci_info type: spine descr: negative test spine_policy_group @@ -232,7 +232,7 @@ ignore_errors: true - name: Assertions check for invalid test - add fabric interface policy groups - assert: + ansible.builtin.assert: that: - nt_without_type is not changed - nt_without_type.msg == "missing required arguments{{':'}} type" @@ -240,7 +240,7 @@ - nt_without_name.msg == "state is present but all of the following are missing{{':'}} name" - name: Query a leaf fabric interface policy group with name - aci_fabric_interface_policy_group: + cisco.aci.aci_fabric_interface_policy_group: <<: *aci_info name: leaf_policy_group type: leaf @@ -248,14 +248,14 @@ register: query_leaf_policy_group - name: Query all leaf fabric interface policy groups - aci_fabric_interface_policy_group: + cisco.aci.aci_fabric_interface_policy_group: <<: *aci_info type: leaf state: query register: query_all_leaf_policy_group - name: Query a spine fabric interface policy group with name - aci_fabric_interface_policy_group: + cisco.aci.aci_fabric_interface_policy_group: <<: *aci_info name: spine_policy_group type: spine @@ -263,14 +263,14 @@ register: query_a_spine_policy_group - name: Query all spine fabric interface policy groups - aci_fabric_interface_policy_group: + cisco.aci.aci_fabric_interface_policy_group: <<: *aci_info type: spine state: query register: query_all_spine_policy_group - name: Assertions check for query a fabric interface policy groups - assert: + ansible.builtin.assert: that: - query_leaf_policy_group is not changed - query_leaf_policy_group.current != [] @@ -290,41 +290,41 @@ - query_all_spine_policy_group.current | length >= 1 - name: Remove a leaf fabric interface policy group with check mode - aci_fabric_interface_policy_group: &cm_leaf_policy_group_absent + cisco.aci.aci_fabric_interface_policy_group: &cm_leaf_policy_group_absent <<: *cm_leaf_policy_group_present state: absent check_mode: true register: cm_leaf_policy_group_absent - name: Remove a leaf fabric interface policy group with normal mode - aci_fabric_interface_policy_group: + cisco.aci.aci_fabric_interface_policy_group: <<: *cm_leaf_policy_group_absent register: nm_leaf_policy_group_absent - name: Remove a leaf fabric interface policy group with normal mode again - aci_fabric_interface_policy_group: + cisco.aci.aci_fabric_interface_policy_group: <<: *cm_leaf_policy_group_absent register: nm_leaf_policy_group_absent_again - name: Remove a spine fabric interface policy group with check mode - aci_fabric_interface_policy_group: &cm_spine_policy_group_absent + cisco.aci.aci_fabric_interface_policy_group: &cm_spine_policy_group_absent <<: *cm_spine_policy_group_present state: absent check_mode: true register: cm_spine_policy_group_absent - name: Remove a spine fabric interface policy group with normal mode - aci_fabric_interface_policy_group: + cisco.aci.aci_fabric_interface_policy_group: <<: *cm_spine_policy_group_absent register: nm_spine_policy_group_absent - name: Remove a spine fabric interface policy group with normal mode again - aci_fabric_interface_policy_group: + cisco.aci.aci_fabric_interface_policy_group: <<: *cm_spine_policy_group_absent register: nm_spine_policy_group_absent_again - name: Assertions check for remove a fabric interface policy groups - assert: + ansible.builtin.assert: that: - cm_leaf_policy_group_absent is changed - cm_leaf_policy_group_absent.current != [] diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_fabric_leaf_profile/tasks/main.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_fabric_leaf_profile/tasks/main.yml index d4bf60dd5..6fb60c923 100644 --- a/ansible_collections/cisco/aci/tests/integration/targets/aci_fabric_leaf_profile/tasks/main.yml +++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_fabric_leaf_profile/tasks/main.yml @@ -4,13 +4,13 @@ # GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) - name: Test that we have an ACI APIC host, ACI username and ACI password - fail: + ansible.builtin.fail: msg: 'Please define the following variables: aci_hostname, aci_username and aci_password.' when: aci_hostname is not defined or aci_username is not defined or aci_password is not defined # GET Credentials from the inventory - name: Set vars - set_fact: + ansible.builtin.set_fact: aci_info: &aci_info host: "{{ aci_hostname }}" username: "{{ aci_username }}" @@ -22,21 +22,21 @@ # CLEAN ENVIRONMENT - name: Remove ansible_leaf_switch_prf if it already exists - aci_fabric_leaf_profile: + cisco.aci.aci_fabric_leaf_profile: <<: *aci_info name: ansible_leaf_switch_prf state: absent # CREATE SPINE SWITCH POLICY - name: Create ansible_leaf_switch_prf - aci_fabric_leaf_profile: + cisco.aci.aci_fabric_leaf_profile: <<: *aci_info name: ansible_leaf_switch_prf state: present register: add_switch_prf - name: Verify profile creation - assert: + ansible.builtin.assert: that: - add_switch_prf.current.0.fabricLeafP.attributes.dn == "uni/fabric/leprof-ansible_leaf_switch_prf" - add_switch_prf.current.0.fabricLeafP.attributes.name == "ansible_leaf_switch_prf" @@ -44,14 +44,14 @@ # CREATE SPINE SWITCH POLICY AGAIN TO TEST IDEMPOTENCE - name: Create ansible_leaf_switch_prf again - aci_fabric_leaf_profile: + cisco.aci.aci_fabric_leaf_profile: <<: *aci_info name: ansible_leaf_switch_prf state: present register: add_switch_prf_again - name: Verify profile creation idempotence - assert: + ansible.builtin.assert: that: - add_switch_prf_again is not changed - add_switch_prf_again.current.0.fabricLeafP.attributes.dn == "uni/fabric/leprof-ansible_leaf_switch_prf" @@ -59,14 +59,14 @@ # QUERY SPINE SWITCH POLICY - name: query leaf switch profile - aci_fabric_leaf_profile: + cisco.aci.aci_fabric_leaf_profile: <<: *aci_info name: ansible_leaf_switch_prf state: query register: query_switch_prf - name: Verify profile query - assert: + ansible.builtin.assert: that: - query_switch_prf is not changed - query_switch_prf.current.0.fabricLeafP.attributes.dn == "uni/fabric/leprof-ansible_leaf_switch_prf" @@ -74,26 +74,26 @@ # QUERY ALL SPINE SWITCH POLICIES - name: query all leaf switch profiles - aci_fabric_leaf_profile: + cisco.aci.aci_fabric_leaf_profile: <<: *aci_info state: query register: query_switch_prf_all - name: Verify profile query idempotence - assert: + ansible.builtin.assert: that: - query_switch_prf_all is not changed # DELETE SPINE SWITCH PROFILE - name: Delete ansible_leaf_switch_prf - aci_fabric_leaf_profile: + cisco.aci.aci_fabric_leaf_profile: <<: *aci_info name: ansible_leaf_switch_prf state: absent register: delete_switch_prf - name: Verify profile deletion - assert: + ansible.builtin.assert: that: - delete_switch_prf is changed - delete_switch_prf.current == [] @@ -102,21 +102,21 @@ # DELETE SPINE SWITCH PROFILE AGAIN TO TEST IDEMPOTENCE - name: Delete ansible_leaf_switch_prf again - aci_fabric_leaf_profile: + cisco.aci.aci_fabric_leaf_profile: <<: *aci_info name: ansible_leaf_switch_prf state: absent register: delete_switch_prf_again - name: Verify profile deletion idempotence - assert: + ansible.builtin.assert: that: - delete_switch_prf_again is not changed - delete_switch_prf_again.current == [] # CLEAN UP ENVIRONMENT - name: Remove ansible_leaf_switch_prf - aci_fabric_leaf_profile: + cisco.aci.aci_fabric_leaf_profile: <<: *aci_info name: ansible_leaf_switch_prf state: absent diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_fabric_leaf_switch_assoc/tasks/main.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_fabric_leaf_switch_assoc/tasks/main.yml index 35caafdb3..68050b8d0 100644 --- a/ansible_collections/cisco/aci/tests/integration/targets/aci_fabric_leaf_switch_assoc/tasks/main.yml +++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_fabric_leaf_switch_assoc/tasks/main.yml @@ -4,13 +4,13 @@ # GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) - name: Test that we have an ACI APIC host, ACI username and ACI password - fail: + ansible.builtin.fail: msg: 'Please define the following variables: aci_hostname, aci_username and aci_password.' when: aci_hostname is not defined or aci_username is not defined or aci_password is not defined # GET Credentials from the inventory - name: Set vars - set_fact: + ansible.builtin.set_fact: aci_info: &aci_info host: "{{ aci_hostname }}" username: "{{ aci_username }}" @@ -22,21 +22,21 @@ # CLEAN ENVIRONMENT - name: Remove ansible_leaf_switch_prf if it already exists - aci_fabric_leaf_profile: + cisco.aci.aci_fabric_leaf_profile: <<: *aci_info name: ansible_leaf_switch_prf state: absent # CREATE SPINE SWITCH POLICY - name: Create ansible_leaf_switch_prf - aci_fabric_leaf_profile: + cisco.aci.aci_fabric_leaf_profile: <<: *aci_info name: ansible_leaf_switch_prf state: present # CREATE SPINE SWITCH ASSOCIATION - name: Create a leaf switch profile association - aci_fabric_leaf_switch_assoc: + cisco.aci.aci_fabric_leaf_switch_assoc: <<: *aci_info profile: ansible_leaf_switch_prf name: ansible_leaf_switch_assoc @@ -45,7 +45,7 @@ register: add_association - name: Verify association creation - assert: + ansible.builtin.assert: that: - add_association.current.0.fabricLeafS.attributes.dn == "uni/fabric/leprof-ansible_leaf_switch_prf/leaves-ansible_leaf_switch_assoc-typ-range" - add_association.current.0.fabricLeafS.attributes.name == "ansible_leaf_switch_assoc" @@ -53,13 +53,13 @@ - add_association.current.0.fabricLeafS.attributes.annotation == 'orchestrator:ansible' - name: Verify Policy Group association - assert: + ansible.builtin.assert: that: - add_association.current.0.fabricLeafS.children.0.fabricRsLeNodePGrp.attributes.tDn == "uni/fabric/funcprof/lenodepgrp-ansible_leaf_pol_grp1" # CREATE SPINE SWITCH ASSOCIATION AGAIN TO TEST IDEMPOTENCE - name: Create a leaf switch profile association again - aci_fabric_leaf_switch_assoc: + cisco.aci.aci_fabric_leaf_switch_assoc: <<: *aci_info profile: ansible_leaf_switch_prf name: ansible_leaf_switch_assoc @@ -68,7 +68,7 @@ register: add_association_again - name: Verify association creation idempotence - assert: + ansible.builtin.assert: that: - add_association_again is not changed - add_association_again.current.0.fabricLeafS.attributes.dn == "uni/fabric/leprof-ansible_leaf_switch_prf/leaves-ansible_leaf_switch_assoc-typ-range" @@ -76,13 +76,13 @@ - add_association_again.current.0.fabricLeafS.attributes.type == "range" - name: Verify Policy Group association idempotence - assert: + ansible.builtin.assert: that: - add_association_again.current.0.fabricLeafS.children.0.fabricRsLeNodePGrp.attributes.tDn == "uni/fabric/funcprof/lenodepgrp-ansible_leaf_pol_grp1" # CREATE SPINE SWITCH ASSOCIATION WITHOUT POLICY GROUP - name: Create a leaf switch profile association without a policy group - aci_fabric_leaf_switch_assoc: + cisco.aci.aci_fabric_leaf_switch_assoc: <<: *aci_info profile: ansible_leaf_switch_prf name: ansible_leaf_switch_assoc2 @@ -90,7 +90,7 @@ register: add_association_without_policy_group - name: Verify association creation - assert: + ansible.builtin.assert: that: - add_association_without_policy_group.current.0.fabricLeafS.attributes.dn == "uni/fabric/leprof-ansible_leaf_switch_prf/leaves-ansible_leaf_switch_assoc2-typ-range" - add_association_without_policy_group.current.0.fabricLeafS.attributes.name == "ansible_leaf_switch_assoc2" @@ -98,7 +98,7 @@ # UPDATE SPINE SWITCH POLICY GROUP ASSOCIATION - name: Update a leaf switch profile association - aci_fabric_leaf_switch_assoc: + cisco.aci.aci_fabric_leaf_switch_assoc: <<: *aci_info profile: ansible_leaf_switch_prf name: ansible_leaf_switch_assoc @@ -107,7 +107,7 @@ register: update_association - name: Verify association update - assert: + ansible.builtin.assert: that: - update_association is changed - update_association.current.0.fabricLeafS.attributes.dn == "uni/fabric/leprof-ansible_leaf_switch_prf/leaves-ansible_leaf_switch_assoc-typ-range" @@ -115,13 +115,13 @@ - update_association.current.0.fabricLeafS.attributes.type == "range" - name: Verify Policy Group association update - assert: + ansible.builtin.assert: that: - update_association.current.0.fabricLeafS.children.0.fabricRsLeNodePGrp.attributes.tDn == "uni/fabric/funcprof/lenodepgrp-ansible_leaf_pol_grp2" # QUERY SPINE SWITCH ASSOCIATION - name: Query leaf switch profile association - aci_fabric_leaf_switch_assoc: + cisco.aci.aci_fabric_leaf_switch_assoc: <<: *aci_info profile: ansible_leaf_switch_prf name: ansible_leaf_switch_assoc @@ -129,7 +129,7 @@ register: query_association - name: Verify query data - assert: + ansible.builtin.assert: that: - query_association is not changed - query_association.current.0.fabricLeafS.attributes.dn == "uni/fabric/leprof-ansible_leaf_switch_prf/leaves-ansible_leaf_switch_assoc-typ-range" @@ -137,25 +137,25 @@ - query_association.current.0.fabricLeafS.attributes.type == "range" - name: Verify Policy Group association - assert: + ansible.builtin.assert: that: - query_association.current.0.fabricLeafS.children.0.fabricRsLeNodePGrp.attributes.tDn == "uni/fabric/funcprof/lenodepgrp-ansible_leaf_pol_grp2" # QUERY ALL SPINE SWITCH ASSOCIATIONS - name: Query leaf switch profile association - aci_fabric_leaf_switch_assoc: + cisco.aci.aci_fabric_leaf_switch_assoc: <<: *aci_info state: query register: query_association_all - name: Verify query all idempotence - assert: + ansible.builtin.assert: that: - query_association_all is not changed # DELETE SPINE SWITCH ASSOCIATION - name: Delete leaf switch profile association - aci_fabric_leaf_switch_assoc: + cisco.aci.aci_fabric_leaf_switch_assoc: <<: *aci_info profile: ansible_leaf_switch_prf name: ansible_leaf_switch_assoc @@ -163,7 +163,7 @@ register: delete_association - name: Verify association removal - assert: + ansible.builtin.assert: that: - delete_association is changed - delete_association.current == [] @@ -173,7 +173,7 @@ # DELETE SPINE SWITCH ASSOCIATION AGAIN TO TEST IDEMPOTENCE - name: Delete leaf switch profile association again - aci_fabric_leaf_switch_assoc: + cisco.aci.aci_fabric_leaf_switch_assoc: <<: *aci_info profile: ansible_leaf_switch_prf name: ansible_leaf_switch_assoc @@ -181,14 +181,14 @@ register: delete_association_again - name: Verify association removal idempotence - assert: + ansible.builtin.assert: that: - delete_association_again is not changed - delete_association_again.current == [] # CLEAN UP ENVIRONMENT - name: Remove ansible_leaf_switch_prf - aci_fabric_leaf_profile: + cisco.aci.aci_fabric_leaf_profile: <<: *aci_info name: ansible_leaf_switch_prf state: absent diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_fabric_management_access/aliases b/ansible_collections/cisco/aci/tests/integration/targets/aci_fabric_management_access/aliases new file mode 100644 index 000000000..209b793f9 --- /dev/null +++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_fabric_management_access/aliases @@ -0,0 +1,2 @@ +# No ACI simulator yet, so not enabled +# unsupported diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_fabric_management_access/pki/admin.crt b/ansible_collections/cisco/aci/tests/integration/targets/aci_fabric_management_access/pki/admin.crt new file mode 100644 index 000000000..cfac5531e --- /dev/null +++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_fabric_management_access/pki/admin.crt @@ -0,0 +1,14 @@ +-----BEGIN CERTIFICATE----- +MIICODCCAaGgAwIBAgIJAIt8XMntue0VMA0GCSqGSIb3DQEBCwUAMDQxDjAMBgNV +BAMMBUFkbWluMRUwEwYDVQQKDAxZb3VyIENvbXBhbnkxCzAJBgNVBAYTAlVTMCAX +DTE4MDEwOTAwNTk0NFoYDzIxMTcxMjE2MDA1OTQ0WjA0MQ4wDAYDVQQDDAVBZG1p +bjEVMBMGA1UECgwMWW91ciBDb21wYW55MQswCQYDVQQGEwJVUzCBnzANBgkqhkiG +9w0BAQEFAAOBjQAwgYkCgYEAohG/7axtt7CbSaMP7r+2mhTKbNgh0Ww36C7Ta14i +v+VmLyKkQHnXinKGhp6uy3Nug+15a+eIu7CrgpBVMQeCiWfsnwRocKcQJWIYDrWl +XHxGQn31yYKR6mylE7Dcj3rMFybnyhezr5D8GcP85YRPmwG9H2hO/0Y1FUnWu9Iw +AQkCAwEAAaNQME4wHQYDVR0OBBYEFD0jLXfpkrU/ChzRvfruRs/fy1VXMB8GA1Ud +IwQYMBaAFD0jLXfpkrU/ChzRvfruRs/fy1VXMAwGA1UdEwQFMAMBAf8wDQYJKoZI +hvcNAQELBQADgYEAOmvre+5tgZ0+F3DgsfxNQqLTrGiBgGCIymPkP/cBXXkNuJyl +3ac7tArHQc7WEA4U2R2rZbEq8FC3UJJm4nUVtCPvEh3G9OhN2xwYev79yt6pIn/l +KU0Td2OpVyo0eLqjoX5u2G90IBWzhyjFbo+CcKMrSVKj1YOdG0E3OuiJf00= +-----END CERTIFICATE----- diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_fabric_management_access/pki/admin.key b/ansible_collections/cisco/aci/tests/integration/targets/aci_fabric_management_access/pki/admin.key new file mode 100644 index 000000000..63bb00cc0 --- /dev/null +++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_fabric_management_access/pki/admin.key @@ -0,0 +1,16 @@ +-----BEGIN PRIVATE KEY----- +MIICdwIBADANBgkqhkiG9w0BAQEFAASCAmEwggJdAgEAAoGBAKIRv+2sbbewm0mj +D+6/tpoUymzYIdFsN+gu02teIr/lZi8ipEB514pyhoaerstzboPteWvniLuwq4KQ +VTEHgoln7J8EaHCnECViGA61pVx8RkJ99cmCkepspROw3I96zBcm58oXs6+Q/BnD +/OWET5sBvR9oTv9GNRVJ1rvSMAEJAgMBAAECgYByu3QO0qF9h7X3JEu0Ld4cKBnB +giQ2uJC/et7KxIJ/LOvw9GopBthyt27KwG1ntBkJpkTuAaQHkyNns7vLkNB0S0IR ++owVFEcKYq9VCHTaiQU8TDp24gN+yPTrpRuH8YhDVq5SfVdVuTMgHVQdj4ya4VlF +Gj+a7+ipxtGiLsVGrQJBAM7p0Fm0xmzi+tBOASUAcVrPLcteFIaTBFwfq16dm/ON +00Khla8Et5kMBttTbqbukl8mxFjBEEBlhQqb6EdQQ0sCQQDIhHx1a9diG7y/4DQA +4KvR3FCYwP8PBORlSamegzCo+P1OzxiEo0amX7yQMA5UyiP/kUsZrme2JBZgna8S +p4R7AkEAr7rMhSOPUnMD6V4WgsJ5g1Jp5kqkzBaYoVUUSms5RASz4+cwJVCwTX91 +Y1jcpVIBZmaaY3a0wrx13ajEAa0dOQJBAIpjnb4wqpsEh7VpmJqOdSdGxb1XXfFQ +sA0T1OQYqQnFppWwqrxIL+d9pZdiA1ITnNqyvUFBNETqDSOrUHwwb2cCQGArE+vu +ffPUWQ0j+fiK+covFG8NL7H+26NSGB5+Xsn9uwOGLj7K/YT6CbBtr9hJiuWjM1Al +0V4ltlTuu2mTMaw= +-----END PRIVATE KEY----- diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_fabric_management_access/tasks/main.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_fabric_management_access/tasks/main.yml new file mode 100644 index 000000000..d5f90d95d --- /dev/null +++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_fabric_management_access/tasks/main.yml @@ -0,0 +1,328 @@ +# Test code for the ACI modules +# Copyright: (c) 2024, Akini Ross (@akinross) + +# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) + +- name: Test that we have an ACI APIC host, ACI username and ACI password + ansible.builtin.fail: + msg: "Please define the following variables: aci_hostname, aci_username and aci_password." + when: aci_hostname is not defined or aci_username is not defined or aci_password is not defined + +# SET VARS +- name: Set vars + ansible.builtin.set_fact: + aci_info: &aci_info + host: "{{ aci_hostname }}" + username: "{{ aci_username }}" + password: "{{ aci_password }}" + validate_certs: "{{ aci_validate_certs | default(false) }}" + use_ssl: "{{ aci_use_ssl | default(true) }}" + use_proxy: "{{ aci_use_proxy | default(true) }}" + output_level: "{{ aci_output_level | default('info') }}" + +- name: Query system information to fetch version + cisco.aci.aci_system: + <<: *aci_info + id: 1 + state: query + register: version + +# CLEAN ENVIRONMENT +- name: Clean environment + cisco.aci.aci_fabric_management_access: &aci_fabric_management_access_1_absent + <<: *aci_info + name: fabric_management_access_policy_1 + state: absent + +- name: Ensure certificate_authority_1 exists + cisco.aci.aci_aaa_certificate_authority: &certificate_authority_1 + <<: *aci_info + name: certificate_authority_1 + certificate_chain: "{{ lookup('file', 'pki/admin.crt') }}" + state: present + +- name: Ensure key_ring_1 exists + cisco.aci.aci_aaa_key_ring: &key_ring_1 + <<: *aci_info + name: key_ring_1 + certificate: "{{ lookup('file', 'pki/admin.crt') }}" + certificate_authority: certificate_authority_1 + key: "{{ lookup('file', 'pki/admin.key') }}" + state: present + register: create_key_ring_1 + until: create_key_ring_1 is not failed + delay: 2 + retries: 4 + +# CREATE +- name: Create a new fabric management access policy (check_mode) + cisco.aci.aci_fabric_management_access: &aci_fabric_management_access_1_present + <<: *aci_fabric_management_access_1_absent + description: "This is a example Fabric Management Access policy." + state: present + check_mode: true + register: cm_create_fabric_management_access_policy_1 + +- name: Create a new fabric management access policy + cisco.aci.aci_fabric_management_access: + <<: *aci_fabric_management_access_1_present + register: nm_create_fabric_management_access_policy_1 + +- name: Create a new fabric management access policy again + cisco.aci.aci_fabric_management_access: + <<: *aci_fabric_management_access_1_present + register: nm_create_fabric_management_access_policy_1_again + +- name: Assertions for creating a fabric management access policy + ansible.builtin.assert: + that: + - cm_create_fabric_management_access_policy_1 is changed + - cm_create_fabric_management_access_policy_1.previous == [] + - cm_create_fabric_management_access_policy_1.current == [] + - cm_create_fabric_management_access_policy_1.proposed.commPol.attributes.name == "fabric_management_access_policy_1" + - cm_create_fabric_management_access_policy_1.proposed.commPol.attributes.descr == "This is a example Fabric Management Access policy." + - nm_create_fabric_management_access_policy_1 is changed + - nm_create_fabric_management_access_policy_1.previous == [] + - nm_create_fabric_management_access_policy_1.current.0.commPol.attributes.name == "fabric_management_access_policy_1" + - nm_create_fabric_management_access_policy_1.current.0.commPol.attributes.descr == "This is a example Fabric Management Access policy." + - nm_create_fabric_management_access_policy_1.current.0.commPol.children.0.commShellinabox.attributes.adminSt == "disabled" + - nm_create_fabric_management_access_policy_1.current.0.commPol.children.1.commSsh.attributes.adminSt == "enabled" + - nm_create_fabric_management_access_policy_1.current.0.commPol.children.2.commTelnet.attributes.adminSt == "disabled" + - nm_create_fabric_management_access_policy_1.current.0.commPol.children.3.commHttps.attributes.adminSt == "enabled" + - nm_create_fabric_management_access_policy_1.current.0.commPol.children.4.commHttp.attributes.adminSt == "disabled" + - nm_create_fabric_management_access_policy_1_again is not changed + - nm_create_fabric_management_access_policy_1_again.previous.0.commPol.attributes.name == "fabric_management_access_policy_1" + - nm_create_fabric_management_access_policy_1_again.previous.0.commPol.attributes.descr == "This is a example Fabric Management Access policy." + - nm_create_fabric_management_access_policy_1_again.previous.0.commPol.children.0.commShellinabox.attributes.adminSt == "disabled" + - nm_create_fabric_management_access_policy_1_again.previous.0.commPol.children.1.commSsh.attributes.adminSt == "enabled" + - nm_create_fabric_management_access_policy_1_again.previous.0.commPol.children.2.commTelnet.attributes.adminSt == "disabled" + - nm_create_fabric_management_access_policy_1_again.previous.0.commPol.children.3.commHttps.attributes.adminSt == "enabled" + - nm_create_fabric_management_access_policy_1_again.previous.0.commPol.children.4.commHttp.attributes.adminSt == "disabled" + - nm_create_fabric_management_access_policy_1_again.current.0.commPol.attributes.name == "fabric_management_access_policy_1" + - nm_create_fabric_management_access_policy_1_again.current.0.commPol.attributes.descr == "This is a example Fabric Management Access policy." + - nm_create_fabric_management_access_policy_1_again.current.0.commPol.children.0.commShellinabox.attributes.adminSt == "disabled" + - nm_create_fabric_management_access_policy_1_again.current.0.commPol.children.1.commSsh.attributes.adminSt == "enabled" + - nm_create_fabric_management_access_policy_1_again.current.0.commPol.children.2.commTelnet.attributes.adminSt == "disabled" + - nm_create_fabric_management_access_policy_1_again.current.0.commPol.children.3.commHttps.attributes.adminSt == "enabled" + - nm_create_fabric_management_access_policy_1_again.current.0.commPol.children.4.commHttp.attributes.adminSt == "disabled" + +# UPDATE +- name: Update an existing fabric management access policy description + cisco.aci.aci_fabric_management_access: + <<: *aci_fabric_management_access_1_present + description: "This is a changed description." + register: nm_update_fabric_management_access_policy_1_change_description + +- name: Assertions for updating a fabric management access policy description + ansible.builtin.assert: + that: + - nm_update_fabric_management_access_policy_1_change_description is changed + - nm_update_fabric_management_access_policy_1_change_description.previous.0.commPol.attributes.descr == "This is a example Fabric Management Access policy." + - nm_update_fabric_management_access_policy_1_change_description.previous.0.commPol.attributes.name == "fabric_management_access_policy_1" + - nm_update_fabric_management_access_policy_1_change_description.current.0.commPol.attributes.descr == "This is a changed description." + - nm_update_fabric_management_access_policy_1_change_description.current.0.commPol.attributes.name == "fabric_management_access_policy_1" + +- name: Update an existing fabric management access policy telnet, ssh, ssh_web, http, and https configuration + cisco.aci.aci_fabric_management_access: + <<: *aci_fabric_management_access_1_present + telnet: + admin_state: enabled + port: 25 + ssh: + admin_state: enabled + password_auth_state: enabled + port: 20 + ciphers: + - aes128_ctr + - aes192_ctr + - aes256_ctr + kex: + - dh_sha1 + - ecdh_521 + macs: + - sha2_256 + - sha2_512 + ssh_web: + admin_state: enabled + http: + admin_state: enabled + port: 85 + allow_origins: http://127.0.0.1:8000 + allow_credentials: enabled + throttle: enabled + throttle_rate: 7500 + throttle_unit: requests_per_minute + https: + admin_state: enabled + port: 445 + allow_origins: http://127.0.0.1:8000 + allow_credentials: enabled + ssl: + - tls_v1.2 + dh_param: 4096 + throttle: enabled + throttle_rate: 7500 + throttle_unit: requests_per_minute + admin_key_ring: key_ring_1 + client_certificate_trustpoint: certificate_authority_1 + client_certificate_authentication_state: enabled + register: nm_update_fabric_management_access_policy_1_change_child_configuration + +- name: Update an existing fabric management access policy https without admin_key_ring + cisco.aci.aci_fabric_management_access: + <<: *aci_fabric_management_access_1_present + https: + admin_state: enabled + port: 443 + register: nm_update_fabric_management_access_policy_1_change_https_no_keyring + +- name: Assertions for updating a fabric management access policy telnet, ssh_web, http configuration + ansible.builtin.assert: + that: + - nm_update_fabric_management_access_policy_1_change_child_configuration is changed + - nm_update_fabric_management_access_policy_1_change_child_configuration.previous.0.commPol.attributes.name == "fabric_management_access_policy_1" + - nm_update_fabric_management_access_policy_1_change_child_configuration.previous.0.commPol.children.0.commShellinabox.attributes.adminSt == "disabled" + - nm_update_fabric_management_access_policy_1_change_child_configuration.previous.0.commPol.children.1.commSsh.attributes.adminSt == "enabled" + - nm_update_fabric_management_access_policy_1_change_child_configuration.previous.0.commPol.children.2.commTelnet.attributes.adminSt == "disabled" + - nm_update_fabric_management_access_policy_1_change_child_configuration.previous.0.commPol.children.2.commTelnet.attributes.port == "23" + - nm_update_fabric_management_access_policy_1_change_child_configuration.previous.0.commPol.children.3.commHttps.attributes.adminSt == "enabled" + - nm_update_fabric_management_access_policy_1_change_child_configuration.previous.0.commPol.children.3.commHttps.attributes.port == "443" + - nm_update_fabric_management_access_policy_1_change_child_configuration.previous.0.commPol.children.3.commHttps.attributes.accessControlAllowCredential == "disabled" + # - nm_update_fabric_management_access_policy_1_change_child_configuration.previous.0.commPol.children.3.commHttps.attributes.accessControlAllowOrigins == "" Commented because the default value is different between versions. + - nm_update_fabric_management_access_policy_1_change_child_configuration.previous.0.commPol.children.3.commHttps.attributes.clientCertAuthState == "disabled" + - nm_update_fabric_management_access_policy_1_change_child_configuration.previous.0.commPol.children.3.commHttps.attributes.dhParam == "none" + - nm_update_fabric_management_access_policy_1_change_child_configuration.previous.0.commPol.children.3.commHttps.attributes.sslProtocols == "TLSv1.1,TLSv1.2" + - nm_update_fabric_management_access_policy_1_change_child_configuration.previous.0.commPol.children.3.commHttps.attributes.globalThrottleRate == "10000" + - nm_update_fabric_management_access_policy_1_change_child_configuration.previous.0.commPol.children.3.commHttps.attributes.globalThrottleSt == "disabled" + - nm_update_fabric_management_access_policy_1_change_child_configuration.previous.0.commPol.children.3.commHttps.attributes.globalThrottleUnit == "r/s" + - nm_update_fabric_management_access_policy_1_change_child_configuration.previous.0.commPol.children.3.commHttps.children.0.commRsKeyRing.attributes.tnPkiKeyRingName == "default" + - nm_update_fabric_management_access_policy_1_change_child_configuration.previous.0.commPol.children.4.commHttp.attributes.adminSt == "disabled" + - nm_update_fabric_management_access_policy_1_change_child_configuration.previous.0.commPol.children.4.commHttp.attributes.port == "80" + - nm_update_fabric_management_access_policy_1_change_child_configuration.current.0.commPol.attributes.name == "fabric_management_access_policy_1" + - nm_update_fabric_management_access_policy_1_change_child_configuration.current.0.commPol.children.0.commShellinabox.attributes.adminSt == "enabled" + - nm_update_fabric_management_access_policy_1_change_child_configuration.current.0.commPol.children.1.commSsh.attributes.adminSt == "enabled" + - nm_update_fabric_management_access_policy_1_change_child_configuration.current.0.commPol.children.1.commSsh.attributes.passwordAuth == "enabled" + - nm_update_fabric_management_access_policy_1_change_child_configuration.current.0.commPol.children.1.commSsh.attributes.port == "20" + - nm_update_fabric_management_access_policy_1_change_child_configuration.current.0.commPol.children.1.commSsh.attributes.sshCiphers == "aes128-ctr,aes192-ctr,aes256-ctr" + - nm_update_fabric_management_access_policy_1_change_child_configuration.current.0.commPol.children.1.commSsh.attributes.kexAlgos == "diffie-hellman-group14-sha1,ecdh-sha2-nistp521" + - nm_update_fabric_management_access_policy_1_change_child_configuration.current.0.commPol.children.1.commSsh.attributes.sshMacs == "hmac-sha2-256,hmac-sha2-512" + - nm_update_fabric_management_access_policy_1_change_child_configuration.current.0.commPol.children.2.commTelnet.attributes.adminSt == "enabled" + - nm_update_fabric_management_access_policy_1_change_child_configuration.current.0.commPol.children.2.commTelnet.attributes.port == "25" + - nm_update_fabric_management_access_policy_1_change_child_configuration.current.0.commPol.children.3.commHttps.attributes.adminSt == "enabled" + - nm_update_fabric_management_access_policy_1_change_child_configuration.current.0.commPol.children.3.commHttps.attributes.port == "445" + - nm_update_fabric_management_access_policy_1_change_child_configuration.current.0.commPol.children.3.commHttps.attributes.accessControlAllowCredential == "enabled" + - nm_update_fabric_management_access_policy_1_change_child_configuration.current.0.commPol.children.3.commHttps.attributes.accessControlAllowOrigins == "http://127.0.0.1:8000" + - nm_update_fabric_management_access_policy_1_change_child_configuration.current.0.commPol.children.3.commHttps.attributes.clientCertAuthState == "enabled" + - nm_update_fabric_management_access_policy_1_change_child_configuration.current.0.commPol.children.3.commHttps.attributes.dhParam == "4096" + - nm_update_fabric_management_access_policy_1_change_child_configuration.current.0.commPol.children.3.commHttps.attributes.sslProtocols == "TLSv1.2" + - nm_update_fabric_management_access_policy_1_change_child_configuration.current.0.commPol.children.3.commHttps.attributes.globalThrottleRate == "7500" + - nm_update_fabric_management_access_policy_1_change_child_configuration.current.0.commPol.children.3.commHttps.attributes.globalThrottleSt == "enabled" + - nm_update_fabric_management_access_policy_1_change_child_configuration.current.0.commPol.children.3.commHttps.attributes.globalThrottleUnit == "r/m" + - nm_update_fabric_management_access_policy_1_change_child_configuration.current.0.commPol.children.3.commHttps.children.0.commRsKeyRing.attributes.tnPkiKeyRingName == "key_ring_1" + - nm_update_fabric_management_access_policy_1_change_child_configuration.current.0.commPol.children.3.commHttps.children.1.commRsClientCertCA.attributes.tDn == "uni/userext/pkiext/tp-certificate_authority_1" + - nm_update_fabric_management_access_policy_1_change_child_configuration.current.0.commPol.children.4.commHttp.attributes.adminSt == "enabled" + - nm_update_fabric_management_access_policy_1_change_child_configuration.current.0.commPol.children.4.commHttp.attributes.port == "85" + - nm_update_fabric_management_access_policy_1_change_child_configuration.current.0.commPol.children.4.commHttp.attributes.accessControlAllowOrigins == "http://127.0.0.1:8000" + - nm_update_fabric_management_access_policy_1_change_child_configuration.current.0.commPol.children.4.commHttp.attributes.accessControlAllowCredential == "enabled" + - nm_update_fabric_management_access_policy_1_change_child_configuration.current.0.commPol.children.4.commHttp.attributes.globalThrottleSt == "enabled" + - nm_update_fabric_management_access_policy_1_change_child_configuration.current.0.commPol.children.4.commHttp.attributes.globalThrottleRate == "7500" + - nm_update_fabric_management_access_policy_1_change_child_configuration.current.0.commPol.children.4.commHttp.attributes.globalThrottleUnit == "r/m" + - nm_update_fabric_management_access_policy_1_change_https_no_keyring is changed + - nm_update_fabric_management_access_policy_1_change_https_no_keyring.previous.0.commPol.attributes.name == "fabric_management_access_policy_1" + - nm_update_fabric_management_access_policy_1_change_https_no_keyring.previous.0.commPol.children.3.commHttps.attributes.port == "445" + - nm_update_fabric_management_access_policy_1_change_https_no_keyring.previous.0.commPol.children.3.commHttps.children.0.commRsKeyRing.attributes.tnPkiKeyRingName == "key_ring_1" + - nm_update_fabric_management_access_policy_1_change_https_no_keyring.current.0.commPol.attributes.name == "fabric_management_access_policy_1" + - nm_update_fabric_management_access_policy_1_change_https_no_keyring.current.0.commPol.children.3.commHttps.attributes.port == "443" + - nm_update_fabric_management_access_policy_1_change_https_no_keyring.current.0.commPol.children.3.commHttps.children.0.commRsKeyRing.attributes.tnPkiKeyRingName == "key_ring_1" + +# VERSION SPECIFIC TESTS +- name: Test fabric management access policy http redirect + when: version.current.0.topSystem.attributes.version is version('5.2', '>=') + block: + - name: Update an existing fabric management access policy http redirect >= 5.2 + cisco.aci.aci_fabric_management_access: + <<: *aci_fabric_management_access_1_present + http: + redirect: tested + register: nm_update_fabric_management_access_policy_1_http_redirect + + - name: Assertions for fabric management access policy http redirect + ansible.builtin.assert: + that: + - nm_update_fabric_management_access_policy_1_http_redirect is changed + - nm_update_fabric_management_access_policy_1_http_redirect.current.0.commPol.children.4.commHttp.attributes.redirectSt == "tested" + +# QUERY +- name: Query an fabric management access policy + cisco.aci.aci_fabric_management_access: + <<: *aci_fabric_management_access_1_present + state: query + register: query_fabric_management_access_policy_1 + +- name: Query all fabric management access policies + cisco.aci.aci_fabric_management_access: + <<: *aci_info + state: query + register: query_all + +- name: Assertions for querying fabric management access policies + ansible.builtin.assert: + that: + - query_fabric_management_access_policy_1 is not changed + - query_fabric_management_access_policy_1.current.0.commPol.attributes.descr == "This is a example Fabric Management Access policy." + - query_fabric_management_access_policy_1.current.0.commPol.attributes.name == "fabric_management_access_policy_1" + - query_fabric_management_access_policy_1.current.0.commPol.children.0.commShellinabox.attributes.adminSt == "enabled" + - query_fabric_management_access_policy_1.current.0.commPol.children.1.commSsh.attributes.adminSt == "enabled" + - query_fabric_management_access_policy_1.current.0.commPol.children.2.commTelnet.attributes.adminSt == "enabled" + - query_fabric_management_access_policy_1.current.0.commPol.children.3.commHttps.attributes.adminSt == "enabled" + - query_fabric_management_access_policy_1.current.0.commPol.children.4.commHttp.attributes.adminSt == "enabled" + - query_fabric_management_access_policy_1.current.0.commPol.children | length == 5 + - query_fabric_management_access_policy_1.current | length == 1 + - query_all is not changed + - query_all.current | length >= 2 + +# DELETE +- name: Delete an existing fabric management access policy (check_mode) + cisco.aci.aci_fabric_management_access: + <<: *aci_fabric_management_access_1_absent + check_mode: true + register: cm_delete_fabric_management_access_policy_1 + +- name: Delete an existing fabric management access policy + cisco.aci.aci_fabric_management_access: + <<: *aci_fabric_management_access_1_absent + register: nm_delete_fabric_management_access_policy_1 + +- name: Delete an existing fabric management access policy again + cisco.aci.aci_fabric_management_access: + <<: *aci_fabric_management_access_1_absent + register: nm_delete_fabric_management_access_policy_1_again + +- name: Assertions for deleting a fabric management access policy + ansible.builtin.assert: + that: + - cm_delete_fabric_management_access_policy_1 is changed + - cm_delete_fabric_management_access_policy_1.previous.0.commPol.attributes.descr == "This is a example Fabric Management Access policy." + - cm_delete_fabric_management_access_policy_1.previous.0.commPol.attributes.name == "fabric_management_access_policy_1" + - cm_delete_fabric_management_access_policy_1.current.0.commPol.attributes.descr == "This is a example Fabric Management Access policy." + - cm_delete_fabric_management_access_policy_1.current.0.commPol.attributes.name == "fabric_management_access_policy_1" + - cm_delete_fabric_management_access_policy_1.proposed == {} + - nm_delete_fabric_management_access_policy_1 is changed + - nm_delete_fabric_management_access_policy_1.previous.0.commPol.attributes.descr == "This is a example Fabric Management Access policy." + - nm_delete_fabric_management_access_policy_1.previous.0.commPol.attributes.name == "fabric_management_access_policy_1" + - nm_delete_fabric_management_access_policy_1.current == [] + - nm_delete_fabric_management_access_policy_1_again is not changed + - nm_delete_fabric_management_access_policy_1_again.previous == [] + - nm_delete_fabric_management_access_policy_1_again.current == [] + +# CLEAN ENVIRONMENT +- name: Delete key_ring_1 + cisco.aci.aci_aaa_key_ring: + <<: *key_ring_1 + state: absent + register: delete_key_ring_1 + +- name: Delete certificate_authority_1 + cisco.aci.aci_aaa_certificate_authority: + <<: *certificate_authority_1 + state: absent \ No newline at end of file diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_fabric_management_access_https_cipher/aliases b/ansible_collections/cisco/aci/tests/integration/targets/aci_fabric_management_access_https_cipher/aliases new file mode 100644 index 000000000..209b793f9 --- /dev/null +++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_fabric_management_access_https_cipher/aliases @@ -0,0 +1,2 @@ +# No ACI simulator yet, so not enabled +# unsupported diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_fabric_management_access_https_cipher/pki/admin.crt b/ansible_collections/cisco/aci/tests/integration/targets/aci_fabric_management_access_https_cipher/pki/admin.crt new file mode 100644 index 000000000..cfac5531e --- /dev/null +++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_fabric_management_access_https_cipher/pki/admin.crt @@ -0,0 +1,14 @@ +-----BEGIN CERTIFICATE----- +MIICODCCAaGgAwIBAgIJAIt8XMntue0VMA0GCSqGSIb3DQEBCwUAMDQxDjAMBgNV +BAMMBUFkbWluMRUwEwYDVQQKDAxZb3VyIENvbXBhbnkxCzAJBgNVBAYTAlVTMCAX +DTE4MDEwOTAwNTk0NFoYDzIxMTcxMjE2MDA1OTQ0WjA0MQ4wDAYDVQQDDAVBZG1p +bjEVMBMGA1UECgwMWW91ciBDb21wYW55MQswCQYDVQQGEwJVUzCBnzANBgkqhkiG +9w0BAQEFAAOBjQAwgYkCgYEAohG/7axtt7CbSaMP7r+2mhTKbNgh0Ww36C7Ta14i +v+VmLyKkQHnXinKGhp6uy3Nug+15a+eIu7CrgpBVMQeCiWfsnwRocKcQJWIYDrWl +XHxGQn31yYKR6mylE7Dcj3rMFybnyhezr5D8GcP85YRPmwG9H2hO/0Y1FUnWu9Iw +AQkCAwEAAaNQME4wHQYDVR0OBBYEFD0jLXfpkrU/ChzRvfruRs/fy1VXMB8GA1Ud +IwQYMBaAFD0jLXfpkrU/ChzRvfruRs/fy1VXMAwGA1UdEwQFMAMBAf8wDQYJKoZI +hvcNAQELBQADgYEAOmvre+5tgZ0+F3DgsfxNQqLTrGiBgGCIymPkP/cBXXkNuJyl +3ac7tArHQc7WEA4U2R2rZbEq8FC3UJJm4nUVtCPvEh3G9OhN2xwYev79yt6pIn/l +KU0Td2OpVyo0eLqjoX5u2G90IBWzhyjFbo+CcKMrSVKj1YOdG0E3OuiJf00= +-----END CERTIFICATE----- diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_fabric_management_access_https_cipher/pki/admin.key b/ansible_collections/cisco/aci/tests/integration/targets/aci_fabric_management_access_https_cipher/pki/admin.key new file mode 100644 index 000000000..63bb00cc0 --- /dev/null +++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_fabric_management_access_https_cipher/pki/admin.key @@ -0,0 +1,16 @@ +-----BEGIN PRIVATE KEY----- +MIICdwIBADANBgkqhkiG9w0BAQEFAASCAmEwggJdAgEAAoGBAKIRv+2sbbewm0mj +D+6/tpoUymzYIdFsN+gu02teIr/lZi8ipEB514pyhoaerstzboPteWvniLuwq4KQ +VTEHgoln7J8EaHCnECViGA61pVx8RkJ99cmCkepspROw3I96zBcm58oXs6+Q/BnD +/OWET5sBvR9oTv9GNRVJ1rvSMAEJAgMBAAECgYByu3QO0qF9h7X3JEu0Ld4cKBnB +giQ2uJC/et7KxIJ/LOvw9GopBthyt27KwG1ntBkJpkTuAaQHkyNns7vLkNB0S0IR ++owVFEcKYq9VCHTaiQU8TDp24gN+yPTrpRuH8YhDVq5SfVdVuTMgHVQdj4ya4VlF +Gj+a7+ipxtGiLsVGrQJBAM7p0Fm0xmzi+tBOASUAcVrPLcteFIaTBFwfq16dm/ON +00Khla8Et5kMBttTbqbukl8mxFjBEEBlhQqb6EdQQ0sCQQDIhHx1a9diG7y/4DQA +4KvR3FCYwP8PBORlSamegzCo+P1OzxiEo0amX7yQMA5UyiP/kUsZrme2JBZgna8S +p4R7AkEAr7rMhSOPUnMD6V4WgsJ5g1Jp5kqkzBaYoVUUSms5RASz4+cwJVCwTX91 +Y1jcpVIBZmaaY3a0wrx13ajEAa0dOQJBAIpjnb4wqpsEh7VpmJqOdSdGxb1XXfFQ +sA0T1OQYqQnFppWwqrxIL+d9pZdiA1ITnNqyvUFBNETqDSOrUHwwb2cCQGArE+vu +ffPUWQ0j+fiK+covFG8NL7H+26NSGB5+Xsn9uwOGLj7K/YT6CbBtr9hJiuWjM1Al +0V4ltlTuu2mTMaw= +-----END PRIVATE KEY----- diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_fabric_management_access_https_cipher/tasks/main.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_fabric_management_access_https_cipher/tasks/main.yml new file mode 100644 index 000000000..5eced8237 --- /dev/null +++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_fabric_management_access_https_cipher/tasks/main.yml @@ -0,0 +1,233 @@ +# Test code for the ACI modules +# Copyright: (c) 2024, Akini Ross (@akinross) + +# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) + +- name: Test that we have an ACI APIC host, ACI username and ACI password + ansible.builtin.fail: + msg: "Please define the following variables: aci_hostname, aci_username and aci_password." + when: aci_hostname is not defined or aci_username is not defined or aci_password is not defined + +# SET VARS +- name: Set vars + ansible.builtin.set_fact: + aci_info: &aci_info + host: "{{ aci_hostname }}" + username: "{{ aci_username }}" + password: "{{ aci_password }}" + validate_certs: "{{ aci_validate_certs | default(false) }}" + use_ssl: "{{ aci_use_ssl | default(true) }}" + use_proxy: "{{ aci_use_proxy | default(true) }}" + output_level: "{{ aci_output_level | default('info') }}" + +- name: Query system information to fetch version + cisco.aci.aci_system: + <<: *aci_info + id: 1 + state: query + register: version + +- name: Define cipher in version < 6.0 + set_fact: + supported_cipher: "DHE-RSA-AES128-SHA" + supported_cipher_2: "DHE-RSA-AES256-SHA" + when: version.current.0.topSystem.attributes.version is version('6.0', '<') + +- name: Define speed settings in version >= 6.0 + set_fact: + supported_cipher: "DHE-RSA-AES128-SHA256" + supported_cipher_2: "ECDHE-ECDSA-AES128-CCM" + when: version.current.0.topSystem.attributes.version is version('6.0', '>=') + +# CLEAN ENVIRONMENT +- name: Clean environment + cisco.aci.aci_fabric_management_access: &aci_fabric_management_access_1_absent + <<: *aci_info + name: fabric_management_access_policy_1 + state: absent + +- name: Ensure certificate_authority_1 exists + cisco.aci.aci_aaa_certificate_authority: &certificate_authority_1 + <<: *aci_info + name: certificate_authority_1 + certificate_chain: "{{ lookup('file', 'pki/admin.crt') }}" + state: present + +- name: Ensure key_ring_1 exists + cisco.aci.aci_aaa_key_ring: &key_ring_1 + <<: *aci_info + name: key_ring_1 + certificate: "{{ lookup('file', 'pki/admin.crt') }}" + certificate_authority: certificate_authority_1 + key: "{{ lookup('file', 'pki/admin.key') }}" + state: present + register: create_key_ring_1 + until: create_key_ring_1 is not failed + delay: 2 + retries: 4 + +- name: Ensure fabric_management_access_policy_1 exists + cisco.aci.aci_fabric_management_access: + <<: *aci_fabric_management_access_1_absent + https: + admin_state: enabled + port: 445 + admin_key_ring: key_ring_1 + client_certificate_trustpoint: certificate_authority_1 + client_certificate_authentication_state: enabled + state: present + +# CREATE CIPHER +- name: Create a https ssl cipher (check_mode) + cisco.aci.aci_fabric_management_access_https_cipher: &https_ssl_cipher_disabled + <<: *aci_info + fabric_management_access_policy_name: fabric_management_access_policy_1 + id: "{{ supported_cipher }}" + cipher_state: disabled + state: present + check_mode: true + register: cm_create_https_ssl_cipher + +- name: Create a https ssl cipher + cisco.aci.aci_fabric_management_access_https_cipher: + <<: *https_ssl_cipher_disabled + register: nm_create_https_ssl_cipher + +- name: Create a https ssl cipher again + cisco.aci.aci_fabric_management_access_https_cipher: + <<: *https_ssl_cipher_disabled + register: nm_create_https_ssl_cipher_again + +- name: Assertions for disabling a https ssl cipher + ansible.builtin.assert: + that: + - cm_create_https_ssl_cipher is changed + - cm_create_https_ssl_cipher.previous == [] + - cm_create_https_ssl_cipher.current == [] + - cm_create_https_ssl_cipher.proposed.commCipher.attributes.id == "{{ supported_cipher }}" + - cm_create_https_ssl_cipher.proposed.commCipher.attributes.state == "disabled" + - nm_create_https_ssl_cipher is changed + - nm_create_https_ssl_cipher.previous == [] + - nm_create_https_ssl_cipher.current.0.commCipher.attributes.id == "{{ supported_cipher }}" + - nm_create_https_ssl_cipher.current.0.commCipher.attributes.state == "disabled" + - nm_create_https_ssl_cipher_again is not changed + - nm_create_https_ssl_cipher_again.previous.0.commCipher.attributes.id == "{{ supported_cipher }}" + - nm_create_https_ssl_cipher_again.previous.0.commCipher.attributes.state == "disabled" + - nm_create_https_ssl_cipher_again.current.0.commCipher.attributes.id == "{{ supported_cipher }}" + - nm_create_https_ssl_cipher_again.current.0.commCipher.attributes.state == "disabled" + +# UPDATE CIPHER +- name: Update https ssl cipher (check_mode) + cisco.aci.aci_fabric_management_access_https_cipher: &https_ssl_cipher_enabled + <<: *https_ssl_cipher_disabled + cipher_state: enabled + check_mode: true + register: cm_update_https_ssl_cipher + +- name: Update https ssl cipher + cisco.aci.aci_fabric_management_access_https_cipher: + <<: *https_ssl_cipher_enabled + register: nm_update_https_ssl_cipher + +- name: Update https ssl cipher again + cisco.aci.aci_fabric_management_access_https_cipher: + <<: *https_ssl_cipher_enabled + register: nm_update_https_ssl_cipher_again + +- name: Assertions for enabling a https ssl cipher + ansible.builtin.assert: + that: + - cm_update_https_ssl_cipher is changed + - cm_update_https_ssl_cipher.previous.0.commCipher.attributes.id == "{{ supported_cipher }}" + - cm_update_https_ssl_cipher.previous.0.commCipher.attributes.state == "disabled" + - cm_update_https_ssl_cipher.current.0.commCipher.attributes.id == "{{ supported_cipher }}" + - cm_update_https_ssl_cipher.current.0.commCipher.attributes.state == "disabled" + - cm_update_https_ssl_cipher.proposed.commCipher.attributes.id == "{{ supported_cipher }}" + - cm_update_https_ssl_cipher.proposed.commCipher.attributes.state == "enabled" + - nm_update_https_ssl_cipher is changed + - nm_update_https_ssl_cipher.previous.0.commCipher.attributes.id == "{{ supported_cipher }}" + - nm_update_https_ssl_cipher.previous.0.commCipher.attributes.state == "disabled" + - nm_update_https_ssl_cipher.current.0.commCipher.attributes.id == "{{ supported_cipher }}" + - nm_update_https_ssl_cipher.current.0.commCipher.attributes.state == "enabled" + - nm_update_https_ssl_cipher_again is not changed + - nm_update_https_ssl_cipher_again.previous.0.commCipher.attributes.id == "{{ supported_cipher }}" + - nm_update_https_ssl_cipher_again.previous.0.commCipher.attributes.state == "enabled" + - nm_update_https_ssl_cipher_again.current.0.commCipher.attributes.id == "{{ supported_cipher }}" + - nm_update_https_ssl_cipher_again.current.0.commCipher.attributes.state == "enabled" + +# QUERY +- name: Create another https ssl cipher + cisco.aci.aci_fabric_management_access_https_cipher: + <<: *https_ssl_cipher_disabled + id: "{{ supported_cipher_2 }}" + +- name: Query an fabric management access policy + cisco.aci.aci_fabric_management_access_https_cipher: + <<: *https_ssl_cipher_enabled + state: query + register: query_fabric_management_access_policy_1 + +- name: Query all fabric management access policies + cisco.aci.aci_fabric_management_access_https_cipher: + <<: *aci_info + state: query + register: query_all + +- name: Assertions for querying fabric management access policies + ansible.builtin.assert: + that: + - query_fabric_management_access_policy_1 is not changed + - query_fabric_management_access_policy_1.current | length == 1 + - query_all is not changed + - query_all.current | length >= 2 + +# DELETE +- name: Delete https ssl cipher (check_mode) + cisco.aci.aci_fabric_management_access_https_cipher: &https_ssl_cipher_deleted + <<: *https_ssl_cipher_enabled + state: absent + check_mode: true + register: cm_delete_https_ssl_cipher + +- name: Delete https ssl cipher + cisco.aci.aci_fabric_management_access_https_cipher: + <<: *https_ssl_cipher_deleted + register: nm_delete_https_ssl_cipher + +- name: Delete https ssl cipher again + cisco.aci.aci_fabric_management_access_https_cipher: + <<: *https_ssl_cipher_deleted + register: nm_delete_https_ssl_cipher_again + +- name: Assertions for deleting a https ssl cipher + ansible.builtin.assert: + that: + - cm_delete_https_ssl_cipher is changed + - cm_delete_https_ssl_cipher.previous.0.commCipher.attributes.id == "{{ supported_cipher }}" + - cm_delete_https_ssl_cipher.previous.0.commCipher.attributes.state == "enabled" + - cm_delete_https_ssl_cipher.current.0.commCipher.attributes.id == "{{ supported_cipher }}" + - cm_delete_https_ssl_cipher.current.0.commCipher.attributes.state == "enabled" + - cm_delete_https_ssl_cipher.proposed == {} + - nm_delete_https_ssl_cipher is changed + - nm_delete_https_ssl_cipher.previous.0.commCipher.attributes.id == "{{ supported_cipher }}" + - nm_delete_https_ssl_cipher.previous.0.commCipher.attributes.state == "enabled" + - nm_delete_https_ssl_cipher.current == [] + - nm_delete_https_ssl_cipher_again is not changed + - nm_delete_https_ssl_cipher_again.previous == [] + - nm_delete_https_ssl_cipher_again.current == [] + +# CLEAN ENVIRONMENT +- name: Delete fabric_management_access_policy_1 + cisco.aci.aci_fabric_management_access: + <<: *aci_fabric_management_access_1_absent + +- name: Delete key_ring_1 + cisco.aci.aci_aaa_key_ring: + <<: *key_ring_1 + state: absent + register: delete_key_ring_1 + +- name: Delete certificate_authority_1 + cisco.aci.aci_aaa_certificate_authority: + <<: *certificate_authority_1 + state: absent diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_fabric_node/tasks/main.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_fabric_node/tasks/main.yml index 552661556..c769a9a4e 100644 --- a/ansible_collections/cisco/aci/tests/integration/targets/aci_fabric_node/tasks/main.yml +++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_fabric_node/tasks/main.yml @@ -5,12 +5,12 @@ # GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) - name: Test that we have an ACI APIC host, ACI username and ACI password - fail: + ansible.builtin.fail: msg: 'Please define the following variables: aci_hostname, aci_username and aci_password.' when: aci_hostname is not defined or aci_username is not defined or aci_password is not defined - name: Set vars - set_fact: + ansible.builtin.set_fact: aci_info: &aci_info host: "{{ aci_hostname }}" username: "{{ aci_username }}" @@ -91,7 +91,7 @@ ignore_errors: true - name: Verify add_fabric_node - assert: + ansible.builtin.assert: that: - cm_add_fabric_node_tier_2 is changed - nm_add_fabric_node is changed @@ -137,7 +137,7 @@ register: nm_add_fabric_node_descr_again - name: Verify add_fabric_node_descr - assert: + ansible.builtin.assert: that: - cm_add_fabric_node_descr is changed - nm_add_fabric_node_descr is changed @@ -157,7 +157,7 @@ register: nm_add_fabric_node_again_no_descr - name: Verify add_fabric_node_again_no_descr - assert: + ansible.builtin.assert: that: # FIXME: Module is not idempotent - cm_add_fabric_node_again_no_descr is not changed @@ -183,7 +183,7 @@ register: nm_query_all_fabric_nodes - name: Verify query_all_fabric_nodes - assert: + ansible.builtin.assert: that: - cm_query_all_fabric_nodes is not changed - nm_query_all_fabric_nodes is not changed @@ -205,7 +205,7 @@ register: nm_query_fabric_node - name: Verify query_fabric_node - assert: + ansible.builtin.assert: that: - cm_query_fabric_node is not changed - nm_query_fabric_node is not changed @@ -232,7 +232,7 @@ register: nm_remove_fabric_node_again - name: Verify remove_fabric_node - assert: + ansible.builtin.assert: that: - cm_remove_fabric_node is changed - nm_remove_fabric_node is changed @@ -255,7 +255,7 @@ register: nm_query_non_fabric_node - name: Verify query_non_fabric_node - assert: + ansible.builtin.assert: that: - cm_query_non_fabric_node is not changed - nm_query_non_fabric_node is not changed diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_fabric_node_control/tasks/main.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_fabric_node_control/tasks/main.yml index f41c69150..5a9d58af1 100644 --- a/ansible_collections/cisco/aci/tests/integration/targets/aci_fabric_node_control/tasks/main.yml +++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_fabric_node_control/tasks/main.yml @@ -5,12 +5,12 @@ # GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) - name: Test that we have an ACI APIC host, ACI username and ACI password - fail: + ansible.builtin.fail: msg: 'Please define the following variables: aci_hostname, aci_username and aci_password.' when: aci_hostname is not defined or aci_username is not defined or aci_password is not defined - name: Set vars - set_fact: + ansible.builtin.set_fact: aci_info: &aci_info host: "{{ aci_hostname }}" username: "{{ aci_username }}" diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_fabric_pod/aliases b/ansible_collections/cisco/aci/tests/integration/targets/aci_fabric_pod/aliases new file mode 100644 index 000000000..209b793f9 --- /dev/null +++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_fabric_pod/aliases @@ -0,0 +1,2 @@ +# No ACI simulator yet, so not enabled +# unsupported diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_fabric_pod/tasks/main.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_fabric_pod/tasks/main.yml new file mode 100644 index 000000000..6da068c24 --- /dev/null +++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_fabric_pod/tasks/main.yml @@ -0,0 +1,206 @@ +# Test code for the ACI modules +# Copyright: (c) 2023, Samita Bhattacharjee (@samitab) + +# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) + +# Virtual pod setup has been skipped due to complex setup requirements assosiated with configuring a vPod. + +- name: Test that we have an ACI APIC host, ACI username and ACI password + ansible.builtin.fail: + msg: 'Please define the following variables: aci_hostname, aci_username and aci_password.' + when: aci_hostname is not defined or aci_username is not defined or aci_password is not defined + +# GET Credentials from the inventory +- name: Set vars + ansible.builtin.set_fact: + aci_info: &aci_info + host: "{{ aci_hostname }}" + username: "{{ aci_username }}" + password: "{{ aci_password }}" + validate_certs: '{{ aci_validate_certs | default(false) }}' + use_ssl: '{{ aci_use_ssl | default(true) }}' + use_proxy: '{{ aci_use_proxy | default(true) }}' + output_level: debug + +# CLEAN ENVIRONMENT +- name: Ensure Fabric Setup Pod 77 is absent before testing + cisco.aci.aci_fabric_pod: + <<: *aci_info + pod_id: 77 + state: absent + register: cleaned + +- name: Sleep for 15 seconds and continue + ansible.builtin.wait_for: + timeout: 15 + delegate_to: localhost + when: cleaned is changed + +# CREATE FABRIC SETUP POD +- name: Create ansible_fabric_pod_setup with check mode + cisco.aci.aci_fabric_pod: + <<: *aci_info + pod_id: 77 + pool: 10.77.0.0/16 + type: physical + description: Ansible test pod setup + state: present + check_mode: true + register: add_fabric_pod_setup_cm + +- name: Create ansible_fabric_pod_setup + cisco.aci.aci_fabric_pod: + <<: *aci_info + pod_id: 77 + pool: 10.77.0.0/16 + type: physical + description: Ansible test pod setup + state: present + register: add_fabric_pod_setup + +- name: Sleep for 15 seconds and continue + ansible.builtin.wait_for: + timeout: 15 + delegate_to: localhost + +- name: Verify profile creation + ansible.builtin.assert: + that: + - add_fabric_pod_setup is changed + - add_fabric_pod_setup.current.0.fabricSetupP.attributes.dn == "uni/controller/setuppol/setupp-77" + - add_fabric_pod_setup.current.0.fabricSetupP.attributes.podId == "77" + - add_fabric_pod_setup.current.0.fabricSetupP.attributes.podType == "physical" + - add_fabric_pod_setup.current.0.fabricSetupP.attributes.tepPool == "10.77.0.0/16" + - add_fabric_pod_setup.current.0.fabricSetupP.attributes.descr == "Ansible test pod setup" + - add_fabric_pod_setup.current.0.fabricSetupP.attributes.annotation == 'orchestrator:ansible' + - add_fabric_pod_setup_cm is changed + - add_fabric_pod_setup_cm.previous == [] + - add_fabric_pod_setup_cm.current == [] + - add_fabric_pod_setup_cm.proposed.fabricSetupP.attributes.dn == "uni/controller/setuppol/setupp-77" + - add_fabric_pod_setup_cm.proposed.fabricSetupP.attributes.podId == "77" + - add_fabric_pod_setup_cm.proposed.fabricSetupP.attributes.podType == "physical" + - add_fabric_pod_setup_cm.proposed.fabricSetupP.attributes.tepPool == "10.77.0.0/16" + - add_fabric_pod_setup_cm.proposed.fabricSetupP.attributes.descr == "Ansible test pod setup" + - add_fabric_pod_setup_cm.proposed.fabricSetupP.attributes.annotation == 'orchestrator:ansible' + +# CREATE FABRIC SETUP POD AGAIN TO TEST IDEMPOTENCE +- name: Create ansible_fabric_pod_setup again + cisco.aci.aci_fabric_pod: + <<: *aci_info + pod_id: 77 + pool: 10.77.0.0/16 + type: physical + description: Ansible test pod setup + state: present + register: add_fabric_pod_setup_again + +- name: Verify profile creation idempotence + ansible.builtin.assert: + that: + - add_fabric_pod_setup_again is not changed + - add_fabric_pod_setup_again.current.0.fabricSetupP.attributes.dn == "uni/controller/setuppol/setupp-77" + - add_fabric_pod_setup_again.current.0.fabricSetupP.attributes.podId == "77" + - add_fabric_pod_setup_again.current.0.fabricSetupP.attributes.podType == "physical" + - add_fabric_pod_setup_again.current.0.fabricSetupP.attributes.tepPool == "10.77.0.0/16" + - add_fabric_pod_setup_again.current.0.fabricSetupP.attributes.descr == "Ansible test pod setup" + +# QUERY FABRIC SETUP POD +- name: Query fabric setup pod + cisco.aci.aci_fabric_pod: + <<: *aci_info + pod_id: 77 + state: query + register: query_pod_profile + +- name: Verify profile query + ansible.builtin.assert: + that: + - query_pod_profile is not changed + - query_pod_profile.current.0.fabricSetupP.attributes.dn == "uni/controller/setuppol/setupp-77" + - query_pod_profile.current.0.fabricSetupP.attributes.podId == "77" + - query_pod_profile.current.0.fabricSetupP.attributes.podType == "physical" + - query_pod_profile.current.0.fabricSetupP.attributes.tepPool == "10.77.0.0/16" + - query_pod_profile.current.0.fabricSetupP.attributes.descr == "Ansible test pod setup" + +# QUERY ALL POD SETUPS +- name: Query all fabric pod setups + cisco.aci.aci_fabric_pod: + <<: *aci_info + state: query + register: query_pod_profile_all + +- name: Verify profile query idempotence + ansible.builtin.assert: + that: + - query_pod_profile_all is not changed + +# DELETE POD SETUP +- name: Delete pod setup with check mode + cisco.aci.aci_fabric_pod: + <<: *aci_info + pod_id: 77 + state: absent + check_mode: true + register: delete_pod_setup_cm + +- name: Delete pod setup + cisco.aci.aci_fabric_pod: + <<: *aci_info + pod_id: 77 + state: absent + register: delete_pod_setup + +- name: Sleep for 15 seconds and continue + ansible.builtin.wait_for: + timeout: 15 + delegate_to: localhost + +- name: Verify pod setup deletion + ansible.builtin.assert: + that: + - delete_pod_setup is changed + - delete_pod_setup.current == [] + - delete_pod_setup.previous.0.fabricSetupP.attributes.dn == "uni/controller/setuppol/setupp-77" + - delete_pod_setup.previous.0.fabricSetupP.attributes.podId == "77" + - delete_pod_setup.previous.0.fabricSetupP.attributes.podType == "physical" + - delete_pod_setup.previous.0.fabricSetupP.attributes.tepPool == "10.77.0.0/16" + - delete_pod_setup.previous.0.fabricSetupP.attributes.descr == "Ansible test pod setup" + - delete_pod_setup_cm is changed + - delete_pod_setup_cm.current != [] + - delete_pod_setup_cm.previous.0.fabricSetupP.attributes.dn == "uni/controller/setuppol/setupp-77" + - delete_pod_setup_cm.previous.0.fabricSetupP.attributes.podId == "77" + - delete_pod_setup_cm.previous.0.fabricSetupP.attributes.podType == "physical" + - delete_pod_setup_cm.previous.0.fabricSetupP.attributes.tepPool == "10.77.0.0/16" + - delete_pod_setup_cm.previous.0.fabricSetupP.attributes.descr == "Ansible test pod setup" + - delete_pod_setup_cm.proposed == {} + +# DELETE POD SETUP AGAIN TO TEST IDEMPOTENCE +- name: Delete pod setup again + cisco.aci.aci_fabric_pod: + <<: *aci_info + pod_id: 77 + state: absent + register: delete_pod_setup_again + +- name: Verify profile deletion idempotence + ansible.builtin.assert: + that: + - delete_pod_setup_again is not changed + - delete_pod_setup_again.current == [] + +# ERROR HANDLING +- name: Create pod setup with out of range pod_id + cisco.aci.aci_fabric_pod: + <<: *aci_info + pod_id: 300 + pool: 10.123.0.0/24 + state: present + register: pod_setup_id_error + ignore_errors: true + +- name: Verify errors of Fabric Setup Pod + ansible.builtin.assert: + that: + - pod_setup_id_error is not changed + - pod_setup_id_error is failed + - pod_setup_id_error.msg == "Pod ID{{":"}} 300 is invalid; it must be in the range of 1 to 254." \ No newline at end of file diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_fabric_pod_connectivity_profile/aliases b/ansible_collections/cisco/aci/tests/integration/targets/aci_fabric_pod_connectivity_profile/aliases new file mode 100644 index 000000000..209b793f9 --- /dev/null +++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_fabric_pod_connectivity_profile/aliases @@ -0,0 +1,2 @@ +# No ACI simulator yet, so not enabled +# unsupported diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_fabric_pod_connectivity_profile/tasks/main.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_fabric_pod_connectivity_profile/tasks/main.yml new file mode 100644 index 000000000..9a42b4656 --- /dev/null +++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_fabric_pod_connectivity_profile/tasks/main.yml @@ -0,0 +1,225 @@ +# Test code for the ACI modules +# Copyright: (c) 2024, Samita Bhattacharjee (@samitab) + +# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) + +- name: Test that we have an ACI APIC host, ACI username and ACI password + ansible.builtin.fail: + msg: 'Please define the following variables: aci_hostname, aci_username and aci_password.' + when: aci_hostname is not defined or aci_username is not defined or aci_password is not defined + +# GET Credentials from the inventory +- name: Set vars + ansible.builtin.set_fact: + aci_info: &aci_info + host: "{{ aci_hostname }}" + username: "{{ aci_username }}" + password: "{{ aci_password }}" + validate_certs: "{{ aci_validate_certs | default(false) }}" + use_ssl: "{{ aci_use_ssl | default(true) }}" + use_proxy: "{{ aci_use_proxy | default(true) }}" + output_level: "{{ aci_output_level | default('info') }}" + +- name: Query system information + cisco.aci.aci_system: + <<: *aci_info + id: 1 + state: query + register: version + +- name: Verify Cloud and Non-Cloud Sites in use. + ansible.builtin.include_tasks: ../../../../../../integration/targets/aci_cloud_provider/tasks/main.yml + +- name: Execute tasks only for non-cloud sites + when: query_cloud.current == [] + block: + + # CLEAN ENVIRONMENT + - name: Ensure fabric external connection profile is absent before testing + cisco.aci.aci_fabric_external_connection_profile: &delete_fabric_external_connection_profile + <<: *aci_info + fabric_id: "1" + name: "ansible_fabric_ext_conn_profile" + community: "extended:as2-nn4:5:16" + state: absent + + - name: Ensure fabric pod connectivity profile is absent before testing + cisco.aci.aci_fabric_pod_connectivity_profile: &delete_fabric_pod_connectivity_profile + <<: *aci_info + fabric_id: 1 + pod_id: 1 + state: absent + + - name: Create fabric external connection profile + cisco.aci.aci_fabric_external_connection_profile: + <<: *delete_fabric_external_connection_profile + state: present + + # CREATE FABRIC POD CONNECTIVITY PROFILE + - name: Create fabric pod connectivity profile with check mode + cisco.aci.aci_fabric_pod_connectivity_profile: &create_fabric_pod_connectivity_profile + <<: *aci_info + fabric_id: "1" + description: "Fabric Pod Connectivity Profile" + pod_id: "1" + unicast_tep: "10.1.1.2/32" + data_plane_tep: "10.1.1.1/32" + state: present + check_mode: true + register: add_fabric_pod_connectivity_profile_cm + + - name: Create fabric pod connectivity profile + cisco.aci.aci_fabric_pod_connectivity_profile: + <<: *create_fabric_pod_connectivity_profile + state: present + register: add_fabric_pod_connectivity_profile + + # CREATE FABRIC POD CONNECTIVITY PROFILE AGAIN TO TEST IDEMPOTENCE + - name: Create fabric pod connectivity profile again + cisco.aci.aci_fabric_pod_connectivity_profile: + <<: *create_fabric_pod_connectivity_profile + state: present + register: add_fabric_pod_connectivity_profile_again + + - name: Verify creation + ansible.builtin.assert: + that: + - add_fabric_pod_connectivity_profile is changed + - add_fabric_pod_connectivity_profile.previous == [] + - add_fabric_pod_connectivity_profile.current.0.fvPodConnP.attributes.dn == "uni/tn-infra/fabricExtConnP-1/podConnP-1" + - add_fabric_pod_connectivity_profile.current.0.fvPodConnP.attributes.descr == "Fabric Pod Connectivity Profile" + - add_fabric_pod_connectivity_profile.current.0.fvPodConnP.attributes.annotation == 'orchestrator:ansible' + - add_fabric_pod_connectivity_profile.current.0.fvPodConnP.attributes.id == "1" + - add_fabric_pod_connectivity_profile.current.0.fvPodConnP.children.0.fvExtRoutableUcastConnP.attributes.addr == "10.1.1.2/32" + - add_fabric_pod_connectivity_profile.current.0.fvPodConnP.children.1.fvIp.attributes.addr == "10.1.1.1/32" + - add_fabric_pod_connectivity_profile_cm is changed + - add_fabric_pod_connectivity_profile_cm.previous == [] + - add_fabric_pod_connectivity_profile_cm.current == [] + - add_fabric_pod_connectivity_profile_cm.proposed.fvPodConnP.attributes.dn == "uni/tn-infra/fabricExtConnP-1/podConnP-1" + - add_fabric_pod_connectivity_profile_cm.proposed.fvPodConnP.attributes.descr == "Fabric Pod Connectivity Profile" + - add_fabric_pod_connectivity_profile_cm.proposed.fvPodConnP.attributes.annotation == 'orchestrator:ansible' + - add_fabric_pod_connectivity_profile_cm.proposed.fvPodConnP.attributes.id == "1" + - add_fabric_pod_connectivity_profile_cm.proposed.fvPodConnP.children.0.fvExtRoutableUcastConnP.attributes.addr == "10.1.1.2/32" + - add_fabric_pod_connectivity_profile_cm.proposed.fvPodConnP.children.1.fvIp.attributes.addr == "10.1.1.1/32" + - add_fabric_pod_connectivity_profile_again is not changed + - add_fabric_pod_connectivity_profile_again.current == add_fabric_pod_connectivity_profile_again.previous + - add_fabric_pod_connectivity_profile_again.current.0.fvPodConnP.attributes.dn == "uni/tn-infra/fabricExtConnP-1/podConnP-1" + - add_fabric_pod_connectivity_profile_again.current.0.fvPodConnP.attributes.descr == "Fabric Pod Connectivity Profile" + - add_fabric_pod_connectivity_profile_again.current.0.fvPodConnP.attributes.annotation == 'orchestrator:ansible' + - add_fabric_pod_connectivity_profile_again.current.0.fvPodConnP.attributes.id == "1" + - add_fabric_pod_connectivity_profile_again.current.0.fvPodConnP.children.0.fvExtRoutableUcastConnP.attributes.addr == "10.1.1.2/32" + - add_fabric_pod_connectivity_profile_again.current.0.fvPodConnP.children.1.fvIp.attributes.addr == "10.1.1.1/32" + - add_fabric_pod_connectivity_profile_again.previous.0.fvPodConnP.attributes.dn == "uni/tn-infra/fabricExtConnP-1/podConnP-1" + - add_fabric_pod_connectivity_profile_again.previous.0.fvPodConnP.attributes.descr == "Fabric Pod Connectivity Profile" + - add_fabric_pod_connectivity_profile_again.previous.0.fvPodConnP.attributes.id == "1" + - add_fabric_pod_connectivity_profile_again.previous.0.fvPodConnP.children.0.fvExtRoutableUcastConnP.attributes.addr == "10.1.1.2/32" + - add_fabric_pod_connectivity_profile_again.previous.0.fvPodConnP.children.1.fvIp.attributes.addr == "10.1.1.1/32" + + # QUERY FABRIC POD CONNECTIVITY PROFILE + - name: Query fabric pod connectivity profile + cisco.aci.aci_fabric_pod_connectivity_profile: + <<: *aci_info + fabric_id: 1 + pod_id: 1 + state: query + register: query_fabric_pod_connectivity_profile + + # QUERY ALL FABRIC POD CONNECTIVITY PROFILE + - name: Query all fabric pod connectivity profile + cisco.aci.aci_fabric_pod_connectivity_profile: + <<: *aci_info + state: query + register: query_fabric_pod_connectivity_profile_all + + - name: Verify query + ansible.builtin.assert: + that: + - query_fabric_pod_connectivity_profile is not changed + - query_fabric_pod_connectivity_profile.current.0.fvPodConnP.attributes.dn == "uni/tn-infra/fabricExtConnP-1/podConnP-1" + - query_fabric_pod_connectivity_profile.current.0.fvPodConnP.attributes.descr == "Fabric Pod Connectivity Profile" + - query_fabric_pod_connectivity_profile.current.0.fvPodConnP.attributes.id == "1" + - query_fabric_pod_connectivity_profile.current.0.fvPodConnP.children.0.fvExtRoutableUcastConnP.attributes.addr == "10.1.1.2/32" + - query_fabric_pod_connectivity_profile.current.0.fvPodConnP.children.1.fvIp.attributes.addr == "10.1.1.1/32" + - query_fabric_pod_connectivity_profile_all is not changed + - query_fabric_pod_connectivity_profile_all.current | length == 1 + - query_fabric_pod_connectivity_profile_all.current.0.fvPodConnP.attributes.dn == "uni/tn-infra/fabricExtConnP-1/podConnP-1" + - query_fabric_pod_connectivity_profile_all.current.0.fvPodConnP.attributes.descr == "Fabric Pod Connectivity Profile" + - query_fabric_pod_connectivity_profile_all.current.0.fvPodConnP.attributes.id == "1" + - query_fabric_pod_connectivity_profile_all.current.0.fvPodConnP.children.0.fvExtRoutableUcastConnP.attributes.addr == "10.1.1.2/32" + - query_fabric_pod_connectivity_profile_all.current.0.fvPodConnP.children.1.fvIp.attributes.addr == "10.1.1.1/32" + + - name: Update fabric pod connectivity profile + cisco.aci.aci_fabric_pod_connectivity_profile: + <<: *create_fabric_pod_connectivity_profile + unicast_tep: "10.1.1.3/32" + data_plane_tep: "10.1.1.4/32" + state: present + register: update_fabric_pod_connectivity_profile + + - name: Update fabric pod connectivity profile - remove unicast and data plane tep + cisco.aci.aci_fabric_pod_connectivity_profile: + <<: *create_fabric_pod_connectivity_profile + unicast_tep: null + data_plane_tep: null + state: present + register: update_fabric_pod_connectivity_profile_2 + + - name: Verify updates + ansible.builtin.assert: + that: + - update_fabric_pod_connectivity_profile is changed + - update_fabric_pod_connectivity_profile.proposed.fvPodConnP.children.0.fvExtRoutableUcastConnP.attributes.addr == "10.1.1.2/32" + - update_fabric_pod_connectivity_profile.proposed.fvPodConnP.children.0.fvExtRoutableUcastConnP.attributes.status == "deleted" + - update_fabric_pod_connectivity_profile.proposed.fvPodConnP.children.1.fvIp.attributes.addr == "10.1.1.1/32" + - update_fabric_pod_connectivity_profile.proposed.fvPodConnP.children.1.fvIp.attributes.status == "deleted" + - update_fabric_pod_connectivity_profile.proposed.fvPodConnP.children.2.fvExtRoutableUcastConnP.attributes.addr == "10.1.1.3/32" + - update_fabric_pod_connectivity_profile.proposed.fvPodConnP.children.3.fvIp.attributes.addr == "10.1.1.4/32" + - update_fabric_pod_connectivity_profile.current.0.fvPodConnP.children | length == 2 + - update_fabric_pod_connectivity_profile.current.0.fvPodConnP.children.0.fvExtRoutableUcastConnP.attributes.addr == "10.1.1.3/32" + - update_fabric_pod_connectivity_profile.current.0.fvPodConnP.children.1.fvIp.attributes.addr == "10.1.1.4/32" + - update_fabric_pod_connectivity_profile_2 is changed + - update_fabric_pod_connectivity_profile_2.proposed.fvPodConnP.children.0.fvExtRoutableUcastConnP.attributes.addr == "10.1.1.3/32" + - update_fabric_pod_connectivity_profile_2.proposed.fvPodConnP.children.0.fvExtRoutableUcastConnP.attributes.status == "deleted" + - update_fabric_pod_connectivity_profile_2.proposed.fvPodConnP.children.1.fvIp.attributes.addr == "10.1.1.4/32" + - update_fabric_pod_connectivity_profile_2.proposed.fvPodConnP.children.1.fvIp.attributes.status == "deleted" + - update_fabric_pod_connectivity_profile_2.current.0.fvPodConnP.children is undefined + + # DELETE FABRIC POD CONNECTIVITY PROFILE + - name: Delete fabric pod connectivity profile with check mode + cisco.aci.aci_fabric_pod_connectivity_profile: + <<: *delete_fabric_pod_connectivity_profile + check_mode: true + register: delete_fabric_pod_connectivity_profile_cm + + - name: Delete fabric pod connectivity profile + cisco.aci.aci_fabric_pod_connectivity_profile: + <<: *delete_fabric_pod_connectivity_profile + register: delete_fabric_pod_connectivity_profile + + # DELETE FABRIC POD CONNECTIVITY PROFILE AGAIN TO TEST IDEMPOTENCE + - name: Delete fabric pod connectivity profile again + cisco.aci.aci_fabric_pod_connectivity_profile: + <<: *delete_fabric_pod_connectivity_profile + register: delete_fabric_pod_connectivity_profile_again + + - name: Verify deletion + ansible.builtin.assert: + that: + - delete_fabric_pod_connectivity_profile is changed + - delete_fabric_pod_connectivity_profile.current == [] + - delete_fabric_pod_connectivity_profile.previous.0.fvPodConnP.attributes.dn == "uni/tn-infra/fabricExtConnP-1/podConnP-1" + - delete_fabric_pod_connectivity_profile.previous.0.fvPodConnP.attributes.descr == "Fabric Pod Connectivity Profile" + - delete_fabric_pod_connectivity_profile.previous.0.fvPodConnP.attributes.id == "1" + - delete_fabric_pod_connectivity_profile_cm is changed + - delete_fabric_pod_connectivity_profile_cm.proposed == {} + - delete_fabric_pod_connectivity_profile_cm.current != [] + - delete_fabric_pod_connectivity_profile_cm.previous.0.fvPodConnP.attributes.dn == "uni/tn-infra/fabricExtConnP-1/podConnP-1" + - delete_fabric_pod_connectivity_profile_cm.previous.0.fvPodConnP.attributes.descr == "Fabric Pod Connectivity Profile" + - delete_fabric_pod_connectivity_profile_cm.previous.0.fvPodConnP.attributes.id == "1" + - delete_fabric_pod_connectivity_profile_again is not changed + - delete_fabric_pod_connectivity_profile_again.current == [] + - delete_fabric_pod_connectivity_profile_again.previous == [] + + - name: Clean up fabric external connection profile + cisco.aci.aci_fabric_external_connection_profile: + <<: *delete_fabric_external_connection_profile \ No newline at end of file diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_fabric_pod_external_tep/aliases b/ansible_collections/cisco/aci/tests/integration/targets/aci_fabric_pod_external_tep/aliases new file mode 100644 index 000000000..209b793f9 --- /dev/null +++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_fabric_pod_external_tep/aliases @@ -0,0 +1,2 @@ +# No ACI simulator yet, so not enabled +# unsupported diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_fabric_pod_external_tep/tasks/main.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_fabric_pod_external_tep/tasks/main.yml new file mode 100644 index 000000000..d9cab57a4 --- /dev/null +++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_fabric_pod_external_tep/tasks/main.yml @@ -0,0 +1,210 @@ +# Test code for the ACI modules +# Copyright: (c) 2023, Samita Bhattacharjee (@samitab) + +# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) + +- name: Test that we have an ACI APIC host, ACI username and ACI password + ansible.builtin.fail: + msg: 'Please define the following variables: aci_hostname, aci_username and aci_password.' + when: aci_hostname is not defined or aci_username is not defined or aci_password is not defined + +# GET Credentials from the inventory +- name: Set vars + ansible.builtin.set_fact: + aci_info: &aci_info + host: "{{ aci_hostname }}" + username: "{{ aci_username }}" + password: "{{ aci_password }}" + validate_certs: '{{ aci_validate_certs | default(false) }}' + use_ssl: '{{ aci_use_ssl | default(true) }}' + use_proxy: '{{ aci_use_proxy | default(true) }}' + output_level: debug + +# CLEAN ENVIRONMENT +- name: Change external tep to inactive + cisco.aci.aci_fabric_pod_external_tep: + <<: *aci_info + pod_id: 1 + pool: 10.66.22.0/24 + address_count: 5 + status: inactive + state: present + ignore_errors: true + +- name: Ensure existing external tep is absent + cisco.aci.aci_fabric_pod_external_tep: + <<: *aci_info + pod_id: 1 + pool: 10.66.22.0/24 + state: absent + +# CREATE EXTERNAL TEP +- name: Create an external tep with check mode + cisco.aci.aci_fabric_pod_external_tep: + <<: *aci_info + pod_id: 1 + pool: 10.66.22.0/24 + address_count: 5 + status: active + state: present + check_mode: true + register: add_external_tep_cm + +- name: Create an external tep + cisco.aci.aci_fabric_pod_external_tep: + <<: *aci_info + pod_id: 1 + pool: 10.66.22.0/24 + address_count: 5 + status: active + state: present + register: add_external_tep + +- name: Verify external tep creation + ansible.builtin.assert: + that: + - add_external_tep is changed + - add_external_tep.current.0.fabricExtRoutablePodSubnet.attributes.dn == "uni/controller/setuppol/setupp-1/extrtpodsubnet-[10.66.22.0/24]" + - add_external_tep.current.0.fabricExtRoutablePodSubnet.attributes.pool == "10.66.22.0/24" + - add_external_tep.current.0.fabricExtRoutablePodSubnet.attributes.reserveAddressCount == "5" + - add_external_tep.current.0.fabricExtRoutablePodSubnet.attributes.state == "active" + - add_external_tep.current.0.fabricExtRoutablePodSubnet.attributes.annotation == "orchestrator:ansible" + - add_external_tep_cm is changed + - add_external_tep_cm.previous == [] + - add_external_tep_cm.current == [] + - add_external_tep_cm.proposed.fabricExtRoutablePodSubnet.attributes.dn == "uni/controller/setuppol/setupp-1/extrtpodsubnet-[10.66.22.0/24]" + - add_external_tep_cm.proposed.fabricExtRoutablePodSubnet.attributes.pool == "10.66.22.0/24" + - add_external_tep_cm.proposed.fabricExtRoutablePodSubnet.attributes.reserveAddressCount == "5" + - add_external_tep_cm.proposed.fabricExtRoutablePodSubnet.attributes.state == "active" + - add_external_tep_cm.proposed.fabricExtRoutablePodSubnet.attributes.annotation == "orchestrator:ansible" + +# CREATE FABRIC POD PROFILE AGAIN TO TEST IDEMPOTENCE +- name: Create an external tep again + cisco.aci.aci_fabric_pod_external_tep: + <<: *aci_info + pod_id: 1 + pool: 10.66.22.0/24 + address_count: 5 + status: active + state: present + register: add_external_tep_again + +- name: Verify external tep creation idempotence + ansible.builtin.assert: + that: + - add_external_tep_again is not changed + - add_external_tep_again.current.0.fabricExtRoutablePodSubnet.attributes.dn == "uni/controller/setuppol/setupp-1/extrtpodsubnet-[10.66.22.0/24]" + - add_external_tep_again.current.0.fabricExtRoutablePodSubnet.attributes.pool == "10.66.22.0/24" + - add_external_tep_again.current.0.fabricExtRoutablePodSubnet.attributes.reserveAddressCount == "5" + - add_external_tep_again.current.0.fabricExtRoutablePodSubnet.attributes.state == "active" + - add_external_tep_again.current.0.fabricExtRoutablePodSubnet.attributes.annotation == "orchestrator:ansible" + +# QUERY FABRIC EXTERNAL TEP +- name: Query external tep + cisco.aci.aci_fabric_pod_external_tep: + <<: *aci_info + pod_id: 1 + pool: 10.66.22.0/24 + state: query + register: query_external_tep + +- name: Verify external tep query + ansible.builtin.assert: + that: + - query_external_tep is not changed + - query_external_tep.current.0.fabricExtRoutablePodSubnet.attributes.dn == "uni/controller/setuppol/setupp-1/extrtpodsubnet-[10.66.22.0/24]" + - query_external_tep.current.0.fabricExtRoutablePodSubnet.attributes.pool == "10.66.22.0/24" + - query_external_tep.current.0.fabricExtRoutablePodSubnet.attributes.reserveAddressCount == "5" + - query_external_tep.current.0.fabricExtRoutablePodSubnet.attributes.state == "active" + +# QUERY ALL EXTERNAL TEPs +- name: Query all external teps + cisco.aci.aci_fabric_pod_external_tep: + <<: *aci_info + state: query + register: query_external_tep_all + +- name: Verify query idempotence + ansible.builtin.assert: + that: + - query_external_tep_all is not changed + +# VERIFY UNABLE TO DELETE ACTIVE EXTERNAL TEP +- name: Try to delete active external tep + cisco.aci.aci_fabric_pod_external_tep: + <<: *aci_info + pod_id: 1 + pool: 10.66.22.0/24 + state: absent + register: active_tep_error + ignore_errors: true + +- name: Verify unable to delete active external tep + ansible.builtin.assert: + that: + - active_tep_error is not changed + - active_tep_error is failed + - active_tep_error.msg == "APIC Error 105{{":"}} Unable to delete Routable TEP Pool.Please set the state = inactive." + +# CHANGE EXTERNAL TEP TO INACTIVE +- name: Change external tep to inactive + cisco.aci.aci_fabric_pod_external_tep: + <<: *aci_info + pod_id: 1 + pool: 10.66.22.0/24 + address_count: 5 + status: inactive + state: present + register: external_tep_inactive + +# DELETE EXTERNAL TEP +- name: Delete inactive external tep with check mode + cisco.aci.aci_fabric_pod_external_tep: + <<: *aci_info + pod_id: 1 + pool: 10.66.22.0/24 + state: absent + check_mode: true + register: delete_external_tep_cm + +- name: Delete inactive external tep + cisco.aci.aci_fabric_pod_external_tep: + <<: *aci_info + pod_id: 1 + pool: 10.66.22.0/24 + state: absent + register: delete_external_tep + +- name: Verify external tep deletion + ansible.builtin.assert: + that: + - external_tep_inactive is changed + - external_tep_inactive.current.0.fabricExtRoutablePodSubnet.attributes.state == "inactive" + - delete_external_tep is changed + - delete_external_tep.current == [] + - delete_external_tep.previous.0.fabricExtRoutablePodSubnet.attributes.dn == "uni/controller/setuppol/setupp-1/extrtpodsubnet-[10.66.22.0/24]" + - delete_external_tep.previous.0.fabricExtRoutablePodSubnet.attributes.pool == "10.66.22.0/24" + - delete_external_tep.previous.0.fabricExtRoutablePodSubnet.attributes.reserveAddressCount == "5" + - delete_external_tep.previous.0.fabricExtRoutablePodSubnet.attributes.state == "inactive" + - delete_external_tep_cm is changed + - delete_external_tep_cm.current != [] + - delete_external_tep_cm.previous.0.fabricExtRoutablePodSubnet.attributes.dn == "uni/controller/setuppol/setupp-1/extrtpodsubnet-[10.66.22.0/24]" + - delete_external_tep_cm.previous.0.fabricExtRoutablePodSubnet.attributes.pool == "10.66.22.0/24" + - delete_external_tep_cm.previous.0.fabricExtRoutablePodSubnet.attributes.reserveAddressCount == "5" + - delete_external_tep_cm.previous.0.fabricExtRoutablePodSubnet.attributes.state == "inactive" + - delete_external_tep_cm.proposed == {} + +# DELETE AGAIN TO TEST IDEMPOTENCE +- name: Delete inactive external tep again + cisco.aci.aci_fabric_pod_external_tep: + <<: *aci_info + pod_id: 1 + pool: 10.66.22.0/24 + state: absent + register: delete_external_tep_again + +- name: Verify profile deletion idempotence + ansible.builtin.assert: + that: + - delete_external_tep_again is not changed + - delete_external_tep_again.current == [] \ No newline at end of file diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_fabric_pod_policy_group/tasks/main.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_fabric_pod_policy_group/tasks/main.yml index 282fe15d3..e05c831ad 100644 --- a/ansible_collections/cisco/aci/tests/integration/targets/aci_fabric_pod_policy_group/tasks/main.yml +++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_fabric_pod_policy_group/tasks/main.yml @@ -4,12 +4,12 @@ # GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) - name: Test that we have an ACI APIC host, ACI username and ACI password - fail: + ansible.builtin.fail: msg: 'Please define the following variables: aci_hostname, aci_username and aci_password.' when: aci_hostname is not defined or aci_username is not defined or aci_password is not defined - name: Set vars - set_fact: + ansible.builtin.set_fact: aci_info: &aci_info host: "{{ aci_hostname }}" username: "{{ aci_username }}" @@ -62,7 +62,7 @@ register: nm_add_group_again - name: Verify add policy group - assert: + ansible.builtin.assert: that: - cm_add_group is changed - nm_add_group is changed @@ -95,7 +95,7 @@ register: nm_add_empty_group - name: Verify add empty policy group - assert: + ansible.builtin.assert: that: - nm_add_empty_group is changed - nm_add_empty_group.current.0.fabricPodPGrp.attributes.dn == 'uni/fabric/funcprof/podpgrp-ansible_empty_pod_policy_group' @@ -141,7 +141,7 @@ register: nm_modify_group_again - name: Verify modify policy - assert: + ansible.builtin.assert: that: - cm_modify_group is changed - nm_modify_group is changed @@ -186,7 +186,7 @@ register: nm_query_all_groups - name: Verify query_all_groups - assert: + ansible.builtin.assert: that: - cm_query_all_groups is not changed - nm_query_all_groups is not changed @@ -206,7 +206,7 @@ register: nm_query_group - name: Verify query_group - assert: + ansible.builtin.assert: that: - cm_query_group is not changed - nm_query_group is not changed @@ -246,7 +246,7 @@ register: nm_remove_group_again - name: Verify remove_group and remove_group_again - assert: + ansible.builtin.assert: that: - cm_remove_group is changed - nm_remove_group is changed diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_fabric_pod_profile/aliases b/ansible_collections/cisco/aci/tests/integration/targets/aci_fabric_pod_profile/aliases new file mode 100644 index 000000000..209b793f9 --- /dev/null +++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_fabric_pod_profile/aliases @@ -0,0 +1,2 @@ +# No ACI simulator yet, so not enabled +# unsupported diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_fabric_pod_profile/tasks/main.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_fabric_pod_profile/tasks/main.yml new file mode 100644 index 000000000..987ef55f8 --- /dev/null +++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_fabric_pod_profile/tasks/main.yml @@ -0,0 +1,153 @@ +# Test code for the ACI modules +# Copyright: (c) 2023, Samita Bhattacharjee (@samitab) + +# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) + +- name: Test that we have an ACI APIC host, ACI username and ACI password + ansible.builtin.fail: + msg: 'Please define the following variables: aci_hostname, aci_username and aci_password.' + when: aci_hostname is not defined or aci_username is not defined or aci_password is not defined + +# GET Credentials from the inventory +- name: Set vars + ansible.builtin.set_fact: + aci_info: &aci_info + host: "{{ aci_hostname }}" + username: "{{ aci_username }}" + password: "{{ aci_password }}" + validate_certs: '{{ aci_validate_certs | default(false) }}' + use_ssl: '{{ aci_use_ssl | default(true) }}' + use_proxy: '{{ aci_use_proxy | default(true) }}' + output_level: debug + +# CLEAN ENVIRONMENT +- name: Ensure Fabric Pod Profile is absent before testing + cisco.aci.aci_fabric_pod_profile: + <<: *aci_info + name: ansible_fabric_pod_profile + state: absent + +# CREATE FABRIC POD PROFILE +- name: Create ansible_fabric_pod_profile with check mode + cisco.aci.aci_fabric_pod_profile: + <<: *aci_info + name: ansible_fabric_pod_profile + description: Ansible test pod profile + state: present + check_mode: true + register: add_fabric_pod_profile_cm + +- name: Create ansible_fabric_pod_profile + cisco.aci.aci_fabric_pod_profile: + <<: *aci_info + name: ansible_fabric_pod_profile + description: Ansible test pod profile + state: present + register: add_fabric_pod_profile + +- name: Verify profile creation + ansible.builtin.assert: + that: + - add_fabric_pod_profile is changed + - add_fabric_pod_profile.previous == [] + - add_fabric_pod_profile.current.0.fabricPodP.attributes.dn == "uni/fabric/podprof-ansible_fabric_pod_profile" + - add_fabric_pod_profile.current.0.fabricPodP.attributes.name == "ansible_fabric_pod_profile" + - add_fabric_pod_profile.current.0.fabricPodP.attributes.descr == "Ansible test pod profile" + - add_fabric_pod_profile.current.0.fabricPodP.attributes.annotation == 'orchestrator:ansible' + - add_fabric_pod_profile_cm is changed + - add_fabric_pod_profile_cm.previous == [] + - add_fabric_pod_profile_cm.current == [] + - add_fabric_pod_profile_cm.proposed.fabricPodP.attributes.dn == "uni/fabric/podprof-ansible_fabric_pod_profile" + - add_fabric_pod_profile_cm.proposed.fabricPodP.attributes.name == "ansible_fabric_pod_profile" + - add_fabric_pod_profile_cm.proposed.fabricPodP.attributes.descr == "Ansible test pod profile" + - add_fabric_pod_profile_cm.proposed.fabricPodP.attributes.annotation == 'orchestrator:ansible' + +# CREATE FABRIC POD PROFILE AGAIN TO TEST IDEMPOTENCE +- name: Create ansible_fabric_pod_profile again + cisco.aci.aci_fabric_pod_profile: + <<: *aci_info + name: ansible_fabric_pod_profile + description: Ansible test pod profile + state: present + register: add_fabric_pod_profile_again + +- name: Verify profile creation idempotence + ansible.builtin.assert: + that: + - add_fabric_pod_profile_again is not changed + - add_fabric_pod_profile_again.current.0.fabricPodP.attributes.dn == "uni/fabric/podprof-ansible_fabric_pod_profile" + - add_fabric_pod_profile_again.current.0.fabricPodP.attributes.name == "ansible_fabric_pod_profile" + - add_fabric_pod_profile_again.current.0.fabricPodP.attributes.descr == "Ansible test pod profile" + +# QUERY FABRIC POD PROFILE +- name: Query fabric pod profile + cisco.aci.aci_fabric_pod_profile: + <<: *aci_info + name: ansible_fabric_pod_profile + state: query + register: query_pod_profile + +- name: Verify profile query + ansible.builtin.assert: + that: + - query_pod_profile is not changed + - query_pod_profile.current.0.fabricPodP.attributes.dn == "uni/fabric/podprof-ansible_fabric_pod_profile" + - query_pod_profile.current.0.fabricPodP.attributes.name == "ansible_fabric_pod_profile" + - query_pod_profile.current.0.fabricPodP.attributes.descr == "Ansible test pod profile" + +# QUERY ALL POD PROFILES +- name: Query all fabric pod profiles + cisco.aci.aci_fabric_pod_profile: + <<: *aci_info + state: query + register: query_pod_profile_all + +- name: Verify profile query idempotence + ansible.builtin.assert: + that: + - query_pod_profile_all is not changed + +# DELETE POD PROFILE +- name: Delete ansible_fabric_pod_profile with check mode + cisco.aci.aci_fabric_pod_profile: + <<: *aci_info + name: ansible_fabric_pod_profile + state: absent + check_mode: true + register: delete_pod_profile_cm + +- name: Delete ansible_fabric_pod_profile + cisco.aci.aci_fabric_pod_profile: + <<: *aci_info + name: ansible_fabric_pod_profile + state: absent + register: delete_pod_profile + +- name: Verify profile deletion + ansible.builtin.assert: + that: + - delete_pod_profile is changed + - delete_pod_profile.current == [] + - delete_pod_profile.previous.0.fabricPodP.attributes.dn == "uni/fabric/podprof-ansible_fabric_pod_profile" + - delete_pod_profile.previous.0.fabricPodP.attributes.name == "ansible_fabric_pod_profile" + - delete_pod_profile.previous.0.fabricPodP.attributes.descr == "Ansible test pod profile" + - delete_pod_profile_cm is changed + - delete_pod_profile_cm.current != [] + - delete_pod_profile_cm.previous.0.fabricPodP.attributes.dn == "uni/fabric/podprof-ansible_fabric_pod_profile" + - delete_pod_profile_cm.previous.0.fabricPodP.attributes.name == "ansible_fabric_pod_profile" + - delete_pod_profile_cm.previous.0.fabricPodP.attributes.descr == "Ansible test pod profile" + - delete_pod_profile_cm.proposed == {} + +# DELETE POD PROFILE AGAIN TO TEST IDEMPOTENCE +- name: Delete ansible_fabric_pod_profile again + cisco.aci.aci_fabric_pod_profile: + <<: *aci_info + name: ansible_fabric_pod_profile + state: absent + register: delete_pod_profile_again + +- name: Verify profile deletion idempotence + ansible.builtin.assert: + that: + - delete_pod_profile_again is not changed + - delete_pod_profile_again.current == [] diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_fabric_pod_remote_pool/aliases b/ansible_collections/cisco/aci/tests/integration/targets/aci_fabric_pod_remote_pool/aliases new file mode 100644 index 000000000..209b793f9 --- /dev/null +++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_fabric_pod_remote_pool/aliases @@ -0,0 +1,2 @@ +# No ACI simulator yet, so not enabled +# unsupported diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_fabric_pod_remote_pool/tasks/main.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_fabric_pod_remote_pool/tasks/main.yml new file mode 100644 index 000000000..74c33979e --- /dev/null +++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_fabric_pod_remote_pool/tasks/main.yml @@ -0,0 +1,246 @@ +# Test code for the ACI modules +# Copyright: (c) 2023, Samita Bhattacharjee (@samitab) + +# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) + +- name: Test that we have an ACI APIC host, ACI username and ACI password + ansible.builtin.fail: + msg: 'Please define the following variables: aci_hostname, aci_username and aci_password.' + when: aci_hostname is not defined or aci_username is not defined or aci_password is not defined + +# GET Credentials from the inventory +- name: Set vars + ansible.builtin.set_fact: + aci_info: &aci_info + host: "{{ aci_hostname }}" + username: "{{ aci_username }}" + password: "{{ aci_password }}" + validate_certs: '{{ aci_validate_certs | default(false) }}' + use_ssl: '{{ aci_use_ssl | default(true) }}' + use_proxy: '{{ aci_use_proxy | default(true) }}' + output_level: debug + +# CLEAN ENVIRONMENT +- name: Ensure Fabric Pod Remote Pool 66 is absent before testing + cisco.aci.aci_fabric_pod_remote_pool: + <<: *aci_info + pod_id: 1 + remote_id: 66 + state: absent + register: cleaned + +- name: Sleep for 15 seconds and continue + ansible.builtin.wait_for: + timeout: 15 + delegate_to: localhost + when: cleaned is changed + +- name: Change external tep to inactive + cisco.aci.aci_fabric_pod_external_tep: + <<: *aci_info + pod_id: 1 + pool: 10.66.22.0/24 + address_count: 5 + status: inactive + state: present + ignore_errors: true + +- name: Ensure existing external tep is absent + cisco.aci.aci_fabric_pod_external_tep: + <<: *aci_info + pod_id: 1 + pool: 10.66.22.0/24 + state: absent + +- name: Create Fabric External Connection Profile + cisco.aci.aci_fabric_external_connection_profile: + <<: *aci_info + fabric_id: 1 + site_id: 1 + community: extended:as2-nn4:5:16 + state: present + +- name: Create Fabric Pod Connectivity Profile + cisco.aci.aci_fabric_pod_connectivity_profile: + <<: *aci_info + fabric_id: 1 + pod_id: 1 + unicast_tep: 10.1.1.1/32 + state: present + +- name: Create an external tep + cisco.aci.aci_fabric_pod_external_tep: + <<: *aci_info + pod_id: 1 + pool: 10.66.22.0/24 + address_count: 5 + status: active + state: present + +# CREATE FABRIC REMOTE POOL +- name: Create a remote pool with check mode + cisco.aci.aci_fabric_pod_remote_pool: + <<: *aci_info + pod_id: 1 + pool: 10.66.22.0/24 + remote_id: 66 + state: present + check_mode: true + register: add_remote_pool_cm + +- name: Create a remote pool + cisco.aci.aci_fabric_pod_remote_pool: + <<: *aci_info + pod_id: 1 + pool: 10.66.22.0/24 + remote_id: 66 + state: present + register: add_remote_pool + +- name: Verify remote pool creation + ansible.builtin.assert: + that: + - add_remote_pool is changed + - add_remote_pool.current.0.fabricExtSetupP.attributes.dn == "uni/controller/setuppol/setupp-1/extsetupp-66" + - add_remote_pool.current.0.fabricExtSetupP.attributes.extPoolId == "66" + - add_remote_pool.current.0.fabricExtSetupP.attributes.tepPool == "10.66.22.0/24" + - add_remote_pool.current.0.fabricExtSetupP.attributes.annotation == "orchestrator:ansible" + - add_remote_pool_cm is changed + - add_remote_pool_cm.previous == [] + - add_remote_pool_cm.current == [] + - add_remote_pool_cm.proposed.fabricExtSetupP.attributes.dn == "uni/controller/setuppol/setupp-1/extsetupp-66" + - add_remote_pool_cm.proposed.fabricExtSetupP.attributes.extPoolId == "66" + - add_remote_pool_cm.proposed.fabricExtSetupP.attributes.tepPool == "10.66.22.0/24" + - add_remote_pool_cm.proposed.fabricExtSetupP.attributes.annotation == "orchestrator:ansible" + + +- name: Sleep for 15 seconds and continue + ansible.builtin.wait_for: + timeout: 15 + delegate_to: localhost + +# CREATE FABRIC REMOTE POOL AGAIN TO TEST IDEMPOTENCE +- name: Create a remote pool again + cisco.aci.aci_fabric_pod_remote_pool: + <<: *aci_info + pod_id: 1 + pool: 10.66.22.0/24 + remote_id: 66 + state: present + register: add_remote_pool_again + +- name: Verify remote pool creation idempotence + ansible.builtin.assert: + that: + - add_remote_pool_again is not changed + - add_remote_pool_again.current.0.fabricExtSetupP.attributes.dn == "uni/controller/setuppol/setupp-1/extsetupp-66" + - add_remote_pool_again.current.0.fabricExtSetupP.attributes.extPoolId == "66" + - add_remote_pool_again.current.0.fabricExtSetupP.attributes.tepPool == "10.66.22.0/24" + - add_remote_pool_again.current.0.fabricExtSetupP.attributes.annotation == "orchestrator:ansible" + +# QUERY FABRIC REMOTE POOL +- name: Query remote pool + cisco.aci.aci_fabric_pod_remote_pool: + <<: *aci_info + pod_id: 1 + remote_id: 66 + state: query + register: query_remote_pool + +- name: Verify remote pool query + ansible.builtin.assert: + that: + - query_remote_pool is not changed + - query_remote_pool.current.0.fabricExtSetupP.attributes.dn == "uni/controller/setuppol/setupp-1/extsetupp-66" + - query_remote_pool.current.0.fabricExtSetupP.attributes.extPoolId == "66" + - query_remote_pool.current.0.fabricExtSetupP.attributes.tepPool == "10.66.22.0/24" + +# QUERY ALL REMOTE POOLs +- name: Query all remote pools + cisco.aci.aci_fabric_pod_remote_pool: + <<: *aci_info + state: query + register: query_remote_pool_all + +- name: Verify query idempotence + ansible.builtin.assert: + that: + - query_remote_pool_all is not changed + +# DELETE REMOTE POOL +- name: Delete remote pool with check mode + cisco.aci.aci_fabric_pod_remote_pool: + <<: *aci_info + pod_id: 1 + remote_id: 66 + state: absent + check_mode: true + register: delete_remote_pool_cm + +- name: Delete remote pool + cisco.aci.aci_fabric_pod_remote_pool: + <<: *aci_info + pod_id: 1 + remote_id: 66 + state: absent + register: delete_remote_pool + +- name: Verify remote pool deletion + ansible.builtin.assert: + that: + - delete_remote_pool is changed + - delete_remote_pool.current == [] + - delete_remote_pool.previous.0.fabricExtSetupP.attributes.dn == "uni/controller/setuppol/setupp-1/extsetupp-66" + - delete_remote_pool.previous.0.fabricExtSetupP.attributes.extPoolId == "66" + - delete_remote_pool.previous.0.fabricExtSetupP.attributes.tepPool == "10.66.22.0/24" + - delete_remote_pool_cm is changed + - delete_remote_pool_cm.current != [] + - delete_remote_pool_cm.previous.0.fabricExtSetupP.attributes.dn == "uni/controller/setuppol/setupp-1/extsetupp-66" + - delete_remote_pool_cm.previous.0.fabricExtSetupP.attributes.extPoolId == "66" + - delete_remote_pool_cm.previous.0.fabricExtSetupP.attributes.tepPool == "10.66.22.0/24" + - delete_remote_pool_cm.proposed == {} + + +- name: Sleep for 15 seconds and continue + ansible.builtin.wait_for: + timeout: 15 + delegate_to: localhost + +# DELETE AGAIN TO TEST IDEMPOTENCE +- name: Delete remote pool again + cisco.aci.aci_fabric_pod_remote_pool: + <<: *aci_info + pod_id: 1 + remote_id: 66 + state: absent + register: delete_remote_pool_again + +- name: Verify profile deletion idempotence + ansible.builtin.assert: + that: + - delete_remote_pool_again is not changed + - delete_remote_pool_again.current == [] + +# CLEAN ENVIRONMENT +- name: Change external tep to inactive + cisco.aci.aci_fabric_pod_external_tep: + <<: *aci_info + pod_id: 1 + pool: 10.66.22.0/24 + address_count: 5 + status: inactive + state: present + ignore_errors: true + +- name: Ensure existing external tep is absent + cisco.aci.aci_fabric_pod_external_tep: + <<: *aci_info + pod_id: 1 + pool: 10.66.22.0/24 + state: absent + +- name: Ensure Fabric External Connection Profile is absent + cisco.aci.aci_fabric_external_connection_profile: + <<: *aci_info + fabric_id: 1 + state: absent \ No newline at end of file diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_fabric_pod_selector/tasks/main.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_fabric_pod_selector/tasks/main.yml index ca9fb8209..d1bcf7b95 100644 --- a/ansible_collections/cisco/aci/tests/integration/targets/aci_fabric_pod_selector/tasks/main.yml +++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_fabric_pod_selector/tasks/main.yml @@ -5,12 +5,12 @@ # GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) - name: Test that we have an ACI APIC host, ACI username and ACI password - fail: + ansible.builtin.fail: msg: 'Please define the following variables: aci_hostname, aci_username and aci_password.' when: aci_hostname is not defined or aci_username is not defined or aci_password is not defined - name: Set vars - set_fact: + ansible.builtin.set_fact: aci_info: &aci_info host: "{{ aci_hostname }}" username: "{{ aci_username }}" diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_fabric_scheduler/tasks/main.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_fabric_scheduler/tasks/main.yml index daf5e8956..532d0739f 100644 --- a/ansible_collections/cisco/aci/tests/integration/targets/aci_fabric_scheduler/tasks/main.yml +++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_fabric_scheduler/tasks/main.yml @@ -4,12 +4,12 @@ # GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) - name: Test that we have an ACI APIC host, ACI username and ACI password - fail: + ansible.builtin.fail: msg: 'Please define the following variables: aci_hostname, aci_username and aci_password.' when: aci_hostname is not defined or aci_username is not defined or aci_password is not defined - name: Set vars - set_fact: + ansible.builtin.set_fact: aci_info: &aci_info host: "{{ aci_hostname }}" username: "{{ aci_username }}" @@ -20,14 +20,14 @@ output_level: debug - name: Verify Cloud and Non-Cloud Sites in use. - include_tasks: ../../../../../../integration/targets/aci_cloud_provider/tasks/main.yml + ansible.builtin.include_tasks: ../../../../../../integration/targets/aci_cloud_provider/tasks/main.yml - name: Execute tasks only for non-cloud sites when: query_cloud.current == [] # This condition will execute only non-cloud sites block: # block specifies execution of tasks within, based on conditions # Clean Environment - name: Ensure first scheduler does not exist - aci_fabric_scheduler: &aci_fabric_scheduler_absent + cisco.aci.aci_fabric_scheduler: &aci_fabric_scheduler_absent <<: *aci_info name: anstest_scheduler_reccuring description: ACI scheduler test @@ -40,7 +40,7 @@ state: absent - name: Ensure second scheduler does not exist - aci_fabric_scheduler: &aci_fabric_scheduler_2_absent + cisco.aci.aci_fabric_scheduler: &aci_fabric_scheduler_2_absent <<: *aci_info name: anstest_scheduler_oneTime windowname: OneTime @@ -50,30 +50,30 @@ state: absent - name: Create first scheduler (check_mode) - aci_fabric_scheduler: &aci_fabric_scheduler_present + cisco.aci.aci_fabric_scheduler: &aci_fabric_scheduler_present <<: *aci_fabric_scheduler_absent state: present check_mode: true register: cm_add_fabric_scheduler_1 - name: Create first scheduler (normal_mode) - aci_fabric_scheduler: + cisco.aci.aci_fabric_scheduler: <<: *aci_fabric_scheduler_present register: nm_add_fabric_scheduler_1 - name: Create first scheduler again - testing idempotency - aci_fabric_scheduler: + cisco.aci.aci_fabric_scheduler: <<: *aci_fabric_scheduler_present register: idempotency_add_fabric_scheduler_1 - name: Create second scheduler - aci_fabric_scheduler: &aci_fabric_scheduler_2_present + cisco.aci.aci_fabric_scheduler: &aci_fabric_scheduler_2_present <<: *aci_fabric_scheduler_2_absent state: present register: nm_add_fabric_scheduler_2 - name: Asserts for creation tasks - assert: + ansible.builtin.assert: that: - cm_add_fabric_scheduler_1 is changed - cm_add_fabric_scheduler_1.previous == [] @@ -92,19 +92,19 @@ - nm_add_fabric_scheduler_2.current.0.trigSchedP.children.0.trigAbsWindowP.attributes.date == "2023-11-21T00:00:00.000+00:00" - name: Query all scheduler - aci_fabric_scheduler: + cisco.aci.aci_fabric_scheduler: <<: *aci_info state: query register: query_all_fabric_scheduler - name: Query first scheduler - aci_fabric_scheduler: + cisco.aci.aci_fabric_scheduler: <<: *aci_fabric_scheduler_present state: query register: query_first_fabric_scheduler - name: Asserts for query tasks - assert: + ansible.builtin.assert: that: - query_all_fabric_scheduler is not changed - query_all_fabric_scheduler.current | length >= 2 @@ -119,32 +119,32 @@ - query_first_fabric_scheduler.current.0.trigSchedP.children.0.trigRecurrWindowP.attributes.minute == "30" - name: Delete first scheduler (check_mode) - aci_fabric_scheduler: + cisco.aci.aci_fabric_scheduler: <<: *aci_fabric_scheduler_present state: absent check_mode: true register: cm_delete_fabric_scheduler_1 - name: Delete first scheduler (normal_mode) - aci_fabric_scheduler: + cisco.aci.aci_fabric_scheduler: <<: *aci_fabric_scheduler_present state: absent register: nm_delete_fabric_scheduler_1 - name: Delete first scheduler again - testing idempotency - aci_fabric_scheduler: + cisco.aci.aci_fabric_scheduler: <<: *aci_fabric_scheduler_present state: absent register: idempotency_delete_maintenance_group_1 - name: Delete second scheduler (normal_mode) - aci_fabric_scheduler: + cisco.aci.aci_fabric_scheduler: <<: *aci_fabric_scheduler_2_present state: absent register: nm_delete_fabric_scheduler_2 - name: Asserts for deletion tasks - assert: + ansible.builtin.assert: that: - cm_delete_fabric_scheduler_1 is changed - cm_delete_fabric_scheduler_1.proposed == {} diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_fabric_span_dst_group/tasks/main.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_fabric_span_dst_group/tasks/main.yml index a67026daa..e1ec15be9 100644 --- a/ansible_collections/cisco/aci/tests/integration/targets/aci_fabric_span_dst_group/tasks/main.yml +++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_fabric_span_dst_group/tasks/main.yml @@ -4,7 +4,7 @@ # GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) - name: Test that we have an ACI APIC host, ACI username and ACI password - fail: + ansible.builtin.fail: msg: 'Please define the following variables: aci_hostname, aci_username and aci_password.' when: aci_hostname is not defined or aci_username is not defined or aci_password is not defined diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_fabric_span_src_group/tasks/main.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_fabric_span_src_group/tasks/main.yml index c3e4eb55c..69673f032 100644 --- a/ansible_collections/cisco/aci/tests/integration/targets/aci_fabric_span_src_group/tasks/main.yml +++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_fabric_span_src_group/tasks/main.yml @@ -4,12 +4,12 @@ # GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) - name: Test that we have an ACI APIC host, ACI username and ACI password - fail: + ansible.builtin.fail: msg: 'Please define the following variables: aci_hostname, aci_username and aci_password.' when: aci_hostname is not defined or aci_username is not defined or aci_password is not defined - name: Set vars - set_fact: + ansible.builtin.set_fact: aci_info: &aci_info host: "{{ aci_hostname }}" username: "{{ aci_username }}" diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_fabric_span_src_group_src/tasks/main.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_fabric_span_src_group_src/tasks/main.yml index 6767e3e89..dc040b102 100644 --- a/ansible_collections/cisco/aci/tests/integration/targets/aci_fabric_span_src_group_src/tasks/main.yml +++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_fabric_span_src_group_src/tasks/main.yml @@ -4,12 +4,12 @@ # GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) - name: Test that we have an ACI APIC host, ACI username and ACI password - fail: + ansible.builtin.fail: msg: 'Please define the following variables: aci_hostname, aci_username and aci_password.' when: aci_hostname is not defined or aci_username is not defined or aci_password is not defined - name: Set vars - set_fact: + ansible.builtin.set_fact: aci_info: &aci_info host: "{{ aci_hostname }}" username: "{{ aci_username }}" diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_fabric_span_src_group_src_node/tasks/main.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_fabric_span_src_group_src_node/tasks/main.yml index 0e5ea30b2..ed35acb3a 100644 --- a/ansible_collections/cisco/aci/tests/integration/targets/aci_fabric_span_src_group_src_node/tasks/main.yml +++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_fabric_span_src_group_src_node/tasks/main.yml @@ -4,12 +4,12 @@ # GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) - name: Test that we have an ACI APIC host, ACI username and ACI password - fail: + ansible.builtin.fail: msg: 'Please define the following variables: aci_hostname, aci_username and aci_password.' when: aci_hostname is not defined or aci_username is not defined or aci_password is not defined - name: Set vars - set_fact: + ansible.builtin.set_fact: aci_info: &aci_info host: "{{ aci_hostname }}" username: "{{ aci_username }}" diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_fabric_span_src_group_src_path/tasks/main.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_fabric_span_src_group_src_path/tasks/main.yml index e0c772843..c63342a1a 100644 --- a/ansible_collections/cisco/aci/tests/integration/targets/aci_fabric_span_src_group_src_path/tasks/main.yml +++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_fabric_span_src_group_src_path/tasks/main.yml @@ -4,12 +4,12 @@ # GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) - name: Test that we have an ACI APIC host, ACI username and ACI password - fail: + ansible.builtin.fail: msg: 'Please define the following variables: aci_hostname, aci_username and aci_password.' when: aci_hostname is not defined or aci_username is not defined or aci_password is not defined - name: Set vars - set_fact: + ansible.builtin.set_fact: aci_info: &aci_info host: "{{ aci_hostname }}" username: "{{ aci_username }}" diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_fabric_spine_profile/tasks/main.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_fabric_spine_profile/tasks/main.yml index 684a9a874..ea79de9b7 100644 --- a/ansible_collections/cisco/aci/tests/integration/targets/aci_fabric_spine_profile/tasks/main.yml +++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_fabric_spine_profile/tasks/main.yml @@ -4,13 +4,13 @@ # GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) - name: Test that we have an ACI APIC host, ACI username and ACI password - fail: + ansible.builtin.fail: msg: 'Please define the following variables: aci_hostname, aci_username and aci_password.' when: aci_hostname is not defined or aci_username is not defined or aci_password is not defined # GET Credentials from the inventory - name: Set vars - set_fact: + ansible.builtin.set_fact: aci_info: &aci_info host: "{{ aci_hostname }}" username: "{{ aci_username }}" @@ -22,21 +22,21 @@ # CLEAN ENVIRONMENT - name: Remove ansible_spine_switch_prf if it already exists - aci_fabric_spine_profile: + cisco.aci.aci_fabric_spine_profile: <<: *aci_info name: ansible_spine_switch_prf state: absent # CREATE SPINE SWITCH POLICY - name: Create ansible_spine_switch_prf - aci_fabric_spine_profile: + cisco.aci.aci_fabric_spine_profile: <<: *aci_info name: ansible_spine_switch_prf state: present register: add_switch_prf - name: Verify profile creation - assert: + ansible.builtin.assert: that: - add_switch_prf.current.0.fabricSpineP.attributes.dn == "uni/fabric/spprof-ansible_spine_switch_prf" - add_switch_prf.current.0.fabricSpineP.attributes.name == "ansible_spine_switch_prf" @@ -44,14 +44,14 @@ # CREATE SPINE SWITCH POLICY AGAIN TO TEST IDEMPOTENCE - name: Create ansible_spine_switch_prf again - aci_fabric_spine_profile: + cisco.aci.aci_fabric_spine_profile: <<: *aci_info name: ansible_spine_switch_prf state: present register: add_switch_prf_again - name: Verify profile creation idempotence - assert: + ansible.builtin.assert: that: - add_switch_prf_again is not changed - add_switch_prf_again.current.0.fabricSpineP.attributes.dn == "uni/fabric/spprof-ansible_spine_switch_prf" @@ -59,14 +59,14 @@ # QUERY SPINE SWITCH POLICY - name: query spine switch profile - aci_fabric_spine_profile: + cisco.aci.aci_fabric_spine_profile: <<: *aci_info name: ansible_spine_switch_prf state: query register: query_switch_prf - name: Verify profile query - assert: + ansible.builtin.assert: that: - query_switch_prf is not changed - query_switch_prf.current.0.fabricSpineP.attributes.dn == "uni/fabric/spprof-ansible_spine_switch_prf" @@ -74,26 +74,26 @@ # QUERY ALL SPINE SWITCH POLICIES - name: query all spine switch profiles - aci_fabric_spine_profile: + cisco.aci.aci_fabric_spine_profile: <<: *aci_info state: query register: query_switch_prf_all - name: Verify profile query idempotence - assert: + ansible.builtin.assert: that: - query_switch_prf_all is not changed # DELETE SPINE SWITCH PROFILE - name: Delete ansible_spine_switch_prf - aci_fabric_spine_profile: + cisco.aci.aci_fabric_spine_profile: <<: *aci_info name: ansible_spine_switch_prf state: absent register: delete_switch_prf - name: Verify profile deletion - assert: + ansible.builtin.assert: that: - delete_switch_prf is changed - delete_switch_prf.current == [] @@ -102,21 +102,21 @@ # DELETE SPINE SWITCH PROFILE AGAIN TO TEST IDEMPOTENCE - name: Delete ansible_spine_switch_prf again - aci_fabric_spine_profile: + cisco.aci.aci_fabric_spine_profile: <<: *aci_info name: ansible_spine_switch_prf state: absent register: delete_switch_prf_again - name: Verify profile deletion idempotence - assert: + ansible.builtin.assert: that: - delete_switch_prf_again is not changed - delete_switch_prf_again.current == [] # CLEAN UP ENVIRONMENT - name: Remove ansible_spine_switch_prf - aci_fabric_spine_profile: + cisco.aci.aci_fabric_spine_profile: <<: *aci_info name: ansible_spine_switch_prf state: absent diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_fabric_spine_switch_assoc/tasks/main.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_fabric_spine_switch_assoc/tasks/main.yml index 697590fae..b9e79a9dd 100644 --- a/ansible_collections/cisco/aci/tests/integration/targets/aci_fabric_spine_switch_assoc/tasks/main.yml +++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_fabric_spine_switch_assoc/tasks/main.yml @@ -4,13 +4,13 @@ # GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) - name: Test that we have an ACI APIC host, ACI username and ACI password - fail: + ansible.builtin.fail: msg: 'Please define the following variables: aci_hostname, aci_username and aci_password.' when: aci_hostname is not defined or aci_username is not defined or aci_password is not defined # GET Credentials from the inventory - name: Set vars - set_fact: + ansible.builtin.set_fact: aci_info: &aci_info host: "{{ aci_hostname }}" username: "{{ aci_username }}" @@ -22,21 +22,21 @@ # CLEAN ENVIRONMENT - name: Remove ansible_spine_switch_prf if it already exists - aci_fabric_spine_profile: + cisco.aci.aci_fabric_spine_profile: <<: *aci_info name: ansible_spine_switch_prf state: absent # CREATE SPINE SWITCH POLICY - name: Create ansible_spine_switch_prf - aci_fabric_spine_profile: + cisco.aci.aci_fabric_spine_profile: <<: *aci_info name: ansible_spine_switch_prf state: present # CREATE SPINE SWITCH ASSOCIATION - name: Create a spine switch profile association - aci_fabric_spine_switch_assoc: + cisco.aci.aci_fabric_spine_switch_assoc: <<: *aci_info profile: ansible_spine_switch_prf name: ansible_spine_switch_assoc @@ -45,7 +45,7 @@ register: add_association - name: Verify association creation - assert: + ansible.builtin.assert: that: - add_association.current.0.fabricSpineS.attributes.dn == "uni/fabric/spprof-ansible_spine_switch_prf/spines-ansible_spine_switch_assoc-typ-range" - add_association.current.0.fabricSpineS.attributes.name == "ansible_spine_switch_assoc" @@ -53,13 +53,13 @@ - add_association.current.0.fabricSpineS.attributes.annotation == 'orchestrator:ansible' - name: Verify Policy Group association - assert: + ansible.builtin.assert: that: - add_association.current.0.fabricSpineS.children.0.fabricRsSpNodePGrp.attributes.tDn == "uni/fabric/funcprof/spnodepgrp-ansible_spine_pol_grp1" # CREATE SPINE SWITCH ASSOCIATION AGAIN TO TEST IDEMPOTENCE - name: Create a spine switch profile association again - aci_fabric_spine_switch_assoc: + cisco.aci.aci_fabric_spine_switch_assoc: <<: *aci_info profile: ansible_spine_switch_prf name: ansible_spine_switch_assoc @@ -68,7 +68,7 @@ register: add_association_again - name: Verify association creation idempotence - assert: + ansible.builtin.assert: that: - add_association_again is not changed - add_association_again.current.0.fabricSpineS.attributes.dn == "uni/fabric/spprof-ansible_spine_switch_prf/spines-ansible_spine_switch_assoc-typ-range" @@ -76,13 +76,13 @@ - add_association_again.current.0.fabricSpineS.attributes.type == "range" - name: Verify Policy Group association idempotence - assert: + ansible.builtin.assert: that: - add_association_again.current.0.fabricSpineS.children.0.fabricRsSpNodePGrp.attributes.tDn == "uni/fabric/funcprof/spnodepgrp-ansible_spine_pol_grp1" # CREATE SPINE SWITCH ASSOCIATION WITHOUT POLICY GROUP - name: Create a spine switch profile association without a policy group - aci_fabric_spine_switch_assoc: + cisco.aci.aci_fabric_spine_switch_assoc: <<: *aci_info profile: ansible_spine_switch_prf name: ansible_spine_switch_assoc2 @@ -90,7 +90,7 @@ register: add_association_without_policy_group - name: Verify association creation - assert: + ansible.builtin.assert: that: - add_association_without_policy_group.current.0.fabricSpineS.attributes.dn == "uni/fabric/spprof-ansible_spine_switch_prf/spines-ansible_spine_switch_assoc2-typ-range" - add_association_without_policy_group.current.0.fabricSpineS.attributes.name == "ansible_spine_switch_assoc2" @@ -98,7 +98,7 @@ # UPDATE SPINE SWITCH POLICY GROUP ASSOCIATION - name: Update a spine switch profile association - aci_fabric_spine_switch_assoc: + cisco.aci.aci_fabric_spine_switch_assoc: <<: *aci_info profile: ansible_spine_switch_prf name: ansible_spine_switch_assoc @@ -107,7 +107,7 @@ register: update_association - name: Verify association update - assert: + ansible.builtin.assert: that: - update_association is changed - update_association.current.0.fabricSpineS.attributes.dn == "uni/fabric/spprof-ansible_spine_switch_prf/spines-ansible_spine_switch_assoc-typ-range" @@ -115,13 +115,13 @@ - update_association.current.0.fabricSpineS.attributes.type == "range" - name: Verify Policy Group association update - assert: + ansible.builtin.assert: that: - update_association.current.0.fabricSpineS.children.0.fabricRsSpNodePGrp.attributes.tDn == "uni/fabric/funcprof/spnodepgrp-ansible_spine_pol_grp2" # QUERY SPINE SWITCH ASSOCIATION - name: Query spine switch profile association - aci_fabric_spine_switch_assoc: + cisco.aci.aci_fabric_spine_switch_assoc: <<: *aci_info profile: ansible_spine_switch_prf name: ansible_spine_switch_assoc @@ -129,7 +129,7 @@ register: query_association - name: Verify query data - assert: + ansible.builtin.assert: that: - query_association is not changed - query_association.current.0.fabricSpineS.attributes.dn == "uni/fabric/spprof-ansible_spine_switch_prf/spines-ansible_spine_switch_assoc-typ-range" @@ -137,25 +137,25 @@ - query_association.current.0.fabricSpineS.attributes.type == "range" - name: Verify Policy Group association - assert: + ansible.builtin.assert: that: - query_association.current.0.fabricSpineS.children.0.fabricRsSpNodePGrp.attributes.tDn == "uni/fabric/funcprof/spnodepgrp-ansible_spine_pol_grp2" # QUERY ALL SPINE SWITCH ASSOCIATIONS - name: Query spine switch profile association - aci_fabric_spine_switch_assoc: + cisco.aci.aci_fabric_spine_switch_assoc: <<: *aci_info state: query register: query_association_all - name: Verify query all idempotence - assert: + ansible.builtin.assert: that: - query_association_all is not changed # DELETE SPINE SWITCH ASSOCIATION - name: Delete spine switch profile association - aci_fabric_spine_switch_assoc: + cisco.aci.aci_fabric_spine_switch_assoc: <<: *aci_info profile: ansible_spine_switch_prf name: ansible_spine_switch_assoc @@ -163,7 +163,7 @@ register: delete_association - name: Verify association removal - assert: + ansible.builtin.assert: that: - delete_association is changed - delete_association.current == [] @@ -173,7 +173,7 @@ # DELETE SPINE SWITCH ASSOCIATION AGAIN TO TEST IDEMPOTENCE - name: Delete spine switch profile association again - aci_fabric_spine_switch_assoc: + cisco.aci.aci_fabric_spine_switch_assoc: <<: *aci_info profile: ansible_spine_switch_prf name: ansible_spine_switch_assoc @@ -181,14 +181,14 @@ register: delete_association_again - name: Verify association removal idempotence - assert: + ansible.builtin.assert: that: - delete_association_again is not changed - delete_association_again.current == [] # CLEAN UP ENVIRONMENT - name: Remove ansible_spine_switch_prf - aci_fabric_spine_profile: + cisco.aci.aci_fabric_spine_profile: <<: *aci_info name: ansible_spine_switch_prf state: absent diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_fabric_switch_block/tasks/main.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_fabric_switch_block/tasks/main.yml index 5bd4ce68b..07fd4fe55 100644 --- a/ansible_collections/cisco/aci/tests/integration/targets/aci_fabric_switch_block/tasks/main.yml +++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_fabric_switch_block/tasks/main.yml @@ -4,13 +4,13 @@ # GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) - name: Test that we have an ACI APIC host, ACI username and ACI password - fail: + ansible.builtin.fail: msg: 'Please define the following variables: aci_hostname, aci_username and aci_password.' when: aci_hostname is not defined or aci_username is not defined or aci_password is not defined # GET Credentials from the inventory - name: Set vars - set_fact: + ansible.builtin.set_fact: aci_info: &aci_info host: "{{ aci_hostname }}" username: "{{ aci_username }}" @@ -22,13 +22,13 @@ # CLEAN ENVIRONMENT - name: Remove ansible_spine_switch_prf if it already exists - aci_fabric_spine_profile: + cisco.aci.aci_fabric_spine_profile: <<: *aci_info name: ansible_spine_switch_prf state: absent - name: Remove ansible_leaf_switch_prf if it already exists - aci_fabric_leaf_profile: + cisco.aci.aci_fabric_leaf_profile: <<: *aci_info name: ansible_leaf_switch_prf state: absent @@ -37,21 +37,21 @@ # CREATE SPINE SWITCH POLICY - name: Create ansible_spine_switch_prf - aci_fabric_spine_profile: + cisco.aci.aci_fabric_spine_profile: <<: *aci_info name: ansible_spine_switch_prf state: present # CREATE LEAF SWITCH POLICY - name: Create ansible_leaf_switch_prf - aci_fabric_leaf_profile: + cisco.aci.aci_fabric_leaf_profile: <<: *aci_info name: ansible_leaf_switch_prf state: present # CREATE SPINE SWITCH ASSOCIATION - name: Create a spine switch profile association - aci_fabric_spine_switch_assoc: + cisco.aci.aci_fabric_spine_switch_assoc: <<: *aci_info profile: ansible_spine_switch_prf name: ansible_spine_switch_assoc @@ -60,7 +60,7 @@ # CREATE LEAF SWITCH ASSOCIATION - name: Create a leaf switch profile association - aci_fabric_leaf_switch_assoc: + cisco.aci.aci_fabric_leaf_switch_assoc: <<: *aci_info profile: ansible_leaf_switch_prf name: ansible_leaf_switch_assoc @@ -69,7 +69,7 @@ # CREATE SPINE SWITCH BLOCK - name: Create a spine switch association block - aci_fabric_switch_block: + cisco.aci.aci_fabric_switch_block: <<: *aci_info switch_type: spine profile: ansible_spine_switch_prf @@ -81,7 +81,7 @@ register: add_switch_block - name: Verify spine block creation - assert: + ansible.builtin.assert: that: - add_switch_block.current.0.fabricNodeBlk.attributes.dn == "uni/fabric/spprof-ansible_spine_switch_prf/spines-ansible_spine_switch_assoc-typ-range/nodeblk-ansible_spine_block" - add_switch_block.current.0.fabricNodeBlk.attributes.name == "ansible_spine_block" @@ -89,7 +89,7 @@ # ADD SPINE SWITCH BLOCK AGAIN TO TEST IDEMPOTENCE - name: Create a spine switch association block again - aci_fabric_switch_block: + cisco.aci.aci_fabric_switch_block: <<: *aci_info switch_type: spine profile: ansible_spine_switch_prf @@ -101,7 +101,7 @@ register: add_switch_block_again - name: Verify spine block creation idempotence - assert: + ansible.builtin.assert: that: - add_switch_block_again is not changed - add_switch_block_again.current.0.fabricNodeBlk.attributes.dn == "uni/fabric/spprof-ansible_spine_switch_prf/spines-ansible_spine_switch_assoc-typ-range/nodeblk-ansible_spine_block" @@ -109,7 +109,7 @@ # CREATE LEAF SWITCH BLOCK - name: Create a leaf switch association block - aci_fabric_switch_block: + cisco.aci.aci_fabric_switch_block: <<: *aci_info switch_type: leaf profile: ansible_leaf_switch_prf @@ -121,14 +121,14 @@ register: add_leaf_switch_block - name: Verify leaf block creation - assert: + ansible.builtin.assert: that: - add_leaf_switch_block.current.0.fabricNodeBlk.attributes.dn == "uni/fabric/leprof-ansible_leaf_switch_prf/leaves-ansible_leaf_switch_assoc-typ-range/nodeblk-ansible_leaf_block" - add_leaf_switch_block.current.0.fabricNodeBlk.attributes.name == "ansible_leaf_block" # ADD LEAF SWITCH BLOCK AGAIN TO TEST IDEMPOTENCE - name: Create a leaf switch association block again - aci_fabric_switch_block: + cisco.aci.aci_fabric_switch_block: <<: *aci_info switch_type: leaf profile: ansible_leaf_switch_prf @@ -140,7 +140,7 @@ register: add_leaf_switch_block_again - name: Verify leaf block creation idempotence - assert: + ansible.builtin.assert: that: - add_leaf_switch_block_again is not changed - add_leaf_switch_block_again.current.0.fabricNodeBlk.attributes.dn == "uni/fabric/leprof-ansible_leaf_switch_prf/leaves-ansible_leaf_switch_assoc-typ-range/nodeblk-ansible_leaf_block" @@ -148,7 +148,7 @@ # QUERY SPINE SWITCH BLOCK - name: Query spine switch association block - aci_fabric_switch_block: + cisco.aci.aci_fabric_switch_block: <<: *aci_info switch_type: spine profile: ansible_spine_switch_prf @@ -158,7 +158,7 @@ register: query_switch_block - name: Verify block query - assert: + ansible.builtin.assert: that: - query_switch_block is not changed - query_switch_block.current.0.fabricNodeBlk.attributes.dn == "uni/fabric/spprof-ansible_spine_switch_prf/spines-ansible_spine_switch_assoc-typ-range/nodeblk-ansible_spine_block" @@ -166,7 +166,7 @@ # QUERY LEAF SWITCH BLOCK - name: Query leaf switch association block - aci_fabric_switch_block: + cisco.aci.aci_fabric_switch_block: <<: *aci_info switch_type: leaf profile: ansible_leaf_switch_prf @@ -176,7 +176,7 @@ register: query_leaf_switch_block - name: Verify leaf block query - assert: + ansible.builtin.assert: that: - query_leaf_switch_block is not changed - query_leaf_switch_block.current.0.fabricNodeBlk.attributes.dn == "uni/fabric/leprof-ansible_leaf_switch_prf/leaves-ansible_leaf_switch_assoc-typ-range/nodeblk-ansible_leaf_block" @@ -184,7 +184,7 @@ # REMOVE SPINE SWITCH BLOCK - name: Remove spine switch association block - aci_fabric_switch_block: + cisco.aci.aci_fabric_switch_block: <<: *aci_info switch_type: spine profile: ansible_spine_switch_prf @@ -194,7 +194,7 @@ register: delete_switch_block - name: Verify spine switch block removal - assert: + ansible.builtin.assert: that: - delete_switch_block is changed - delete_switch_block.current == [] @@ -203,7 +203,7 @@ # REMOVE SPINE SWITCH BLOCK AGAIN TO TEST IDEMPOTENCE - name: Remove spine switch association block - aci_fabric_switch_block: + cisco.aci.aci_fabric_switch_block: <<: *aci_info switch_type: spine profile: ansible_spine_switch_prf @@ -213,14 +213,14 @@ register: delete_switch_block - name: Verify spine switch block removal idempotence - assert: + ansible.builtin.assert: that: - delete_switch_block is not changed - delete_switch_block.current == [] # REMOVE LEAF SWITCH BLOCK - name: Remove leaf switch association block - aci_fabric_switch_block: + cisco.aci.aci_fabric_switch_block: <<: *aci_info switch_type: leaf profile: ansible_leaf_switch_prf @@ -230,7 +230,7 @@ register: delete_leaf_switch_block - name: Verify leaf switch block removal - assert: + ansible.builtin.assert: that: - delete_leaf_switch_block is changed - delete_leaf_switch_block.current == [] @@ -239,7 +239,7 @@ # REMOVE LEAF SWITCH BLOCK AGAIN TO TEST IDEMPOTENCE - name: Remove leaf switch association block - aci_fabric_switch_block: + cisco.aci.aci_fabric_switch_block: <<: *aci_info switch_type: leaf profile: ansible_leaf_switch_prf @@ -249,20 +249,20 @@ register: delete_leaf_switch_block - name: Verify leaf switch block removal idempotence - assert: + ansible.builtin.assert: that: - delete_leaf_switch_block is not changed - delete_leaf_switch_block.current == [] # CLEAN UP ENVIRONMENT - name: Remove ansible_spine_switch_prf - aci_fabric_spine_profile: + cisco.aci.aci_fabric_spine_profile: <<: *aci_info name: ansible_spine_switch_prf state: absent - name: Remove ansible_leaf_switch_prf - aci_fabric_leaf_profile: + cisco.aci.aci_fabric_leaf_profile: <<: *aci_info name: ansible_leaf_switch_prf state: absent diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_fabric_switch_policy_group/tasks/main.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_fabric_switch_policy_group/tasks/main.yml index 83f5355a6..82acdc7c3 100644 --- a/ansible_collections/cisco/aci/tests/integration/targets/aci_fabric_switch_policy_group/tasks/main.yml +++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_fabric_switch_policy_group/tasks/main.yml @@ -4,13 +4,13 @@ # GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) - name: Test that we have an ACI APIC host, ACI username and ACI password - fail: + ansible.builtin.fail: msg: 'Please define the following variables: aci_hostname, aci_username and aci_password.' when: aci_hostname is not defined or aci_username is not defined or aci_password is not defined # GET Credentials from the inventory - name: Set vars - set_fact: + ansible.builtin.set_fact: aci_info: &aci_info host: "{{ aci_hostname }}" username: "{{ aci_username }}" @@ -52,14 +52,14 @@ register: add_fabric_leaf_policy_group - name: Verify that ansible_fabric_leaf_policy_group has been created with correct attributes - assert: + ansible.builtin.assert: that: - add_fabric_leaf_policy_group.current.0.fabricLeNodePGrp.attributes.dn == "uni/fabric/funcprof/lenodepgrp-ansible_fabric_leaf_policy_group" - add_fabric_leaf_policy_group.current.0.fabricLeNodePGrp.attributes.name == "ansible_fabric_leaf_policy_group" - add_fabric_leaf_policy_group.current.0.fabricLeNodePGrp.attributes.annotation == 'orchestrator:ansible' - name: Verify that ansible_fabric_leaf_policy_group children have correct attributes - assert: + ansible.builtin.assert: that: - add_fabric_leaf_policy_group.current.0.fabricLeNodePGrp.children.0.fabricRsNodeCfgSrv.attributes.tDn == "uni/fabric/analytics/cluster-ansible_test/cfgsrv-ansible_test" - add_fabric_leaf_policy_group.current.0.fabricLeNodePGrp.children.1.fabricRsCallhomeInvPol.attributes.tnCallhomeInvPName == "default" @@ -78,14 +78,14 @@ register: add_fabric_leaf_policy_group_again - name: Verify that ansible_fabric_leaf_policy_group has not been changed - assert: + ansible.builtin.assert: that: - add_fabric_leaf_policy_group_again is not changed - add_fabric_leaf_policy_group_again.current.0.fabricLeNodePGrp.attributes.dn == "uni/fabric/funcprof/lenodepgrp-ansible_fabric_leaf_policy_group" - add_fabric_leaf_policy_group_again.current.0.fabricLeNodePGrp.attributes.name == "ansible_fabric_leaf_policy_group" - name: Verify that ansible_fabric_leaf_policy_group children are still correct - assert: + ansible.builtin.assert: that: - add_fabric_leaf_policy_group_again.current.0.fabricLeNodePGrp.children.0.fabricRsNodeCfgSrv.attributes.tDn == "uni/fabric/analytics/cluster-ansible_test/cfgsrv-ansible_test" - add_fabric_leaf_policy_group_again.current.0.fabricLeNodePGrp.children.1.fabricRsCallhomeInvPol.attributes.tnCallhomeInvPName == "default" @@ -112,13 +112,13 @@ register: add_fabric_spine_policy_group - name: Verify that ansible_fabric_spine_policy_group has been created with correct attributes - assert: + ansible.builtin.assert: that: - add_fabric_spine_policy_group.current.0.fabricSpNodePGrp.attributes.dn == "uni/fabric/funcprof/spnodepgrp-ansible_fabric_spine_policy_group" - add_fabric_spine_policy_group.current.0.fabricSpNodePGrp.attributes.name == "ansible_fabric_spine_policy_group" - name: Verify that ansible_fabric_spine_policy_group children have correct attributes - assert: + ansible.builtin.assert: that: - add_fabric_spine_policy_group.current.0.fabricSpNodePGrp.children.0.fabricRsCallhomeInvPol.attributes.tnCallhomeInvPName == "default" - add_fabric_spine_policy_group.current.0.fabricSpNodePGrp.children.1.fabricRsTwampResponderPol.attributes.tnTwampResponderPolName == "" @@ -136,14 +136,14 @@ register: add_fabric_spine_policy_group_again - name: Verify that ansible_fabric_spine_policy_group has not been changed - assert: + ansible.builtin.assert: that: - add_fabric_spine_policy_group_again is not changed - add_fabric_spine_policy_group_again.current.0.fabricSpNodePGrp.attributes.dn == "uni/fabric/funcprof/spnodepgrp-ansible_fabric_spine_policy_group" - add_fabric_spine_policy_group_again.current.0.fabricSpNodePGrp.attributes.name == "ansible_fabric_spine_policy_group" - name: Verify that ansible_fabric_spine_policy_group children are still correct - assert: + ansible.builtin.assert: that: - add_fabric_spine_policy_group_again.current.0.fabricSpNodePGrp.children.0.fabricRsCallhomeInvPol.attributes.tnCallhomeInvPName == "default" - add_fabric_spine_policy_group_again.current.0.fabricSpNodePGrp.children.1.fabricRsTwampResponderPol.attributes.tnTwampResponderPolName == "" @@ -166,14 +166,14 @@ register: update_fabric_leaf_policy_group - name: Verify ansible_fabric_leaf_policy_group is changed - assert: + ansible.builtin.assert: that: - update_fabric_leaf_policy_group is changed - update_fabric_leaf_policy_group.current.0.fabricLeNodePGrp.attributes.dn == "uni/fabric/funcprof/lenodepgrp-ansible_fabric_leaf_policy_group" - update_fabric_leaf_policy_group.current.0.fabricLeNodePGrp.attributes.name == "ansible_fabric_leaf_policy_group" - name: Verify ansible_fabric_leaf_policy_group children are updated - assert: + ansible.builtin.assert: that: - update_fabric_leaf_policy_group.current.0.fabricLeNodePGrp.children.0.fabricRsNodeCfgSrv.attributes.tDn == "uni/fabric/analytics/cluster-ansible_test/cfgsrv-ansible_test" - update_fabric_leaf_policy_group.current.0.fabricLeNodePGrp.children.1.fabricRsCallhomeInvPol.attributes.tnCallhomeInvPName == "default" @@ -197,14 +197,14 @@ register: update_fabric_spine_policy_group - name: Verify ansible_fabric_spine_policy_group is changed - assert: + ansible.builtin.assert: that: - update_fabric_spine_policy_group is changed - update_fabric_spine_policy_group.current.0.fabricSpNodePGrp.attributes.dn == "uni/fabric/funcprof/spnodepgrp-ansible_fabric_spine_policy_group" - update_fabric_spine_policy_group.current.0.fabricSpNodePGrp.attributes.name == "ansible_fabric_spine_policy_group" - name: Verify ansible_fabric_spine_policy_group children are updated - assert: + ansible.builtin.assert: that: - update_fabric_spine_policy_group.current.0.fabricSpNodePGrp.children.0.fabricRsCallhomeInvPol.attributes.tnCallhomeInvPName == "default" - update_fabric_spine_policy_group.current.0.fabricSpNodePGrp.children.1.fabricRsTwampResponderPol.attributes.tnTwampResponderPolName == "default" @@ -225,14 +225,14 @@ register: query_fabric_leaf_policy_group - name: Verify attributes - assert: + ansible.builtin.assert: that: - query_fabric_leaf_policy_group is not changed - query_fabric_leaf_policy_group.current.0.fabricLeNodePGrp.attributes.dn == "uni/fabric/funcprof/lenodepgrp-ansible_fabric_leaf_policy_group" - query_fabric_leaf_policy_group.current.0.fabricLeNodePGrp.attributes.name == "ansible_fabric_leaf_policy_group" - name: Verify children - assert: + ansible.builtin.assert: that: - query_fabric_leaf_policy_group.current.0.fabricLeNodePGrp.children.0.fabricRsNodeCfgSrv.attributes.tDn == "uni/fabric/analytics/cluster-ansible_test/cfgsrv-ansible_test" - query_fabric_leaf_policy_group.current.0.fabricLeNodePGrp.children.1.fabricRsCallhomeInvPol.attributes.tnCallhomeInvPName == "default" @@ -252,7 +252,7 @@ register: query_fabric_leaf_policy_group_all - name: Verify query all is idempotent - assert: + ansible.builtin.assert: that: - query_fabric_leaf_policy_group_all is not changed @@ -266,14 +266,14 @@ register: query_fabric_spine_policy_group - name: Verify attributes - assert: + ansible.builtin.assert: that: - query_fabric_spine_policy_group is not changed - query_fabric_spine_policy_group.current.0.fabricSpNodePGrp.attributes.dn == "uni/fabric/funcprof/spnodepgrp-ansible_fabric_spine_policy_group" - query_fabric_spine_policy_group.current.0.fabricSpNodePGrp.attributes.name == "ansible_fabric_spine_policy_group" - name: Verify children - assert: + ansible.builtin.assert: that: - query_fabric_spine_policy_group.current.0.fabricSpNodePGrp.children.0.fabricRsCallhomeInvPol.attributes.tnCallhomeInvPName == "default" - query_fabric_spine_policy_group.current.0.fabricSpNodePGrp.children.1.fabricRsTwampResponderPol.attributes.tnTwampResponderPolName == "default" @@ -292,7 +292,7 @@ register: query_fabric_spine_policy_group_all - name: Verify query all is idempotent - assert: + ansible.builtin.assert: that: - query_fabric_spine_policy_group_all is not changed @@ -306,7 +306,7 @@ register: delete_fabric_leaf_policy_group - name: Verify Fabric Leaf Policy Group deletion - assert: + ansible.builtin.assert: that: - delete_fabric_leaf_policy_group is changed - delete_fabric_leaf_policy_group.current == [] @@ -330,7 +330,7 @@ register: delete_fabric_spine_policy_group - name: Verify Fabric Spine Policy Group deletion - assert: + ansible.builtin.assert: that: - delete_fabric_spine_policy_group is changed - delete_fabric_spine_policy_group.current == [] diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_fabric_wide_settings/tasks/main.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_fabric_wide_settings/tasks/main.yml index 526c8bee0..387d23580 100644 --- a/ansible_collections/cisco/aci/tests/integration/targets/aci_fabric_wide_settings/tasks/main.yml +++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_fabric_wide_settings/tasks/main.yml @@ -5,12 +5,12 @@ # GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) - name: Test that we have an ACI APIC host, ACI username and ACI password - fail: + ansible.builtin.fail: msg: 'Please define the following variables: aci_hostname, aci_username and aci_password.' when: aci_hostname is not defined or aci_username is not defined or aci_password is not defined - name: Set vars - set_fact: + ansible.builtin.set_fact: aci_info: &aci_info host: "{{ aci_hostname }}" username: "{{ aci_username }}" @@ -21,7 +21,7 @@ output_level: '{{ aci_output_level | default("info") }}' - name: Verify Cloud and Non-Cloud Sites in use. - include_tasks: ../../../../../../integration/targets/aci_cloud_provider/tasks/main.yml + ansible.builtin.include_tasks: ../../../../../../integration/targets/aci_cloud_provider/tasks/main.yml - name: Execute tasks only for non-cloud sites when: query_cloud.current == [] # This condition will skip execution for cloud sites diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_file_remote_path/tasks/main.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_file_remote_path/tasks/main.yml index ab1560ba6..c0fcbaa9f 100644 --- a/ansible_collections/cisco/aci/tests/integration/targets/aci_file_remote_path/tasks/main.yml +++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_file_remote_path/tasks/main.yml @@ -4,12 +4,12 @@ # GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) - name: Test that we have an ACI APIC host, ACI username and ACI password - fail: + ansible.builtin.fail: msg: 'Please define the following variables: aci_hostname, aci_username and aci_password.' when: aci_hostname is not defined or aci_username is not defined or aci_password is not defined - name: Set vars - set_fact: + ansible.builtin.set_fact: aci_info: &aci_info host: "{{ aci_hostname }}" username: "{{ aci_username }}" diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_filter/tasks/main.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_filter/tasks/main.yml index a8928de57..db4e07eff 100644 --- a/ansible_collections/cisco/aci/tests/integration/targets/aci_filter/tasks/main.yml +++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_filter/tasks/main.yml @@ -4,7 +4,7 @@ # GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) - name: Test that we have an ACI APIC host, ACI username and ACI password - fail: + ansible.builtin.fail: msg: 'Please define the following variables: aci_hostname, aci_username and aci_password.' when: aci_hostname is not defined or aci_username is not defined or aci_password is not defined @@ -64,7 +64,7 @@ register: nm_add_filter_again - name: Verify add_filter - assert: + ansible.builtin.assert: that: - cm_add_filter is changed - cm_add_filter_again is changed @@ -100,7 +100,7 @@ register: nm_add_filter_descr_again - name: Verify add_filter_descr - assert: + ansible.builtin.assert: that: - cm_add_filter_descr is changed - cm_add_filter_descr_again is changed @@ -118,7 +118,7 @@ register: nm_add_filter_again_no_descr - name: Verify add_filter_again_no_descr - assert: + ansible.builtin.assert: that: - cm_add_filter_again_no_descr is not changed - nm_add_filter_again_no_descr is not changed @@ -142,7 +142,7 @@ register: nm_query_all_filters - name: Verify query_all_filters - assert: + ansible.builtin.assert: that: - cm_query_all_filters is not changed - nm_query_all_filters is not changed @@ -166,7 +166,7 @@ register: nm_query_filter - name: Verify query_filter - assert: + ansible.builtin.assert: that: - cm_query_filter is not changed - nm_query_filter is not changed @@ -192,7 +192,7 @@ register: nm_remove_filter_again - name: Verify remove_filter - assert: + ansible.builtin.assert: that: - cm_remove_filter is changed - cm_remove_filter_again is changed @@ -217,7 +217,7 @@ register: nm_query_non_filter - name: Verify query_non_filter - assert: + ansible.builtin.assert: that: - cm_query_non_filter is not changed - nm_query_non_filter is not changed diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_filter_entry/tasks/main.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_filter_entry/tasks/main.yml index e969111a2..859df9e97 100644 --- a/ansible_collections/cisco/aci/tests/integration/targets/aci_filter_entry/tasks/main.yml +++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_filter_entry/tasks/main.yml @@ -4,13 +4,13 @@ # GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) - name: Test that we have an ACI APIC host, ACI username and ACI password - fail: + ansible.builtin.fail: msg: 'Please define the following variables: aci_hostname, aci_username and aci_password.' when: aci_hostname is not defined or aci_username is not defined or aci_password is not defined # CLEAN ENVIRONMENT - name: Set vars - set_fact: + ansible.builtin.set_fact: aci_info: &aci_info host: "{{ aci_hostname }}" username: "{{ aci_username }}" @@ -21,7 +21,7 @@ output_level: '{{ aci_output_level | default("debug") }}' - name: Verify Cloud and Non-Cloud Sites in use. - include_tasks: ../../../../../../integration/targets/aci_cloud_provider/tasks/main.yml + ansible.builtin.include_tasks: ../../../../../../integration/targets/aci_cloud_provider/tasks/main.yml # TODO current module will fail on cloud sites because range is not supported # APIC Error 1: Invalid Configuration CLOUD_SOURCE_PORT_NOT_SUPPORTED: vz::EntryMo Dn = uni/tn-ansible_test/flt-anstest_fileter_2/e-source_port_start - Source port range is not allowed on CAPIC" @@ -176,7 +176,7 @@ register: icmp6_msg_type_est - name: Assertion check for the filter entry - match_only_fragments, source_port and tcp_flags attributes - assert: + ansible.builtin.assert: that: - nt_match_only_fragments_with_dst_port is not changed - nt_match_only_fragments_with_dst_port.msg == "Parameter 'match_only_fragments' cannot be used with 'Layer 4 Port' value" @@ -266,7 +266,7 @@ register: entry_present_update - name: Verify Cloud and Non-Cloud Sites in use. - include_tasks: ../../../../../../integration/targets/aci_cloud_provider/tasks/main.yml + ansible.builtin.include_tasks: ../../../../../../integration/targets/aci_cloud_provider/tasks/main.yml - name: create filter entry - test different types cisco.aci.aci_filter_entry: @@ -309,7 +309,7 @@ register: present_incompatible_params - name: present assertions - assert: + ansible.builtin.assert: that: - entry_present_check_mode is changed - entry_present_check_mode.previous == [] @@ -346,7 +346,7 @@ - present_incompatible_params.msg.startswith("Parameter") - name: present assertions for arp - assert: + ansible.builtin.assert: that: - entry_present_2 is changed - entry_present_2.sent.vzEntry.attributes.arpOpc == 'reply' @@ -406,7 +406,7 @@ register: query_all - name: query assertions for all - assert: + ansible.builtin.assert: that: - query_tenant_filter_entry is not changed - query_tenant_filter_entry.current | length == 1 @@ -450,7 +450,7 @@ - name: query assertions for only Non-Cloud - assert: + ansible.builtin.assert: that: - query_tenant_filter.current.0.vzFilter.children | length == 4 when: query_cloud.current == [] # This condition will skip execution for cloud sites @@ -486,7 +486,7 @@ with_items: ["anstest2", "anstest3", "anstest4"] - name: absent assertions - assert: + ansible.builtin.assert: that: - entry_absent_check_mode is changed - entry_absent_check_mode.previous != [] diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_filter_listify/aliases b/ansible_collections/cisco/aci/tests/integration/targets/aci_filter_listify/aliases new file mode 100644 index 000000000..209b793f9 --- /dev/null +++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_filter_listify/aliases @@ -0,0 +1,2 @@ +# No ACI simulator yet, so not enabled +# unsupported diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_filter_listify/tasks/main.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_filter_listify/tasks/main.yml new file mode 100644 index 000000000..a186c9ce6 --- /dev/null +++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_filter_listify/tasks/main.yml @@ -0,0 +1,197 @@ +# Test code for the ACI modules +# Copyright: (c) 2023, Shreyas Srish (shrsr@cisco.com) +# Copyright: (c) 2024, Akini Ross +# +# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) + +- name: Test that we have an ACI APIC host, ACI username and ACI password + ansible.builtin.fail: + msg: 'Please define the following variables: aci_hostname, aci_username and aci_password.' + when: aci_hostname is not defined or aci_username is not defined or aci_password is not defined + +- name: Set vars + ansible.builtin.set_fact: + aci_info: &aci_info + host: "{{ aci_hostname }}" + username: "{{ aci_username }}" + password: "{{ aci_password }}" + validate_certs: '{{ aci_validate_certs | default(false) }}' + use_ssl: '{{ aci_use_ssl | default(true) }}' + use_proxy: '{{ aci_use_proxy | default(true) }}' + output_level: '{{ aci_output_level | default("info") }}' + aci_model_data: + tenant: + - name: ansible_test + description: Created using listify + app: + - name: app_test + epg: + - name: web + bd: web_bd + - name: app + bd: app_bd + bd: + - name: bd_test + subnet: + - name: 10.10.10.1 + mask: 24 + scope: + - private + - shared + vrf: vrf_test + - name: bd_test2 + subnet: + - name: 20.20.20.1 + mask: 24 + scope: [public, shared] + vrf: vrf_test + vrf: + - name: vrf_test + - name: ansible_test2 + description: Created using listify + app: + - name: app_test2 + epg: + - name: web2 + bd: web_bd2 + - name: app2 + bd: app_bd2 + policies: + protocol: + bfd: + - name: BFD-ON + description: Enable BFD + admin_state: enabled + detection_multiplier: 3 + min_tx_interval: 50 + min_rx_interval: 50 + echo_rx_interval: 50 + echo_admin_state: enabled + sub_interface_optimization_state: enabled + ospf: + interface: + - name: OSPF-P2P-IntPol + network_type: p2p + priority: 1 + - name: OSPF-Broadcast-IntPol + network_type: bcast + priority: 1 + +- name: Verify Cloud and Non-Cloud Sites in use. + ansible.builtin.include_tasks: ../../../../../../integration/targets/aci_cloud_provider/tasks/main.yml + +- name: Execute tasks only for non-cloud sites + when: query_cloud.current == [] # This condition will execute only non-cloud sites + block: # block specifies execution of tasks within, based on conditions + + - name: Set facts for nested dictionaries + ansible.builtin.set_fact: + bfd_listify_output: '{{ aci_model_data|cisco.aci.aci_listify("tenant", "policies", "protocol", "bfd") }}' + ospf_listify_output: '{{ aci_model_data|cisco.aci.aci_listify("tenant", "policies", "protocol", "ospf", "interface") }}' + + - name: Validate listify for nested dictionaries + ansible.builtin.assert: + that: + - bfd_listify_output.0.tenant_name == "ansible_test2" + - bfd_listify_output.0.tenant_description == "Created using listify" + - bfd_listify_output.0.tenant_policies_protocol_bfd_admin_state == "enabled" + - bfd_listify_output.0.tenant_policies_protocol_bfd_description == "Enable BFD" + - bfd_listify_output.0.tenant_policies_protocol_bfd_detection_multiplier == 3 + - bfd_listify_output.0.tenant_policies_protocol_bfd_echo_admin_state == "enabled" + - bfd_listify_output.0.tenant_policies_protocol_bfd_echo_rx_interval == 50 + - bfd_listify_output.0.tenant_policies_protocol_bfd_min_rx_interval == 50 + - bfd_listify_output.0.tenant_policies_protocol_bfd_min_tx_interval == 50 + - bfd_listify_output.0.tenant_policies_protocol_bfd_name == "BFD-ON" + - bfd_listify_output.0.tenant_policies_protocol_bfd_sub_interface_optimization_state == "enabled" + - ospf_listify_output.0.tenant_name == "ansible_test2" + - ospf_listify_output.0.tenant_description == "Created using listify" + - ospf_listify_output.0.tenant_policies_protocol_ospf_interface_name == "OSPF-P2P-IntPol" + - ospf_listify_output.0.tenant_policies_protocol_ospf_interface_network_type == "p2p" + - ospf_listify_output.0.tenant_policies_protocol_ospf_interface_priority == 1 + - ospf_listify_output.1.tenant_policies_protocol_ospf_interface_name == "OSPF-Broadcast-IntPol" + - ospf_listify_output.1.tenant_policies_protocol_ospf_interface_network_type == "bcast" + - ospf_listify_output.1.tenant_policies_protocol_ospf_interface_priority == 1 + + - name: Create tenants + cisco.aci.aci_tenant: + <<: *aci_info + tenant: '{{ item.tenant_name }}' + description: '{{ item.tenant_description }}' + with_items: '{{ aci_model_data|cisco.aci.aci_listify("tenant") }}' + register: tenant_listify + + - name: Create VRFs + cisco.aci.aci_vrf: + <<: *aci_info + tenant: '{{ item.tenant_name }}' + vrf_name: '{{ item.tenant_vrf_name }}' + with_items: '{{ aci_model_data|cisco.aci.aci_listify("tenant","vrf") }}' + register: vrf_listify + + - name: Create BDs + cisco.aci.aci_bd: + <<: *aci_info + tenant: '{{ item.tenant_name }}' + vrf: '{{ item.tenant_bd_vrf }}' + bd: '{{ item.tenant_bd_name }}' + enable_routing: yes + with_items: '{{ aci_model_data|cisco.aci.aci_listify("tenant","bd") }}' + register: bd_listify + + - name: Create BD subnets + cisco.aci.aci_bd_subnet: + <<: *aci_info + tenant: '{{ item.tenant_name }}' + bd: '{{ item.tenant_bd_name }}' + gateway: '{{ item.tenant_bd_subnet_name }}' + mask: '{{ item.tenant_bd_subnet_mask }}' + scope: '{{ item.tenant_bd_subnet_scope }}' + with_items: '{{ aci_model_data|cisco.aci.aci_listify("tenant","bd","subnet") }}' + register: bd_subnets_listify + + - name: Create APs + cisco.aci.aci_ap: + <<: *aci_info + tenant: '{{ item.tenant_name }}' + app_profile: '{{ item.tenant_app_name }}' + with_items: '{{ aci_model_data|cisco.aci.aci_listify("tenant","app") }}' + register: ap_listify + + - name: Create EPGs + cisco.aci.aci_epg: + <<: *aci_info + tenant: '{{ item.tenant_name }}' + app_profile: '{{ item.tenant_app_name }}' + epg: '{{ item.tenant_app_epg_name }}' + bd: '{{ item.tenant_app_epg_bd }}' + with_items: '{{ aci_model_data|cisco.aci.aci_listify("tenant","app","epg") }}' + register: epg_listify + + - name: Validate listify + ansible.builtin.assert: + that: + - tenant_listify.results.0.current.0.fvTenant.attributes.name == "ansible_test" + - vrf_listify.results.0.current.0.fvCtx.attributes.name == "vrf_test" + - bd_listify.results.0.current.0.fvBD.attributes.name == "bd_test" + - bd_listify.results.1.current.0.fvBD.attributes.name == "bd_test2" + - bd_subnets_listify.results.0.current.0.fvSubnet.attributes.ip == "10.10.10.1/24" + - bd_subnets_listify.results.0.current.0.fvSubnet.attributes.scope == "private,shared" + - bd_subnets_listify.results.1.current.0.fvSubnet.attributes.ip == "20.20.20.1/24" + - bd_subnets_listify.results.1.current.0.fvSubnet.attributes.scope == "public,shared" + - ap_listify.results.0.current.0.fvAp.attributes.name == "app_test" + - epg_listify.results.0.current.0.fvAEPg.attributes.name == "web" + - epg_listify.results.1.current.0.fvAEPg.attributes.name == "app" + - tenant_listify.results.1.current.0.fvTenant.attributes.name == "ansible_test2" + - ap_listify.results.1.current.0.fvAp.attributes.name == "app_test2" + - epg_listify.results.2.current.0.fvAEPg.attributes.name == "web2" + - epg_listify.results.3.current.0.fvAEPg.attributes.name == "app2" + + # Clean Up Environment + - name: Delete tenants + cisco.aci.aci_tenant: + <<: *aci_info + tenant: "{{ item }}" + state: absent + loop: + - ansible_test + - ansible_test2 diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_firmware_group/tasks/main.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_firmware_group/tasks/main.yml index 5cf88997c..6f2fc7907 100644 --- a/ansible_collections/cisco/aci/tests/integration/targets/aci_firmware_group/tasks/main.yml +++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_firmware_group/tasks/main.yml @@ -4,12 +4,12 @@ # GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) - name: Test that we have an ACI APIC host, ACI username and ACI password - fail: + ansible.builtin.fail: msg: 'Please define the following variables: aci_hostname, aci_username and aci_password.' when: aci_hostname is not defined or aci_username is not defined or aci_password is not defined - name: Set vars - set_fact: + ansible.builtin.set_fact: aci_info: &aci_info host: "{{ aci_hostname }}" username: "{{ aci_username }}" @@ -20,21 +20,21 @@ output_level: debug - name: Verify Cloud and Non-Cloud Sites in use. - include_tasks: ../../../../../../integration/targets/aci_cloud_provider/tasks/main.yml + ansible.builtin.include_tasks: ../../../../../../integration/targets/aci_cloud_provider/tasks/main.yml - name: Execute tasks only for non-cloud sites when: query_cloud.current == [] # This condition will execute only non-cloud sites block: # block specifies execution of tasks within, based on conditions # Clean Environment - name: Create firmware policy - aci_firmware_policy: &aci_firmware_policy_present + cisco.aci.aci_firmware_policy: &aci_firmware_policy_present <<: *aci_info name: anstest_policy version: n9000-15.2(7) state: present - name: Ensure first firmware group does not exist - aci_firmware_group: &aci_firmware_group_absent + cisco.aci.aci_firmware_group: &aci_firmware_group_absent <<: *aci_info group: anstest_group policy: anstest_policy @@ -43,37 +43,37 @@ state: absent - name: Ensure second firmware group does not exist - aci_firmware_group: &aci_firmware_group_2_absent + cisco.aci.aci_firmware_group: &aci_firmware_group_2_absent <<: *aci_info group: anstest_group_2 policy: anstest_policy state: absent - name: Create first firmware group (check_mode) - aci_firmware_group: &aci_firmware_group_present + cisco.aci.aci_firmware_group: &aci_firmware_group_present <<: *aci_firmware_group_absent state: present check_mode: true register: cm_add_firmware_group_1 - name: Create first firmware group (normal_mode) - aci_firmware_group: + cisco.aci.aci_firmware_group: <<: *aci_firmware_group_present register: nm_add_firmware_group_1 - name: Create first firmware group again - testing idempotency - aci_firmware_group: + cisco.aci.aci_firmware_group: <<: *aci_firmware_group_present register: idempotency_add_firmware_group_1 - name: Create second firmware group - aci_firmware_group: &aci_firmware_group_2_present + cisco.aci.aci_firmware_group: &aci_firmware_group_2_present <<: *aci_firmware_group_2_absent state: present register: nm_add_firmware_group_2 - name: Asserts for creation tasks - assert: + ansible.builtin.assert: that: - cm_add_firmware_group_1 is changed - cm_add_firmware_group_1.previous == [] @@ -86,19 +86,19 @@ - nm_add_firmware_group_2 is changed - name: Query all firmware groups - aci_firmware_group: + cisco.aci.aci_firmware_group: <<: *aci_info state: query register: query_all_firmware_group - name: Query first firmware group - aci_firmware_group: + cisco.aci.aci_firmware_group: <<: *aci_firmware_group_present state: query register: query_first_firmware_group - name: Asserts for query tasks - assert: + ansible.builtin.assert: that: - query_all_firmware_group is not changed - query_all_firmware_group.current | length >= 2 @@ -110,32 +110,32 @@ - query_first_firmware_group.current.0.firmwareFwGrp.children.0.firmwareRsFwgrpp.attributes.tnFirmwareFwPName == "anstest_policy" - name: Delete first firmware group (check_mode) - aci_firmware_group: + cisco.aci.aci_firmware_group: <<: *aci_firmware_group_present state: absent check_mode: true register: cm_delete_firmware_group_1 - name: Delete first firmware group (normal_mode) - aci_firmware_group: + cisco.aci.aci_firmware_group: <<: *aci_firmware_group_present state: absent register: nm_delete_firmware_group_1 - name: Delete first firmware group again - testing idempotency - aci_firmware_group: + cisco.aci.aci_firmware_group: <<: *aci_firmware_group_present state: absent register: idempotency_delete_firmware_group_1 - name: Delete second firmware group (normal_mode) - aci_firmware_group: + cisco.aci.aci_firmware_group: <<: *aci_firmware_group_2_present state: absent register: nm_delete_firmware_group_2 - name: Asserts for deletion tasks - assert: + ansible.builtin.assert: that: - cm_delete_firmware_group_1 is changed - cm_delete_firmware_group_1.proposed == {} @@ -149,6 +149,6 @@ - nm_delete_firmware_group_2.current == [] - name: Delete firmware policy - clean up the environment - aci_firmware_policy: + cisco.aci.aci_firmware_policy: <<: *aci_firmware_policy_present state: absent diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_firmware_group_node/tasks/main.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_firmware_group_node/tasks/main.yml index 8da20a7ca..49cba8fa2 100644 --- a/ansible_collections/cisco/aci/tests/integration/targets/aci_firmware_group_node/tasks/main.yml +++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_firmware_group_node/tasks/main.yml @@ -4,12 +4,12 @@ # GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) - name: Test that we have an ACI APIC host, ACI username and ACI password - fail: + ansible.builtin.fail: msg: 'Please define the following variables: aci_hostname, aci_username and aci_password.' when: aci_hostname is not defined or aci_username is not defined or aci_password is not defined - name: Set vars - set_fact: + ansible.builtin.set_fact: aci_info: &aci_info host: "{{ aci_hostname }}" username: "{{ aci_username }}" @@ -20,65 +20,65 @@ output_level: debug - name: Verify Cloud and Non-Cloud Sites in use. - include_tasks: ../../../../../../integration/targets/aci_cloud_provider/tasks/main.yml + ansible.builtin.include_tasks: ../../../../../../integration/targets/aci_cloud_provider/tasks/main.yml - name: Execute tasks only for non-cloud sites when: query_cloud.current == [] # This condition will execute only non-cloud sites block: # block specifies execution of tasks within, based on conditions # Clean Environment - name: Create firmware policy exists - aci_firmware_policy: &aci_firmware_policy_present + cisco.aci.aci_firmware_policy: &aci_firmware_policy_present <<: *aci_info name: anstest_policy version: n9000-15.2(7) state: present - name: Create first firmware group - aci_firmware_group: &aci_firmware_group_present + cisco.aci.aci_firmware_group: &aci_firmware_group_present <<: *aci_info group: anstest_group firmwarepol: anstest_policy state: present - name: Ensure first firmware group node does not exist - aci_firmware_group_node: &aci_firmware_group_node_absent + cisco.aci.aci_firmware_group_node: &aci_firmware_group_node_absent <<: *aci_info group: anstest_group node: 1001 state: absent - name: Ensure second firmware group node does not exist - aci_firmware_group_node: &aci_firmware_group_node_2_absent + cisco.aci.aci_firmware_group_node: &aci_firmware_group_node_2_absent <<: *aci_info group: anstest_group node: 1002 state: absent - name: Create first firmware group node (check_mode) - aci_firmware_group_node: &aci_firmware_group_node_present + cisco.aci.aci_firmware_group_node: &aci_firmware_group_node_present <<: *aci_firmware_group_node_absent state: present check_mode: true register: cm_add_firmware_group_node_1 - name: Create first firmware group node (normal_mode) - aci_firmware_group_node: + cisco.aci.aci_firmware_group_node: <<: *aci_firmware_group_node_present register: nm_add_firmware_group_node_1 - name: Create first firmware group node again - testing idempotency - aci_firmware_group_node: + cisco.aci.aci_firmware_group_node: <<: *aci_firmware_group_node_present register: idempotency_add_firmware_group_node_1 - name: Create second firmware group node - aci_firmware_group_node: &aci_firmware_group_node_2_present + cisco.aci.aci_firmware_group_node: &aci_firmware_group_node_2_present <<: *aci_firmware_group_node_2_absent state: present register: nm_add_firmware_group_node_2 - name: Asserts for creation tasks - assert: + ansible.builtin.assert: that: - cm_add_firmware_group_node_1 is changed - cm_add_firmware_group_node_1.previous == [] @@ -93,19 +93,19 @@ - name: Query all firmware group nodes - aci_firmware_group_node: + cisco.aci.aci_firmware_group_node: <<: *aci_info state: query register: query_all_firmware_group_node - name: Query first firmware group nnode - aci_firmware_group_node: + cisco.aci.aci_firmware_group_node: <<: *aci_firmware_group_node_present state: query register: query_first_firmware_group_node - name: Asserts for query tasks - assert: + ansible.builtin.assert: that: - query_all_firmware_group_node is not changed - query_all_firmware_group_node.current | length >= 2 @@ -115,32 +115,32 @@ - query_first_firmware_group_node.current.0.fabricNodeBlk.attributes.to_ == "1001" - name: Delete first firmware group (check_mode) - aci_firmware_group_node: + cisco.aci.aci_firmware_group_node: <<: *aci_firmware_group_node_present state: absent check_mode: true register: cm_delete_firmware_group_node_1 - name: Delete first firmware group (normal_mode) - aci_firmware_group_node: + cisco.aci.aci_firmware_group_node: <<: *aci_firmware_group_node_present state: absent register: nm_delete_firmware_group_node_1 - name: Delete first firmware group again - testing idempotency - aci_firmware_group_node: + cisco.aci.aci_firmware_group_node: <<: *aci_firmware_group_node_present state: absent register: idempotency_delete_firmware_group_1 - name: Delete second firmware group (normal_mode) - aci_firmware_group_node: + cisco.aci.aci_firmware_group_node: <<: *aci_firmware_group_node_2_present state: absent register: nm_delete_firmware_group_node_2 - name: Asserts for deletion tasks - assert: + ansible.builtin.assert: that: - cm_delete_firmware_group_node_1 is changed - cm_delete_firmware_group_node_1.proposed == {} @@ -154,11 +154,11 @@ - nm_delete_firmware_group_node_2.current == [] - name: Delete firmware group - clean up the environment - aci_firmware_group: + cisco.aci.aci_firmware_group: <<: *aci_firmware_group_present state: absent - name: Delete firmware policy - clean up the environment - aci_firmware_policy: + cisco.aci.aci_firmware_policy: <<: *aci_firmware_policy_present state: absent diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_firmware_policy/tasks/main.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_firmware_policy/tasks/main.yml index ec0bb88ae..4b4be8ad8 100644 --- a/ansible_collections/cisco/aci/tests/integration/targets/aci_firmware_policy/tasks/main.yml +++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_firmware_policy/tasks/main.yml @@ -4,12 +4,12 @@ # GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) - name: Test that we have an ACI APIC host, ACI username and ACI password - fail: + ansible.builtin.fail: msg: 'Please define the following variables: aci_hostname, aci_username and aci_password.' when: aci_hostname is not defined or aci_username is not defined or aci_password is not defined - name: Set vars - set_fact: + ansible.builtin.set_fact: aci_info: &aci_info host: "{{ aci_hostname }}" username: "{{ aci_username }}" @@ -20,14 +20,14 @@ output_level: debug - name: Verify Cloud and Non-Cloud Sites in use. - include_tasks: ../../../../../../integration/targets/aci_cloud_provider/tasks/main.yml + ansible.builtin.include_tasks: ../../../../../../integration/targets/aci_cloud_provider/tasks/main.yml - name: Execute tasks only for non-cloud sites when: query_cloud.current == [] # This condition will execute only non-cloud sites block: # block specifies execution of tasks within, based on conditions # Clean Environment - name: Ensure first firmware policy does not exist - aci_firmware_policy: &aci_firmware_policy_absent + cisco.aci.aci_firmware_policy: &aci_firmware_policy_absent <<: *aci_info name: anstest_policy version: n9000-15.2(7) @@ -35,37 +35,37 @@ state: absent - name: Ensure second firmware policy does not exist - aci_firmware_policy: &aci_firmware_policy_2_absent + cisco.aci.aci_firmware_policy: &aci_firmware_policy_2_absent <<: *aci_info name: anstest_policy_2 version: n9000-16.0(1) state: absent - name: Create first firmware policy (check_mode) - aci_firmware_policy: &aci_firmware_policy_present + cisco.aci.aci_firmware_policy: &aci_firmware_policy_present <<: *aci_firmware_policy_absent state: present check_mode: true register: cm_add_firmware_policy_1 - name: Create first firmware policy (normal_mode) - aci_firmware_policy: + cisco.aci.aci_firmware_policy: <<: *aci_firmware_policy_present register: nm_add_firmware_policy_1 - name: Create first firmware policy again - testing idempotency - aci_firmware_policy: + cisco.aci.aci_firmware_policy: <<: *aci_firmware_policy_present register: idempotency_add_firmware_policy_1 - name: Create second firmware policy - aci_firmware_policy: &aci_firmware_policy_2_present + cisco.aci.aci_firmware_policy: &aci_firmware_policy_2_present <<: *aci_firmware_policy_2_absent state: present register: nm_add_firmware_policy_2 - name: Asserts for creation tasks - assert: + ansible.builtin.assert: that: - cm_add_firmware_policy_1 is changed - cm_add_firmware_policy_1.previous == [] @@ -81,19 +81,19 @@ - nm_add_firmware_policy_2.current.0.firmwareFwP.attributes.version == "n9000-16.0(1)" - name: Query all firmware policies - aci_firmware_policy: + cisco.aci.aci_firmware_policy: <<: *aci_info state: query register: query_all_firmware_policy - name: Query first firmware policy - aci_firmware_policy: + cisco.aci.aci_firmware_policy: <<: *aci_firmware_policy_present state: query register: query_first_firmware_policy - name: Asserts for query tasks - assert: + ansible.builtin.assert: that: - query_all_firmware_policy is not changed - query_all_firmware_policy.current | length >= 2 @@ -104,32 +104,32 @@ - query_first_firmware_policy.current.0.firmwareFwP.attributes.version == "n9000-15.2(7)" - name: Delete first firmware policy (check_mode) - aci_firmware_policy: + cisco.aci.aci_firmware_policy: <<: *aci_firmware_policy_present state: absent check_mode: true register: cm_delete_firmware_policy_1 - name: Delete first firmware policy (normal_mode) - aci_firmware_policy: + cisco.aci.aci_firmware_policy: <<: *aci_firmware_policy_present state: absent register: nm_delete_firmware_policy_1 - name: Delete first firmware policy again - testing idempotency - aci_firmware_policy: + cisco.aci.aci_firmware_policy: <<: *aci_firmware_policy_present state: absent register: idempotency_delete_firmware_policy_1 - name: Delete second firmware policy (normal_mode) - aci_firmware_policy: + cisco.aci.aci_firmware_policy: <<: *aci_firmware_policy_2_present state: absent register: nm_delete_firmware_policy_2 - name: Asserts for deletion tasks - assert: + ansible.builtin.assert: that: - cm_delete_firmware_policy_1 is changed - cm_delete_firmware_policy_1.proposed == {} diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_firmware_source/tasks/main.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_firmware_source/tasks/main.yml index d9287506c..a02049473 100644 --- a/ansible_collections/cisco/aci/tests/integration/targets/aci_firmware_source/tasks/main.yml +++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_firmware_source/tasks/main.yml @@ -22,7 +22,7 @@ # ADD SOURCE - name: Add source (check_mode) - aci_firmware_source: &source_present + cisco.aci.aci_firmware_source: &source_present host: '{{ aci_hostname }}' username: '{{ aci_username }}' password: '{{ aci_password }}' @@ -38,12 +38,12 @@ register: cm_add_source - name: Add source (normal mode) - aci_firmware_source: + cisco.aci.aci_firmware_source: <<: *source_present register: nm_add_source - name: Verify add_source - assert: + ansible.builtin.assert: that: - cm_add_source is changed - nm_add_source is changed @@ -60,22 +60,22 @@ - nm_add_source.current.0.firmwareOSource.attributes.annotation == 'orchestrator:ansible' - name: Add source again (check_mode) - aci_firmware_source: *source_present + cisco.aci.aci_firmware_source: *source_present check_mode: true register: cm_add_source_again - name: Add source again (normal mode) - aci_firmware_source: + cisco.aci.aci_firmware_source: <<: *source_present register: nm_add_source_again - name: Verify add_source_again - assert: + ansible.builtin.assert: that: - cm_add_source_again is not changed - name: Add another source (normal mode) - aci_firmware_source: + cisco.aci.aci_firmware_source: <<: *source_present source: ansible_test_2 register: nm_add_source @@ -99,7 +99,7 @@ register: nm_query_all_sources - name: Verify query_all_sources - assert: + ansible.builtin.assert: that: - cm_query_all_sources is not changed - nm_query_all_sources is not changed @@ -108,20 +108,20 @@ # QUERY A SOURCE - name: Query our source (check_mode) - aci_firmware_source: + cisco.aci.aci_firmware_source: <<: *source_query source: ansible_test_1 check_mode: true register: cm_query_source - name: Query our source (normal mode) - aci_firmware_source: + cisco.aci.aci_firmware_source: <<: *source_query source: ansible_test_1 register: nm_query_source - name: Verify query_source - assert: + ansible.builtin.assert: that: - cm_query_source is not changed - nm_query_source is not changed @@ -131,7 +131,7 @@ # REMOVE SOURCE - name: Remove source (check_mode) - aci_firmware_source: &source_remove + cisco.aci.aci_firmware_source: &source_remove <<: *source_query source: ansible_test_1 state: absent @@ -139,11 +139,11 @@ register: cm_remove_source - name: Remove source (normal mode) - aci_firmware_source: *source_remove + cisco.aci.aci_firmware_source: *source_remove register: nm_remove_source - name: Verify remove_source - assert: + ansible.builtin.assert: that: - cm_remove_source is changed - nm_remove_source is changed @@ -151,36 +151,36 @@ - nm_remove_source.current == [] - name: Remove source again (check_mode) - aci_firmware_source: *source_remove + cisco.aci.aci_firmware_source: *source_remove check_mode: true register: cm_remove_source_again - name: Remove source again (normal mode) - aci_firmware_source: *source_remove + cisco.aci.aci_firmware_source: *source_remove register: nm_remove_source_again - name: Verify remove_source_again - assert: + ansible.builtin.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: + cisco.aci.aci_firmware_source: <<: *source_query source: non_existing_source check_mode: true register: cm_query_non_source - name: Query non-existing source (normal mode) - aci_firmware_source: + cisco.aci.aci_firmware_source: <<: *source_query source: non_existing_source register: nm_query_non_source - name: Verify query_non_source - assert: + ansible.builtin.assert: that: - cm_query_non_source is not changed - nm_query_non_source is not changed @@ -202,7 +202,7 @@ register: error_on_missing_required_param - name: Verify error_on_missing_required_param - assert: + ansible.builtin.assert: that: - error_on_missing_required_param is failed - 'error_on_missing_required_param.msg == "state is present but all of the following are missing: source, url"' diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_igmp_interface_policy/tasks/main.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_igmp_interface_policy/tasks/main.yml index eac9daf6b..5e5be5de7 100644 --- a/ansible_collections/cisco/aci/tests/integration/targets/aci_igmp_interface_policy/tasks/main.yml +++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_igmp_interface_policy/tasks/main.yml @@ -4,12 +4,12 @@ # GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) - name: Test that we have an ACI APIC host, ACI username and ACI password - fail: + ansible.builtin.fail: msg: 'Please define the following variables: aci_hostname, aci_username and aci_password.' when: aci_hostname is not defined or aci_username is not defined or aci_password is not defined - name: Set vars - set_fact: + ansible.builtin.set_fact: aci_info: &aci_info host: "{{ aci_hostname }}" port: "{{ aci_port | default(omit) }}" diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_interface_blacklist/tasks/main.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_interface_blacklist/tasks/main.yml index 17e0bb67c..de24043b7 100644 --- a/ansible_collections/cisco/aci/tests/integration/targets/aci_interface_blacklist/tasks/main.yml +++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_interface_blacklist/tasks/main.yml @@ -4,12 +4,12 @@ # GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) - name: Test that we have an ACI APIC host, ACI username and ACI password - fail: + ansible.builtin.fail: msg: 'Please define the following variables: aci_hostname, aci_username and aci_password.' when: aci_hostname is not defined or aci_username is not defined or aci_password is not defined - name: Set vars - set_fact: + ansible.builtin.set_fact: aci_info: &aci_info host: "{{ aci_hostname }}" username: "{{ aci_username }}" @@ -33,14 +33,14 @@ fex_id: 123 - name: Query system information - aci_system: + cisco.aci.aci_system: <<: *aci_info id: 1 state: query register: version - name: Verify Cloud and Non-Cloud Sites in use. - include_tasks: ../../../../../../integration/targets/aci_cloud_provider/tasks/main.yml + ansible.builtin.include_tasks: ../../../../../../integration/targets/aci_cloud_provider/tasks/main.yml - name: Execute tasks only for non-cloud sites when: query_cloud.current == [] # This condition will execute only non-cloud sites @@ -53,11 +53,11 @@ register: enable_and_clear - name: set regex - set_fact: + ansible.builtin.set_fact: regexp: '(topology/pod-)(\d)(/paths-)(\d*)(/pathep-\[eth)(.*)(])' - name: Save Target DNs - set_fact: + ansible.builtin.set_fact: tdn: "{{ item.fabricRsOosPath.attributes.tDn }}" loop: "{{ enable_and_clear.current }}" register: enabled_tdn @@ -105,7 +105,7 @@ register: query_leaf_int_enabled - name: Leaf - Verify that outofsvc_interface_blacklist is not present - assert: + ansible.builtin.assert: that: - query_leaf_int_enabled.current.0.fabricOOServicePol.children is not defined @@ -118,7 +118,7 @@ register: disable_leaf_int_check - name: Leaf - Verify that outofsvc_interface_blacklist is not created after check mode - assert: + ansible.builtin.assert: that: - disable_leaf_int_check.current.0.fabricOOServicePol.children is not defined @@ -130,7 +130,7 @@ register: disable_leaf_int - name: Leaf - Verify that outofsvc_interface_blacklist is created - assert: + ansible.builtin.assert: that: - disable_leaf_int.current|length == 1 - disable_leaf_int.current.0.fabricRsOosPath.attributes.tDn == "topology/pod-1/paths-1101/pathep-[eth1/33]" @@ -145,7 +145,7 @@ register: disable_leaf_int_again - name: Leaf - Verify that outofsvc_interface_blacklist remains created after disabling again - assert: + ansible.builtin.assert: that: - disable_leaf_int_again is not changed - disable_leaf_int_again.current|length == 1 @@ -160,7 +160,7 @@ register: query_leaf_int_disabled - name: Leaf - Verify that outofsvc_interface_blacklist remains created after query - assert: + ansible.builtin.assert: that: - query_leaf_int_disabled is not changed - query_leaf_int_disabled.current|length == 1 @@ -176,7 +176,7 @@ register: enable_leaf_int_check - name: Leaf - Verify that outofsvc_interface_blacklist remains created after check mode - assert: + ansible.builtin.assert: that: - enable_leaf_int_check.current|length == 1 - enable_leaf_int_check.current.0.fabricRsOosPath.attributes.tDn == "topology/pod-1/paths-1101/pathep-[eth1/33]" @@ -190,7 +190,7 @@ register: enable_leaf_int - name: Leaf - Verify that outofsvc_interface_blacklist is deleted - assert: + ansible.builtin.assert: that: - enable_leaf_int.current.0.fabricOOServicePol.children is not defined @@ -202,7 +202,7 @@ register: enable_leaf_int_again - name: Leaf - Verify that outofsvc_interface_blacklist remains deleted after enabling again - assert: + ansible.builtin.assert: that: - enable_leaf_int_again is not changed - enable_leaf_int_again.current.0.fabricOOServicePol.children is not defined @@ -221,7 +221,7 @@ register: query_spine_int_enabled - name: Spine - Verify that outofsvc_interface_blacklist is not present - assert: + ansible.builtin.assert: that: - query_spine_int_enabled.current.0.fabricOOServicePol.children is not defined @@ -234,7 +234,7 @@ register: disable_spine_int_check - name: Spine - Verify that outofsvc_interface_blacklist is not created after check mode - assert: + ansible.builtin.assert: that: - disable_spine_int_check.current.0.fabricOOServicePol.children is not defined @@ -246,7 +246,7 @@ register: disable_spine_int - name: Spine - Verify that outofsvc_interface_blacklist is created - assert: + ansible.builtin.assert: that: - disable_spine_int.current|length == 1 - disable_spine_int.current.0.fabricRsOosPath.attributes.tDn == "topology/pod-1/paths-1201/pathep-[eth1/33]" @@ -260,7 +260,7 @@ register: disable_spine_int_again - name: Spine - Verify that outofsvc_interface_blacklist remains created after disabling again - assert: + ansible.builtin.assert: that: - disable_spine_int_again is not changed - disable_spine_int_again.current|length == 1 @@ -275,7 +275,7 @@ register: query_spine_int_disabled - name: Spine - Verify that outofsvc_interface_blacklist remains created after query - assert: + ansible.builtin.assert: that: - query_spine_int_disabled is not changed - query_spine_int_disabled.current|length == 1 @@ -291,7 +291,7 @@ register: enable_spine_int_check - name: Spine - Verify that outofsvc_interface_blacklist remains created after check mode - assert: + ansible.builtin.assert: that: - enable_spine_int_check.current|length == 1 - enable_spine_int_check.current.0.fabricRsOosPath.attributes.tDn == "topology/pod-1/paths-1201/pathep-[eth1/33]" @@ -305,7 +305,7 @@ register: enable_spine_int - name: Spine - Verify that outofsvc_interface_blacklist is deleted - assert: + ansible.builtin.assert: that: - enable_spine_int.current.0.fabricOOServicePol.children is not defined @@ -317,7 +317,7 @@ register: enable_spine_int_again - name: Spine - Verify that outofsvc_interface_blacklist remains deleted after enabling again - assert: + ansible.builtin.assert: that: - enable_spine_int_again is not changed - enable_spine_int_again.current.0.fabricOOServicePol.children is not defined @@ -336,7 +336,7 @@ register: query_fex_int_enabled - name: Fex - Verify that outofsvc_interface_blacklist is not present - assert: + ansible.builtin.assert: that: - query_fex_int_enabled.current.0.fabricOOServicePol.children is not defined @@ -349,7 +349,7 @@ register: disable_fex_int_check - name: Fex - Verify that outofsvc_interface_blacklist is not created after check mode - assert: + ansible.builtin.assert: that: - disable_fex_int_check.current.0.fabricOOServicePol.children is not defined @@ -361,7 +361,7 @@ register: disable_fex_int - name: Fex - Verify that outofsvc_interface_blacklist is created - assert: + ansible.builtin.assert: that: - disable_fex_int.current|length == 1 - disable_fex_int.current.0.fabricRsOosPath.attributes.tDn == "topology/pod-1/paths-1101/extpaths-123/pathep-[eth1/33]" @@ -375,7 +375,7 @@ register: disable_fex_int_again - name: Fex - Verify that outofsvc_interface_blacklist remains created after disabling again - assert: + ansible.builtin.assert: that: - disable_fex_int_again is not changed - disable_fex_int_again.current|length == 1 @@ -390,7 +390,7 @@ register: query_fex_int_disabled - name: Fex - Verify that outofsvc_interface_blacklist remains created after query - assert: + ansible.builtin.assert: that: - query_fex_int_disabled is not changed - query_fex_int_disabled.current|length == 1 @@ -406,7 +406,7 @@ register: enable_fex_int_check - name: Fex - Verify that outofsvc_interface_blacklist remains created after check mode - assert: + ansible.builtin.assert: that: - enable_fex_int_check.current|length == 1 - enable_fex_int_check.current.0.fabricRsOosPath.attributes.tDn == "topology/pod-1/paths-1101/extpaths-123/pathep-[eth1/33]" @@ -420,7 +420,7 @@ register: enable_fex_int - name: Fex - Verify that outofsvc_interface_blacklist is deleted - assert: + ansible.builtin.assert: that: - enable_fex_int.current.0.fabricOOServicePol.children is not defined @@ -432,7 +432,7 @@ register: enable_fex_int_again - name: Fex - Verify that outofsvc_interface_blacklist remains deleted after enabling again - assert: + ansible.builtin.assert: that: - enable_fex_int_again is not changed - enable_fex_int_again.current.0.fabricOOServicePol.children is not defined @@ -462,7 +462,7 @@ register: query_all_disabled - name: All - Verify that multiple outofsvc_interface_blacklist exist - assert: + ansible.builtin.assert: that: - query_all_disabled is not changed - query_all_disabled.current | length == 3 @@ -492,7 +492,7 @@ register: query_all_enabled - name: All - Verify that no outofsvc_interface_blacklist exist - assert: + ansible.builtin.assert: that: - query_all_enabled is not changed - query_all_enabled.current == [] diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_interface_config/tasks/main.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_interface_config/tasks/main.yml index 3e8ebcb82..b9bf19f61 100644 --- a/ansible_collections/cisco/aci/tests/integration/targets/aci_interface_config/tasks/main.yml +++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_interface_config/tasks/main.yml @@ -4,12 +4,12 @@ # GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) - name: Test that we have an ACI APIC host, ACI username and ACI password - fail: + ansible.builtin.fail: msg: 'Please define the following variables: aci_hostname, aci_username and aci_password.' when: aci_hostname is not defined or aci_username is not defined or aci_password is not defined - name: Set vars - set_fact: + ansible.builtin.set_fact: aci_info: &aci_info host: "{{ aci_hostname }}" username: "{{ aci_username }}" @@ -28,7 +28,7 @@ register: version - name: Verify Cloud and Non-Cloud Sites in use. - include_tasks: ../../../../../../integration/targets/aci_cloud_provider/tasks/main.yml + ansible.builtin.include_tasks: ../../../../../../integration/targets/aci_cloud_provider/tasks/main.yml - name: Execute tasks only for ACI v6+ and non-cloud sites when: @@ -74,7 +74,7 @@ ignore_errors: true - name: Assertions check for the invalid tasks - assert: + ansible.builtin.assert: that: - invalid_interface_absent.msg is match("state is absent but all of the following are missing{{':'}} node") - invalid_interface_details is not changed @@ -128,7 +128,7 @@ ignore_errors: true - name: Assertions check for invalid interface configuration tasks - assert: + ansible.builtin.assert: that: - invalid_node is not changed - invalid_node.msg is match("^Node ID{{':'}} .+? is invalid; it must be in the range of 101 to 4000.") @@ -169,7 +169,7 @@ register: nm_interface_501_present - name: Assertions check for an interface 501 - assert: + ansible.builtin.assert: that: - interface_501_absent.current == [] - cm_interface_501_present is changed @@ -213,7 +213,7 @@ register: nm_interface_502_present - name: Assertions check for an interface 502 - assert: + ansible.builtin.assert: that: - interface_502_absent.current == [] - cm_interface_502_present is changed @@ -257,7 +257,7 @@ register: nm_interface_505_present - name: Assertions check for an interface 505 - assert: + ansible.builtin.assert: that: - interface_505_absent.current == [] - cm_interface_505_present is changed @@ -301,7 +301,7 @@ register: nm_interface_506_present - name: Assertions check for an interface 506 - assert: + ansible.builtin.assert: that: - interface_506_absent.current == [] - cm_interface_506_present is changed @@ -345,7 +345,7 @@ register: nm_interface_507_present - name: Assertions check for an interface 507 - assert: + ansible.builtin.assert: that: - interface_507_absent.current == [] - cm_interface_507_present is changed @@ -385,7 +385,7 @@ register: nm_interface_508_present - name: Assertions check for an interface 508 - assert: + ansible.builtin.assert: that: - interface_508_absent.current == [] - cm_interface_508_present is changed @@ -431,7 +431,7 @@ register: idm_interface_509_present - name: Assertions check for an interface 509 - assert: + ansible.builtin.assert: that: - interface_509_absent.current == [] - cm_interface_509_present is changed @@ -493,7 +493,7 @@ register: idm_breakout_501_present - name: Assertions check for convert the interface 501 to breakout(100g-4x) - assert: + ansible.builtin.assert: that: - invalid_breakout_501_present is not changed - invalid_breakout_501_present.msg == "parameters are mutually exclusive{{':'}} policy_group|breakout" @@ -524,7 +524,7 @@ register: query_all_access_interfaces - name: Assertions check for query all access interfaces - assert: + ansible.builtin.assert: that: - query_all_access_interfaces is not changed - query_all_access_interfaces.current|length >= 5 @@ -537,7 +537,7 @@ register: query_all_fabric_interfaces - name: Assertions check for query all fabric interfaces - assert: + ansible.builtin.assert: that: - query_all_fabric_interfaces is not changed - query_all_fabric_interfaces.current|length >= 2 @@ -551,7 +551,7 @@ register: query_access_interface_502 - name: Assertions check for query a access interface with node id 502 - assert: + ansible.builtin.assert: that: - query_access_interface_502 is not changed - query_access_interface_502.current|length == 1 @@ -570,7 +570,7 @@ register: query_access_fabric_509 - name: Assertions check for query a fabric interface with node id 509 - assert: + ansible.builtin.assert: that: - query_access_fabric_509 is not changed - query_access_fabric_509.current|length == 1 @@ -617,7 +617,7 @@ register: rm_interface_508_present - name: Assertions check for remove Interfaces 501 to 508 - assert: + ansible.builtin.assert: that: - rm_interface_501_present is changed - rm_interface_501_present.current == [] @@ -646,7 +646,7 @@ register: nm_rm_interface_509_present - name: Assertions check for remove Interface 509 - assert: + ansible.builtin.assert: that: - cm_rm_interface_509_present is changed - cm_rm_interface_509_present.current != [] @@ -660,7 +660,7 @@ register: idm_rm_interface_509_present - name: Assertions check for remove Interface 509 with idempotency check - assert: + ansible.builtin.assert: that: - idm_rm_interface_509_present is not changed - idm_rm_interface_509_present.current == [] @@ -674,7 +674,7 @@ register: query_interface_509 - name: Assertions check for query an interface 509 after removed from the APIC - assert: + ansible.builtin.assert: that: - query_interface_509 is not changed - query_interface_509.current == [] diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_interface_description/tasks/main.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_interface_description/tasks/main.yml index ec4f0250d..474603c12 100644 --- a/ansible_collections/cisco/aci/tests/integration/targets/aci_interface_description/tasks/main.yml +++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_interface_description/tasks/main.yml @@ -4,12 +4,12 @@ # GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) - name: Test that we have an ACI APIC host, ACI username and ACI password - fail: + ansible.builtin.fail: msg: 'Please define the following variables: aci_hostname, aci_username and aci_password.' when: aci_hostname is not defined or aci_username is not defined or aci_password is not defined - name: Set vars - set_fact: + ansible.builtin.set_fact: aci_info: &aci_info host: "{{ aci_hostname }}" username: "{{ aci_username }}" @@ -20,7 +20,7 @@ output_level: debug - name: Node types - set_fact: + ansible.builtin.set_fact: test_vars_leaf: &test_vars_leaf pod_id: 1 node_id: 1101 @@ -41,7 +41,7 @@ description: testing - name: Verify Cloud and Non-Cloud Sites in use. - include_tasks: ../../../../../../integration/targets/aci_cloud_provider/tasks/main.yml + ansible.builtin.include_tasks: ../../../../../../integration/targets/aci_cloud_provider/tasks/main.yml - name: Execute tasks only for non-cloud sites when: query_cloud.current == [] # This condition will execute only non-cloud sites @@ -72,7 +72,7 @@ register: query_leaf_description - name: Leaf - Verify that no infraHPathS is present - assert: + ansible.builtin.assert: that: - query_leaf_description.current.0.infraInfra.children.0.infraHPathS.children is not defined @@ -84,7 +84,7 @@ register: set_leaf_description - name: Leaf - Verify that description is set on interface - assert: + ansible.builtin.assert: that: - set_leaf_description.current|length == 1 - set_leaf_description.current.0.infraHPathS.children.0.infraRsHPathAtt.attributes.tDn == "topology/pod-1/paths-1101/pathep-[eth1/33]" @@ -99,7 +99,7 @@ register: query_leaf_interface_1101_eth1_33 - name: Assertion check for query Leaf interface - 1101_eth1_33 - assert: + ansible.builtin.assert: that: - query_leaf_interface_1101_eth1_33.current.0.infraHPathS.children | length == 1 - query_leaf_interface_1101_eth1_33.current.0.infraHPathS.children.0.infraRsHPathAtt.attributes.rn == "rsHPathAtt-[topology/pod-1/paths-1101/pathep-[eth1/33]]" @@ -115,7 +115,7 @@ register: query_all_leaf_interfaces - name: Verify query all leaf interfaces - assert: + ansible.builtin.assert: that: - query_all_leaf_interfaces.current | length > 1 - query_all_leaf_interfaces.current.1.infraHPathS.children.0.infraRsHPathAtt.attributes.rn == "rsHPathAtt-[topology/pod-1/paths-1101/pathep-[eth1/33]]" @@ -137,7 +137,7 @@ register: query_leaf_description_again - name: Leaf - Verify that no infraHPathS is present - assert: + ansible.builtin.assert: that: - query_leaf_description_again.current.0.infraInfra.children.0.infraHPathS.children is not defined @@ -155,7 +155,7 @@ register: query_spine_description - name: Spine - Verify that no infraSHPathS is present - assert: + ansible.builtin.assert: that: - query_spine_description.current.0.infraInfra.children.0.infraSHPathS.children is not defined @@ -167,7 +167,7 @@ register: set_spine_description - name: Spine - Verify that description is set on interface - assert: + ansible.builtin.assert: that: - set_spine_description.current|length == 1 - set_spine_description.current.0.infraSHPathS.children.0.infraRsSHPathAtt.attributes.tDn == "topology/pod-1/paths-1201/pathep-[eth1/33]" @@ -181,7 +181,7 @@ register: query_spine_interface_1201_eth1_33 - name: Assertion check for query Spine interface - 1201_eth1_33 - assert: + ansible.builtin.assert: that: - query_spine_interface_1201_eth1_33.current.0.infraSHPathS.children | length == 1 - query_spine_interface_1201_eth1_33.current.0.infraSHPathS.children.0.infraRsSHPathAtt.attributes.rn == "rsSHPathAtt-[topology/pod-1/paths-1201/pathep-[eth1/33]]" @@ -197,7 +197,7 @@ register: query_all_spine_interfaces - name: Verify query all spine interfaces - assert: + ansible.builtin.assert: that: - query_all_spine_interfaces.current | length >= 1 - query_all_spine_interfaces.current.1.infraSHPathS.children.0.infraRsSHPathAtt.attributes.rn == "rsSHPathAtt-[topology/pod-1/paths-1201/pathep-[eth1/33]]" @@ -219,7 +219,7 @@ register: query_spine_description_again - name: Spine - Verify that no infraSHPathS is present - assert: + ansible.builtin.assert: that: - query_spine_description_again.current.0.infraInfra.children.0.infraSHPathS.children is not defined @@ -237,7 +237,7 @@ register: query_fex_description - name: Fex - Verify that no infraHPathS is present - assert: + ansible.builtin.assert: that: - query_fex_description.current.0.infraInfra.children.0.infraHPathS.children is not defined @@ -249,7 +249,7 @@ register: set_fex_description - name: Fex - Verify that description is set on interface - assert: + ansible.builtin.assert: that: - set_fex_description.current|length == 1 - set_fex_description.current.0.infraHPathS.children.0.infraRsHPathAtt.attributes.tDn == "topology/pod-1/paths-1101/extpaths-123/pathep-[eth1/33]" @@ -263,7 +263,7 @@ register: query_fex_interface_1201_eth1_33 - name: Assertion check for query Fex interface - 1101_eth123_1_33 - assert: + ansible.builtin.assert: that: - query_fex_interface_1201_eth1_33.current.0.infraHPathS.children | length == 1 - query_fex_interface_1201_eth1_33.current.0.infraHPathS.children.0.infraRsHPathAtt.attributes.rn == "rsHPathAtt-[topology/pod-1/paths-1101/extpaths-123/pathep-[eth1/33]]" @@ -284,6 +284,6 @@ register: query_fex_description_again - name: Fex - Verify that no infraHPathS is present - assert: + ansible.builtin.assert: that: - query_fex_description_again.current.0.infraInfra.children.0.infraHPathS.children is not defined diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_interface_policy_bfd/aliases b/ansible_collections/cisco/aci/tests/integration/targets/aci_interface_policy_bfd/aliases new file mode 100644 index 000000000..209b793f9 --- /dev/null +++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_interface_policy_bfd/aliases @@ -0,0 +1,2 @@ +# No ACI simulator yet, so not enabled +# unsupported diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_interface_policy_bfd/tasks/main.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_interface_policy_bfd/tasks/main.yml new file mode 100644 index 000000000..2d688f2c6 --- /dev/null +++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_interface_policy_bfd/tasks/main.yml @@ -0,0 +1,245 @@ +# Test code for the ACI modules +# Copyright: (c) 2023, Anvitha Jain (@anvjain) + +# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) + +- name: Test that we have an ACI APIC host, ACI username and ACI password + fail: + msg: 'Please define the following variables: aci_hostname, aci_username and aci_password.' + when: aci_hostname is not defined or aci_username is not defined or aci_password is not defined + +- name: Set vars + ansible.builtin.set_fact: + aci_info: &aci_info + host: "{{ aci_hostname }}" + username: "{{ aci_username }}" + password: "{{ aci_password }}" + validate_certs: '{{ aci_validate_certs | default(false) }}' + use_ssl: '{{ aci_use_ssl | default(true) }}' + use_proxy: '{{ aci_use_proxy | default(true) }}' + output_level: debug + +- name: Query system information + cisco.aci.aci_system: + <<: *aci_info + id: 1 + state: query + register: version + +- name: Execute tasks only for non-cloud sites + when: version.current.0.topSystem.attributes.version is version('5.2', '>=') # This condition will execute only when APIC version >= 5.2 + block: # block specifies execution of tasks within, based on conditions + + # CLEAN ENVIRONMENT + - name: Remove the ansible_tenant + cisco.aci.aci_tenant: + <<: *aci_info + tenant: ansible_tenant + state: absent + + - name: Add a new tenant + cisco.aci.aci_tenant: + <<: *aci_info + tenant: ansible_tenant + description: Ansible tenant + state: present + + # CREATE BFD Interface policy + - name: Add a new BFD Interface policy - check mode + cisco.aci.aci_interface_policy_bfd: &add_bfd_interface_pol + <<: *aci_info + tenant: ansible_tenant + name: ansible_bfd_interface_policy + description: Ansible BFD Interface Policy + state: present + check_mode: true + register: cm_add_bfd_interface_pol + + - name: Add a new BFD Interface policy - normal mode + cisco.aci.aci_interface_policy_bfd: + <<: *add_bfd_interface_pol + state: present + register: nm_add_bfd_interface_pol + + - name: Verify BFD Interface Policy creation + assert: + that: + - cm_add_bfd_interface_pol is changed + - nm_add_bfd_interface_pol is changed + - cm_add_bfd_interface_pol.previous == nm_add_bfd_interface_pol.previous == [] + - cm_add_bfd_interface_pol.proposed.bfdIfPol.attributes.dn == nm_add_bfd_interface_pol.current.0.bfdIfPol.attributes.dn == "uni/tn-ansible_tenant/bfdIfPol-ansible_bfd_interface_policy" + - cm_add_bfd_interface_pol.proposed.bfdIfPol.attributes.name == nm_add_bfd_interface_pol.current.0.bfdIfPol.attributes.name == "ansible_bfd_interface_policy" + - cm_add_bfd_interface_pol.proposed.bfdIfPol.attributes.descr == nm_add_bfd_interface_pol.current.0.bfdIfPol.attributes.descr == "Ansible BFD Interface Policy" + + - name: Add a new BFD Interface policy again - idempotency + cisco.aci.aci_interface_policy_bfd: + <<: *add_bfd_interface_pol + state: present + register: add_bfd_interface_pol_again + + - name: Verify BFD Interface Policy creation again - idempotency + assert: + that: + - add_bfd_interface_pol_again is not changed + - add_bfd_interface_pol_again.previous != [] + - add_bfd_interface_pol_again.current | length == 1 + - add_bfd_interface_pol_again.previous | length == 1 + + - name: Modify a BFD Interface policy + cisco.aci.aci_interface_policy_bfd: + <<: *add_bfd_interface_pol + admin_state: disabled + detection_multiplier: 5 + min_transmit_interval: 270 + min_receive_interval: 500 + state: present + register: update_bfd_interface_pol + + - name: Verify modifying BFD Interface Policy + assert: + that: + - update_bfd_interface_pol is changed + - update_bfd_interface_pol.previous != update_bfd_interface_pol.current + - update_bfd_interface_pol.current.0.bfdIfPol.attributes.dn == "uni/tn-ansible_tenant/bfdIfPol-ansible_bfd_interface_policy" + - update_bfd_interface_pol.current.0.bfdIfPol.attributes.name == "ansible_bfd_interface_policy" + - update_bfd_interface_pol.current.0.bfdIfPol.attributes.descr == "Ansible BFD Interface Policy" + - update_bfd_interface_pol.current.0.bfdIfPol.attributes.adminSt == "disabled" + - update_bfd_interface_pol.current.0.bfdIfPol.attributes.detectMult == "5" + - update_bfd_interface_pol.current.0.bfdIfPol.attributes.minRxIntvl == "500" + - update_bfd_interface_pol.current.0.bfdIfPol.attributes.minTxIntvl == "270" + + # Added another BFD Interface policy + - name: Add a new BFD Interface policy - normal mode + cisco.aci.aci_interface_policy_bfd: + <<: *add_bfd_interface_pol + name: ansible_bfd_interface_policy_2 + state: present + register: add_bfd_interface_pol_2 + + - name: Verify BFD Interface Policy creation + assert: + that: + - add_bfd_interface_pol_2 is changed + - add_bfd_interface_pol_2.previous == [] + - add_bfd_interface_pol_2.current.0.bfdIfPol.attributes.dn == "uni/tn-ansible_tenant/bfdIfPol-ansible_bfd_interface_policy_2" + - add_bfd_interface_pol_2.current.0.bfdIfPol.attributes.name == "ansible_bfd_interface_policy_2" + - add_bfd_interface_pol_2.current.0.bfdIfPol.attributes.descr == "Ansible BFD Interface Policy" + - add_bfd_interface_pol_2.current.0.bfdIfPol.attributes.adminSt == "enabled" + - add_bfd_interface_pol_2.current.0.bfdIfPol.attributes.detectMult == "3" + - add_bfd_interface_pol_2.current.0.bfdIfPol.attributes.minRxIntvl == "50" + - add_bfd_interface_pol_2.current.0.bfdIfPol.attributes.minTxIntvl == "50" + + - name: Query all BFD Interface policies in a specific tenant + cisco.aci.aci_interface_policy_bfd: + <<: *aci_info + tenant: ansible_tenant + state: query + register: query_all_result + + - name: Verify querying all BFD Interface Policies + assert: + that: + - query_all_result is not changed + - query_all_result.current.0.fvTenant.children | length == 2 + - query_all_result.current.0.fvTenant.children[0].bfdIfPol.attributes.name == "ansible_bfd_interface_policy_2" + - query_all_result.current.0.fvTenant.children[1].bfdIfPol.attributes.name == "ansible_bfd_interface_policy" + + - name: Query 'ansible_bfd_interface_policy' BFD Interface policies in a specific tenant + cisco.aci.aci_interface_policy_bfd: + <<: *aci_info + tenant: ansible_tenant + name: ansible_bfd_interface_policy + state: query + register: query_result + + - name: Verify querying'ansible_bfd_interface_policy BFD' Multihop Interface Policy + assert: + that: + - query_result is not changed + - query_result.current.0.bfdIfPol.attributes.dn == "uni/tn-ansible_tenant/bfdIfPol-ansible_bfd_interface_policy" + - query_result.current.0.bfdIfPol.attributes.name == "ansible_bfd_interface_policy" + + - name: Remove a BFD Interface policy - check mode + cisco.aci.aci_interface_policy_bfd: + <<: *aci_info + tenant: ansible_tenant + name: ansible_bfd_interface_policy + state: absent + check_mode: true + register: cm_remove_bfd_interface_pol + + - name: Remove a BFD Interface policy - normal mode + cisco.aci.aci_interface_policy_bfd: + <<: *aci_info + tenant: ansible_tenant + name: ansible_bfd_interface_policy + state: absent + register: nm_remove_bfd_interface_pol + + - name: Remove a BFD Interface policy again + cisco.aci.aci_interface_policy_bfd: + <<: *aci_info + tenant: ansible_tenant + name: ansible_bfd_interface_policy + state: absent + register: remove_bfd_interface_pol_again + + - name: Verify removing BFD Interface Policies + assert: + that: + - nm_remove_bfd_interface_pol is changed + - cm_remove_bfd_interface_pol is changed + - cm_remove_bfd_interface_pol.proposed == {} + - nm_remove_bfd_interface_pol.previous != [] + - remove_bfd_interface_pol_again is not changed + - nm_remove_bfd_interface_pol.current == remove_bfd_interface_pol_again.current == [] + +# Validating out of range parameters. + +# Added BFD Interface policy with out of the range detection_multiplier + - name: Add a new BFD Interface policy - out of the range detection_multiplier + cisco.aci.aci_interface_policy_bfd: + <<: *add_bfd_interface_pol + name: ansible_bfd_interface_policy_3 + detection_multiplier: 256 + state: present + ignore_errors: true + register: add_bfd_interface_pol_3 + + - name: Verify BFD Interface Policy creation + assert: + that: + - add_bfd_interface_pol_3 is not changed + - add_bfd_interface_pol_3.msg == "The \"detection_multiplier\" must be a value between 1 and 50" + +# Added BFD Interface policy with out of the range min_transmit_interval + - name: Add a new BFD Interface policy - out of the range min_transmit_interval + cisco.aci.aci_interface_policy_bfd: + <<: *add_bfd_interface_pol + name: ansible_bfd_interface_policy_3 + min_transmit_interval: 10 + state: present + ignore_errors: true + register: add_bfd_interface_pol_3 + + - name: Verify BFD Interface Policy creation + assert: + that: + - add_bfd_interface_pol_3 is not changed + - add_bfd_interface_pol_3.msg == "The \"min_transmit_interval\" must be a value between 50 and 999" + +# Added BFD Interface policy with out of the range min_receive_interval + - name: Add a new BFD Interface policy - out of the range min_receive_interval + cisco.aci.aci_interface_policy_bfd: + <<: *add_bfd_interface_pol + name: ansible_bfd_interface_policy_3 + min_receive_interval: 1000 + state: present + ignore_errors: true + register: add_bfd_interface_pol_3 + + - name: Verify BFD Interface Policy creation + assert: + that: + - add_bfd_interface_pol_3 is not changed + - add_bfd_interface_pol_3.msg == "The \"min_receive_interval\" must be a value between 50 and 999" \ No newline at end of file diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_interface_policy_bfd_multihop/aliases b/ansible_collections/cisco/aci/tests/integration/targets/aci_interface_policy_bfd_multihop/aliases new file mode 100644 index 000000000..209b793f9 --- /dev/null +++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_interface_policy_bfd_multihop/aliases @@ -0,0 +1,2 @@ +# No ACI simulator yet, so not enabled +# unsupported diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_interface_policy_bfd_multihop/tasks/main.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_interface_policy_bfd_multihop/tasks/main.yml new file mode 100644 index 000000000..8454803ec --- /dev/null +++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_interface_policy_bfd_multihop/tasks/main.yml @@ -0,0 +1,245 @@ +# Test code for the ACI modules +# Copyright: (c) 2023, Anvitha Jain (@anvjain) + +# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) + +- name: Test that we have an ACI APIC host, ACI username and ACI password + fail: + msg: 'Please define the following variables: aci_hostname, aci_username and aci_password.' + when: aci_hostname is not defined or aci_username is not defined or aci_password is not defined + +- name: Set vars + ansible.builtin.set_fact: + aci_info: &aci_info + host: "{{ aci_hostname }}" + username: "{{ aci_username }}" + password: "{{ aci_password }}" + validate_certs: '{{ aci_validate_certs | default(false) }}' + use_ssl: '{{ aci_use_ssl | default(true) }}' + use_proxy: '{{ aci_use_proxy | default(true) }}' + output_level: debug + +- name: Query system information + cisco.aci.aci_system: + <<: *aci_info + id: 1 + state: query + register: version + +- name: Execute tasks only for non-cloud sites + when: version.current.0.topSystem.attributes.version is version('5.2', '>=') # This condition will execute only when APIC version >= 5.2 + block: # block specifies execution of tasks within, based on conditions + + # CLEAN ENVIRONMENT + - name: Remove the ansible_tenant + aci_tenant: + <<: *aci_info + tenant: ansible_tenant + state: absent + + - name: Add a new tenant + aci_tenant: + <<: *aci_info + tenant: ansible_tenant + description: Ansible tenant + state: present + + # CREATE BFD Multihop Interface policy + - name: Add a new BFD Multihop Interface policy - check mode + cisco.aci.aci_interface_policy_bfd_multihop: &add_bfd_multihop_interface_pol + <<: *aci_info + tenant: ansible_tenant + name: ansible_bfd_multihop_interface_policy + description: Ansible BFD Multihop Interface Policy + state: present + check_mode: true + register: cm_add_bfd_multihop_interface_pol + + - name: Add a new BFD Multihop Interface policy - normal mode + cisco.aci.aci_interface_policy_bfd_multihop: + <<: *add_bfd_multihop_interface_pol + state: present + register: nm_add_bfd_multihop_interface_pol + + - name: Verify BFD Multihop Interface Policy creation + assert: + that: + - cm_add_bfd_multihop_interface_pol is changed + - nm_add_bfd_multihop_interface_pol is changed + - cm_add_bfd_multihop_interface_pol.previous == nm_add_bfd_multihop_interface_pol.previous == [] + - cm_add_bfd_multihop_interface_pol.proposed.bfdMhIfPol.attributes.dn == nm_add_bfd_multihop_interface_pol.current.0.bfdMhIfPol.attributes.dn == "uni/tn-ansible_tenant/bfdMhIfPol-ansible_bfd_multihop_interface_policy" + - cm_add_bfd_multihop_interface_pol.proposed.bfdMhIfPol.attributes.name == nm_add_bfd_multihop_interface_pol.current.0.bfdMhIfPol.attributes.name == "ansible_bfd_multihop_interface_policy" + - cm_add_bfd_multihop_interface_pol.proposed.bfdMhIfPol.attributes.descr == nm_add_bfd_multihop_interface_pol.current.0.bfdMhIfPol.attributes.descr == "Ansible BFD Multihop Interface Policy" + + - name: Add a new BFD Multihop Interface policy again - idempotency + cisco.aci.aci_interface_policy_bfd_multihop: + <<: *add_bfd_multihop_interface_pol + state: present + register: add_bfd_multihop_interface_pol_again + + - name: Verify BFD Multihop Interface Policy creation again - idempotency + assert: + that: + - add_bfd_multihop_interface_pol_again is not changed + - add_bfd_multihop_interface_pol_again.previous != [] + - add_bfd_multihop_interface_pol_again.current | length == 1 + - add_bfd_multihop_interface_pol_again.previous | length == 1 + + - name: Modify a BFD Multihop Interface policy + cisco.aci.aci_interface_policy_bfd_multihop: + <<: *add_bfd_multihop_interface_pol + admin_state: disabled + detection_multiplier: 5 + min_transmit_interval: 270 + min_receive_interval: 500 + state: present + register: update_bfd_multihop_interface_pol + + - name: Verify modifying BFD Multihop Interface Policy + assert: + that: + - update_bfd_multihop_interface_pol is changed + - update_bfd_multihop_interface_pol.previous != update_bfd_multihop_interface_pol.current + - update_bfd_multihop_interface_pol.current.0.bfdMhIfPol.attributes.dn == "uni/tn-ansible_tenant/bfdMhIfPol-ansible_bfd_multihop_interface_policy" + - update_bfd_multihop_interface_pol.current.0.bfdMhIfPol.attributes.name == "ansible_bfd_multihop_interface_policy" + - update_bfd_multihop_interface_pol.current.0.bfdMhIfPol.attributes.descr == "Ansible BFD Multihop Interface Policy" + - update_bfd_multihop_interface_pol.current.0.bfdMhIfPol.attributes.adminSt == "disabled" + - update_bfd_multihop_interface_pol.current.0.bfdMhIfPol.attributes.detectMult == "5" + - update_bfd_multihop_interface_pol.current.0.bfdMhIfPol.attributes.minRxIntvl == "500" + - update_bfd_multihop_interface_pol.current.0.bfdMhIfPol.attributes.minTxIntvl == "270" + + # Added another BFD Multihop Interface policy + - name: Add a new BFD Multihop Interface policy - normal mode + cisco.aci.aci_interface_policy_bfd_multihop: + <<: *add_bfd_multihop_interface_pol + name: ansible_bfd_multihop_interface_policy_2 + state: present + register: add_bfd_multihop_interface_pol_2 + + - name: Verify BFD Multihop Interface Policy creation + assert: + that: + - add_bfd_multihop_interface_pol_2 is changed + - add_bfd_multihop_interface_pol_2.previous == [] + - add_bfd_multihop_interface_pol_2.current.0.bfdMhIfPol.attributes.dn == "uni/tn-ansible_tenant/bfdMhIfPol-ansible_bfd_multihop_interface_policy_2" + - add_bfd_multihop_interface_pol_2.current.0.bfdMhIfPol.attributes.name == "ansible_bfd_multihop_interface_policy_2" + - add_bfd_multihop_interface_pol_2.current.0.bfdMhIfPol.attributes.descr == "Ansible BFD Multihop Interface Policy" + - add_bfd_multihop_interface_pol_2.current.0.bfdMhIfPol.attributes.adminSt == "enabled" + - add_bfd_multihop_interface_pol_2.current.0.bfdMhIfPol.attributes.detectMult == "3" + - add_bfd_multihop_interface_pol_2.current.0.bfdMhIfPol.attributes.minRxIntvl == "250" + - add_bfd_multihop_interface_pol_2.current.0.bfdMhIfPol.attributes.minTxIntvl == "250" + + - name: Query all BFD Multihop Interface policies in a specific tenant + cisco.aci.aci_interface_policy_bfd_multihop: + <<: *aci_info + tenant: ansible_tenant + state: query + register: query_all_result + + - name: Verify querying all BFD Multihop Interface Policies + assert: + that: + - query_all_result is not changed + - query_all_result.current.0.fvTenant.children | length == 2 + - query_all_result.current.0.fvTenant.children[0].bfdMhIfPol.attributes.name == "ansible_bfd_multihop_interface_policy_2" + - query_all_result.current.0.fvTenant.children[1].bfdMhIfPol.attributes.name == "ansible_bfd_multihop_interface_policy" + + - name: Query 'ansible_bfd_multihop_interface_policy' BFD Multihop Interface policies in a specific tenant + cisco.aci.aci_interface_policy_bfd_multihop: + <<: *aci_info + tenant: ansible_tenant + name: ansible_bfd_multihop_interface_policy + state: query + register: query_result + + - name: Verify querying'ansible_bfd_multihop_interface_policy BFD' Multihop Interface Policy + assert: + that: + - query_result is not changed + - query_result.current.0.bfdMhIfPol.attributes.dn == "uni/tn-ansible_tenant/bfdMhIfPol-ansible_bfd_multihop_interface_policy" + - query_result.current.0.bfdMhIfPol.attributes.name == "ansible_bfd_multihop_interface_policy" + + - name: Remove a BFD Multihop Interface policy - check mode + cisco.aci.aci_interface_policy_bfd_multihop: + <<: *aci_info + tenant: ansible_tenant + name: ansible_bfd_multihop_interface_policy + state: absent + check_mode: true + register: cm_remove_bfd_multihop_interface_pol + + - name: Remove a BFD Multihop Interface policy - normal mode + cisco.aci.aci_interface_policy_bfd_multihop: + <<: *aci_info + tenant: ansible_tenant + name: ansible_bfd_multihop_interface_policy + state: absent + register: nm_remove_bfd_multihop_interface_pol + + - name: Remove a BFD Multihop Interface policy again - idempotency + cisco.aci.aci_interface_policy_bfd_multihop: + <<: *aci_info + tenant: ansible_tenant + name: ansible_bfd_multihop_interface_policy + state: absent + register: remove_bfd_multihop_interface_pol_again + + - name: Verify removing BFD Multihop Interface Policies + assert: + that: + - nm_remove_bfd_multihop_interface_pol is changed + - cm_remove_bfd_multihop_interface_pol is changed + - cm_remove_bfd_multihop_interface_pol.proposed == nm_remove_bfd_multihop_interface_pol.proposed == {} + - nm_remove_bfd_multihop_interface_pol.previous != [] + - remove_bfd_multihop_interface_pol_again is not changed + - nm_remove_bfd_multihop_interface_pol.current == remove_bfd_multihop_interface_pol_again.current == [] + +# Validating out of rage parameters. + +# Added BFD Multihop Interface policy with out of the range detection_multiplier + - name: Add a new BFD Multihop Interface policy - out of the range detection_multiplier + cisco.aci.aci_interface_policy_bfd_multihop: + <<: *add_bfd_multihop_interface_pol + name: ansible_bfd_multihop_interface_policy_3 + detection_multiplier: 256 + state: present + ignore_errors: true + register: add_bfd_multihop_interface_pol_3 + + - name: Verify BFD Multihop Interface Policy creation + assert: + that: + - add_bfd_multihop_interface_pol_3 is not changed + - add_bfd_multihop_interface_pol_3.msg == "The \"detection_multiplier\" must be a value between 1 and 50" + +# Added BFD Multihop Interface policy with out of the range min_transmit_interval + - name: Add a new BFD Multihop Interface policy - out of the range min_transmit_interval + cisco.aci.aci_interface_policy_bfd_multihop: + <<: *add_bfd_multihop_interface_pol + name: ansible_bfd_multihop_interface_policy_3 + min_transmit_interval: 50 + state: present + ignore_errors: true + register: add_bfd_multihop_interface_pol_3 + + - name: Verify BFD Multihop Interface Policy creation + assert: + that: + - add_bfd_multihop_interface_pol_3 is not changed + - add_bfd_multihop_interface_pol_3.msg == "The \"min_transmit_interval\" must be a value between 250 and 999" + +# Added BFD Multihop Interface policy with out of the range min_receive_interval + - name: Add a new BFD Multihop Interface policy - out of the range min_receive_interval + cisco.aci.aci_interface_policy_bfd_multihop: + <<: *add_bfd_multihop_interface_pol + name: ansible_bfd_multihop_interface_policy_3 + min_receive_interval: 1000 + state: present + ignore_errors: true + register: add_bfd_multihop_interface_pol_3 + + - name: Verify BFD Multihop Interface Policy creation + assert: + that: + - add_bfd_multihop_interface_pol_3 is not changed + - add_bfd_multihop_interface_pol_3.msg == "The \"min_receive_interval\" must be a value between 250 and 999" \ No newline at end of file diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_interface_policy_cdp/tasks/main.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_interface_policy_cdp/tasks/main.yml index 48ac1d806..db7751943 100644 --- a/ansible_collections/cisco/aci/tests/integration/targets/aci_interface_policy_cdp/tasks/main.yml +++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_interface_policy_cdp/tasks/main.yml @@ -4,12 +4,12 @@ # GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) - name: Test that we have an ACI APIC host, ACI username and ACI password - fail: + ansible.builtin.fail: msg: 'Please define the following variables: aci_hostname, aci_username and aci_password.' when: aci_hostname is not defined or aci_username is not defined or aci_password is not defined - name: Verify Cloud and Non-Cloud Sites in use. - include_tasks: ../../../../../../integration/targets/aci_cloud_provider/tasks/main.yml + ansible.builtin.include_tasks: ../../../../../../integration/targets/aci_cloud_provider/tasks/main.yml - name: Execute tasks only for non-cloud sites when: query_cloud.current == [] # This condition will execute only non-cloud sites @@ -63,7 +63,7 @@ register: cdp_idem - name: Assert that idempotency is not changed - assert: + ansible.builtin.assert: that: - cdp_idem is not changed @@ -86,7 +86,7 @@ var: cdp_disable - name: Assert that CDP is Disabled - assert: + ansible.builtin.assert: that: - cdp_disable.current.0.cdpIfPol.attributes.adminSt == 'disabled' @@ -106,6 +106,6 @@ var: cdp_query - name: CDP Query Assertion - assert: + ansible.builtin.assert: that: - cdp_query is not changed \ No newline at end of file diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_interface_policy_eigrp/aliases b/ansible_collections/cisco/aci/tests/integration/targets/aci_interface_policy_eigrp/aliases new file mode 100644 index 000000000..209b793f9 --- /dev/null +++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_interface_policy_eigrp/aliases @@ -0,0 +1,2 @@ +# No ACI simulator yet, so not enabled +# unsupported diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_interface_policy_eigrp/tasks/main.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_interface_policy_eigrp/tasks/main.yml new file mode 100644 index 000000000..841c29ad8 --- /dev/null +++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_interface_policy_eigrp/tasks/main.yml @@ -0,0 +1,192 @@ +# Test code for the ACI modules +# Copyright: (c) 2023, Gaspard Micol (@gmicol) + +# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) + +- name: Test that we have an ACI APIC host, ACI username and ACI password + ansible.builtin.fail: + msg: 'Please define the following variables: aci_hostname, aci_username and aci_password.' + when: aci_hostname is not defined or aci_username is not defined or aci_password is not defined + +- name: Set vars + ansible.builtin.set_fact: + aci_info: &aci_info + host: "{{ aci_hostname }}" + username: "{{ aci_username }}" + password: "{{ aci_password }}" + validate_certs: '{{ aci_validate_certs | default(false) }}' + use_ssl: '{{ aci_use_ssl | default(true) }}' + use_proxy: '{{ aci_use_proxy | default(true) }}' + output_level: debug + +# CLEAN ENVIRONMENT +- name: Remove the ansible_tenant + cisco.aci.aci_tenant: &aci_tenant_absent + <<: *aci_info + tenant: ansible_tenant + state: absent + +- name: Verify Cloud and Non-Cloud Sites in use. + ansible.builtin.include_tasks: ../../../../../../integration/targets/aci_cloud_provider/tasks/main.yml + +- name: Execute tasks only for non-cloud sites + when: query_cloud.current == [] # This condition will execute only non-cloud sites + block: # block specifies execution of tasks within, based on conditions + - name: Add a new tenant + cisco.aci.aci_tenant: &aci_tenant_present + <<: *aci_info + tenant: ansible_tenant + description: Ansible tenant + state: present + + - name: Add a eigrp interface policy (check_mode) + cisco.aci.aci_interface_policy_eigrp: &aci_interface_policy_eigrp_present + <<: *aci_info + tenant: ansible_tenant + eigrp_interface: ansible_eigrp_interface_1 + description: eigrp interface policy 1 for ansible_tenant tenant + bandwidth: 100000 + control_state: [bfd, nexthop_self, passive, split_horizon] + delay: 10 + delay_unit: picoseconds + hello_interval: 10 + hold_interval: 30 + state: present + check_mode: true + register: cm_add_eigrp_interface + + - name: Add a eigrp interface policy (normal_mode) + cisco.aci.aci_interface_policy_eigrp: + <<: *aci_interface_policy_eigrp_present + register: nm_add_eigrp_interface + + - name: Add the first eigrp interface policy again - testing idempotency + cisco.aci.aci_interface_policy_eigrp: + <<: *aci_interface_policy_eigrp_present + register: nm_add_eigrp_interface_idempotency + + - name: Add a second eigrp interface policy (normal_mode) + cisco.aci.aci_interface_policy_eigrp: + <<: *aci_info + tenant: ansible_tenant + eigrp_interface: ansible_eigrp_interface_2 + description: eigrp interface policy 2 for ansible_tenant tenant + state: present + register: nm_add_eigrp_interface_2 + + - name: Add a third eigrp interface policy - bandwidth out of bounds + cisco.aci.aci_interface_policy_eigrp: + <<: *aci_info + tenant: ansible_tenant + eigrp_interface: ansible_eigrp_interface_3 + bandwidth: 2560000001 + state: present + ignore_errors: true + register: error_bw_out_of_bounds + + - name: Add a fourth eigrp interface policy - hello_interval out of bounds + cisco.aci.aci_interface_policy_eigrp: + <<: *aci_info + tenant: ansible_tenant + eigrp_interface: ansible_eigrp_interface_4 + hello_interval: 65536 + state: present + ignore_errors: true + register: error_helloIntvl_out_of_bounds + + - name: Add a fifth eigrp interface policy - hold_interval out of bounds + cisco.aci.aci_interface_policy_eigrp: + <<: *aci_info + tenant: ansible_tenant + eigrp_interface: ansible_eigrp_interface_5 + hold_interval: 65536 + state: present + ignore_errors: true + register: error_holdIntvl_out_of_bounds + + - name: Asserts for eigrp interface policys creation tasks + ansible.builtin.assert: + that: + - cm_add_eigrp_interface is changed + - cm_add_eigrp_interface.previous == [] + - cm_add_eigrp_interface.current == [] + - nm_add_eigrp_interface is changed + - nm_add_eigrp_interface.current.0.eigrpIfPol.attributes.name == "ansible_eigrp_interface_1" + - nm_add_eigrp_interface.current.0.eigrpIfPol.attributes.bw == "100000" + - nm_add_eigrp_interface.current.0.eigrpIfPol.attributes.ctrl == "bfd,nh-self,passive,split-horizon" + - nm_add_eigrp_interface.current.0.eigrpIfPol.attributes.delay == "10" + - nm_add_eigrp_interface.current.0.eigrpIfPol.attributes.delayUnit == "pico" + - nm_add_eigrp_interface.current.0.eigrpIfPol.attributes.helloIntvl == "10" + - nm_add_eigrp_interface.current.0.eigrpIfPol.attributes.holdIntvl == "30" + - nm_add_eigrp_interface_idempotency is not changed + - nm_add_eigrp_interface_2 is changed + - nm_add_eigrp_interface_2.previous == [] + - nm_add_eigrp_interface_2.current.0.eigrpIfPol.attributes.name == "ansible_eigrp_interface_2" + - nm_add_eigrp_interface_2.current.0.eigrpIfPol.attributes.bw == "0" + - nm_add_eigrp_interface_2.current.0.eigrpIfPol.attributes.ctrl == "nh-self,split-horizon" + - nm_add_eigrp_interface_2.current.0.eigrpIfPol.attributes.delay == "0" + - nm_add_eigrp_interface_2.current.0.eigrpIfPol.attributes.delayUnit == "tens-of-micro" + - nm_add_eigrp_interface_2.current.0.eigrpIfPol.attributes.helloIntvl == "5" + - nm_add_eigrp_interface_2.current.0.eigrpIfPol.attributes.holdIntvl == "15" + - error_bw_out_of_bounds.msg == "Parameter 'bandwidth' is only valid in range between 0 and 2560000000." + - error_helloIntvl_out_of_bounds.msg == "Parameter 'hello_interval' is only valid in range between 1 and 65535." + - error_holdIntvl_out_of_bounds.msg == "Parameter 'hold_interval' is only valid in range between 1 and 65535." + + - name: Query all eigrp interface policies + cisco.aci.aci_interface_policy_eigrp: + <<: *aci_info + state: query + register: query_all_eigrp_interface + + - name: Query ansible_eigrp_interface_1 + cisco.aci.aci_interface_policy_eigrp: + <<: *aci_interface_policy_eigrp_present + state: query + register: query_ansible_eigrp_interface_1 + + - name: Asserts query tasks + ansible.builtin.assert: + that: + - query_all_eigrp_interface is not changed + - query_all_eigrp_interface.current|length >= 2 + - query_ansible_eigrp_interface_1 is not changed + - query_ansible_eigrp_interface_1.current.0.eigrpIfPol.attributes.name == "ansible_eigrp_interface_1" + - query_ansible_eigrp_interface_1.current.0.eigrpIfPol.attributes.bw == "100000" + - query_ansible_eigrp_interface_1.current.0.eigrpIfPol.attributes.ctrl == "bfd,nh-self,passive,split-horizon" + - query_ansible_eigrp_interface_1.current.0.eigrpIfPol.attributes.delay == "10" + - query_ansible_eigrp_interface_1.current.0.eigrpIfPol.attributes.delayUnit == "pico" + - query_ansible_eigrp_interface_1.current.0.eigrpIfPol.attributes.helloIntvl == "10" + - query_ansible_eigrp_interface_1.current.0.eigrpIfPol.attributes.holdIntvl == "30" + + - name: Remove eigrp interface policy (check_mode) + cisco.aci.aci_interface_policy_eigrp: &eigrp_interface_absent + <<: *aci_interface_policy_eigrp_present + state: absent + check_mode: true + register: cm_remove_eigrp_interface + + - name: Remove eigrp interface policy (normal_mode) + cisco.aci.aci_interface_policy_eigrp: + <<: *eigrp_interface_absent + register: nm_remove_eigrp_interface + + - name: Remove eigrp interface policy - testing idempotency + cisco.aci.aci_interface_policy_eigrp: + <<: *eigrp_interface_absent + register: nm_remove_eigrp_interface_idempotency + + - name: Asserts deletion tasks + ansible.builtin.assert: + that: + - cm_remove_eigrp_interface is changed + - cm_remove_eigrp_interface.proposed == {} + - nm_remove_eigrp_interface is changed + - nm_remove_eigrp_interface.previous != [] + - nm_remove_eigrp_interface.method == "DELETE" + - nm_remove_eigrp_interface_idempotency is not changed + - nm_remove_eigrp_interface_idempotency.previous == [] + + - name: Remove the ansible_tenant - cleanup before ending tests + cisco.aci.aci_tenant: + <<: *aci_tenant_present + state: absent diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_interface_policy_fc/tasks/main.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_interface_policy_fc/tasks/main.yml index 5e039380e..001ce0323 100644 --- a/ansible_collections/cisco/aci/tests/integration/targets/aci_interface_policy_fc/tasks/main.yml +++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_interface_policy_fc/tasks/main.yml @@ -4,12 +4,12 @@ # GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) - name: Test that we have an ACI APIC host, ACI username and ACI password - fail: + ansible.builtin.fail: msg: 'Please define the following variables: aci_hostname, aci_username and aci_password.' when: aci_hostname is not defined or aci_username is not defined or aci_password is not defined - name: Set vars - set_fact: + ansible.builtin.set_fact: aci_info: &aci_info host: "{{ aci_hostname }}" username: "{{ aci_username }}" @@ -20,14 +20,14 @@ output_level: debug - name: Verify Cloud and Non-Cloud Sites in use. - include_tasks: ../../../../../../integration/targets/aci_cloud_provider/tasks/main.yml + ansible.builtin.include_tasks: ../../../../../../integration/targets/aci_cloud_provider/tasks/main.yml - name: Execute tasks only for non-cloud sites when: query_cloud.current == [] # This condition will execute only non-cloud sites block: # block specifies execution of tasks within, based on conditions # Clean Environment - name: Ensure first fc interface policy does not exist - aci_interface_policy_fc: &aci_interface_policy_fc_absent + cisco.aci.aci_interface_policy_fc: &aci_interface_policy_fc_absent <<: *aci_info name: anstest_policy description: test for fc interface policy @@ -40,36 +40,36 @@ state: absent - name: Ensure second fc interface policy does not exist - aci_interface_policy_fc: &aci_interface_policy_fc_2_absent + cisco.aci.aci_interface_policy_fc: &aci_interface_policy_fc_2_absent <<: *aci_info name: anstest_policy_2 state: absent - name: Create first fc interface policy (check_mode) - aci_interface_policy_fc: &aci_interface_policy_fc_present + cisco.aci.aci_interface_policy_fc: &aci_interface_policy_fc_present <<: *aci_interface_policy_fc_absent state: present check_mode: true register: cm_add_interface_policy_fc_1 - name: Create first fc interface policy (normal_mode) - aci_interface_policy_fc: + cisco.aci.aci_interface_policy_fc: <<: *aci_interface_policy_fc_present register: nm_add_interface_policy_fc_1 - name: Create first fc interface policy again - testing idempotency - aci_interface_policy_fc: + cisco.aci.aci_interface_policy_fc: <<: *aci_interface_policy_fc_present register: idempotency_add_interface_policy_fc_1 - name: Create second fc interface policy - aci_interface_policy_fc: &aci_interface_policy_fc_2_present + cisco.aci.aci_interface_policy_fc: &aci_interface_policy_fc_2_present <<: *aci_interface_policy_fc_2_absent state: present register: nm_add_interface_policy_fc_2 - name: Asserts for creation tasks - assert: + ansible.builtin.assert: that: - cm_add_interface_policy_fc_1 is changed - cm_add_interface_policy_fc_1.previous == [] @@ -94,19 +94,19 @@ - idempotency_add_interface_policy_fc_1 is not changed - name: Query all fc interface policies - aci_interface_policy_fc: + cisco.aci.aci_interface_policy_fc: <<: *aci_info state: query register: query_all_interface_policy_fc - name: Query first fc interface policy - aci_interface_policy_fc: + cisco.aci.aci_interface_policy_fc: <<: *aci_interface_policy_fc_present state: query register: query_first_interface_policy_fc - name: Asserts for query tasks - assert: + ansible.builtin.assert: that: - query_all_interface_policy_fc is not changed - query_all_interface_policy_fc.current | length >= 2 @@ -121,32 +121,32 @@ - query_first_interface_policy_fc.current.0.fcIfPol.attributes.trunkMode == "trunk-on" - name: Delete first fc interface policy (check_mode) - aci_interface_policy_fc: + cisco.aci.aci_interface_policy_fc: <<: *aci_interface_policy_fc_present state: absent check_mode: true register: cm_delete_interface_policy_fc_1 - name: Delete first fc interface policy (normal_mode) - aci_interface_policy_fc: + cisco.aci.aci_interface_policy_fc: <<: *aci_interface_policy_fc_present state: absent register: nm_delete_interface_policy_fc_1 - name: Delete first fc interface policy again - testing idempotency - aci_interface_policy_fc: + cisco.aci.aci_interface_policy_fc: <<: *aci_interface_policy_fc_present state: absent register: idempotency_delete_interface_policy_fc_1 - name: Delete second fc interface policy (normal_mode) - aci_interface_policy_fc: + cisco.aci.aci_interface_policy_fc: <<: *aci_interface_policy_fc_2_present state: absent register: nm_delete_interface_policy_fc_2 - name: Asserts for deletion tasks - assert: + ansible.builtin.assert: that: - cm_delete_interface_policy_fc_1 is changed - cm_delete_interface_policy_fc_1.proposed == {} diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_interface_policy_hsrp/aliases b/ansible_collections/cisco/aci/tests/integration/targets/aci_interface_policy_hsrp/aliases new file mode 100644 index 000000000..209b793f9 --- /dev/null +++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_interface_policy_hsrp/aliases @@ -0,0 +1,2 @@ +# No ACI simulator yet, so not enabled +# unsupported diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_interface_policy_hsrp/tasks/main.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_interface_policy_hsrp/tasks/main.yml new file mode 100644 index 000000000..4a8fca8f4 --- /dev/null +++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_interface_policy_hsrp/tasks/main.yml @@ -0,0 +1,184 @@ +# Test code for the ACI modules +# Copyright: (c) 2023, Shreyas Srish (@shrsr) +# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) + +# SET VARS +- name: Set vars + ansible.builtin.set_fact: + aci_info: &aci_info + host: '{{ aci_hostname }}' + username: '{{ aci_username }}' + password: '{{ aci_password }}' + validate_certs: '{{ aci_validate_certs | default(false) }}' + use_ssl: '{{ aci_use_ssl | default(true) }}' + use_proxy: '{{ aci_use_proxy | default(true) }}' + output_level: '{{ aci_output_level | default("debug") }}' + +# CLEAN ENVIRONMENT +- name: Remove test tenant before we kickoff + cisco.aci.aci_tenant: &tenant_absent + <<: *aci_info + tenant: ansible_test + state: absent + +- name: Verify Cloud and Non-Cloud Sites in use. + ansible.builtin.include_tasks: ../../../../../../integration/targets/aci_cloud_provider/tasks/main.yml + +- name: Execute tasks only for non-cloud sites + when: query_cloud.current == [] # This condition will execute only non-cloud sites + block: # block specifies execution of tasks within, based on conditions + # SETUP ENVIRONMENT + - name: Create tenant + cisco.aci.aci_tenant: &tenant_present + <<: *tenant_absent + state: present + + - name: Add a HSRP interface policy in check mode + cisco.aci.aci_interface_policy_hsrp: &hsrp_present + <<: *tenant_present + hsrp: hsrp1 + controls: ["bia"] + reload_delay: 2 + delay: 2 + state: present + check_mode: true + register: cm_add_hsrp + + - name: Add a HSRP interface policy in normal mode + cisco.aci.aci_interface_policy_hsrp: *hsrp_present + register: nm_add_hsrp + + - name: Verify add hsrp + ansible.builtin.assert: + that: + - cm_add_hsrp is changed + - nm_add_hsrp is changed + - cm_add_hsrp.previous == nm_add_hsrp.previous == [] + - cm_add_hsrp.proposed.hsrpIfPol.attributes.ctrl == "bia" + - cm_add_hsrp.proposed.hsrpIfPol.attributes.delay == "2" + - cm_add_hsrp.proposed.hsrpIfPol.attributes.reloadDelay == "2" + - cm_add_hsrp.proposed.hsrpIfPol.attributes.name == "hsrp1" + - nm_add_hsrp.current.0.hsrpIfPol.attributes.ctrl == "bia" + - nm_add_hsrp.current.0.hsrpIfPol.attributes.delay == "2" + - nm_add_hsrp.current.0.hsrpIfPol.attributes.reloadDelay == "2" + - nm_add_hsrp.current.0.hsrpIfPol.attributes.name == "hsrp1" + - nm_add_hsrp.current.0.hsrpIfPol.attributes.dn == "uni/tn-ansible_test/hsrpIfPol-hsrp1" + + - name: Add the HSRP interface policy again to check idempotency + cisco.aci.aci_interface_policy_hsrp: *hsrp_present + register: nm_add_hsrp_again + + - name: Verify add_hsrp again + ansible.builtin.assert: + that: + - nm_add_hsrp_again is not changed + + - name: Update hsrp interface policy + cisco.aci.aci_interface_policy_hsrp: &hsrp_update + <<: *hsrp_present + delay: 3 + register: nm_hsrp_update + + - name: Verify update hsrp + ansible.builtin.assert: + that: + - nm_hsrp_update is changed + - nm_hsrp_update.current.0.hsrpIfPol.attributes.delay == "3" + - nm_hsrp_update.current.0.hsrpIfPol.attributes.reloadDelay == "2" + - nm_hsrp_update.current.0.hsrpIfPol.attributes.name == "hsrp1" + - nm_hsrp_update.current.0.hsrpIfPol.attributes.dn == "uni/tn-ansible_test/hsrpIfPol-hsrp1" + + - name: Update hsrp interface policy to check for errors in delay + cisco.aci.aci_interface_policy_hsrp: + <<: *hsrp_update + delay: 10001 + register: nm_hsrp_error1 + ignore_errors: true + + - name: Update hsrp interface policy to check for errors in reload delay + cisco.aci.aci_interface_policy_hsrp: + <<: *hsrp_update + reload_delay: 10001 + register: nm_hsrp_error2 + ignore_errors: true + + - name: Verify errors + ansible.builtin.assert: + that: + - nm_hsrp_error1.msg == "Parameter 'delay' is only valid in range between 1 and 10000." + - nm_hsrp_error2.msg == "Parameter 'reload_delay' is only valid in range between 1 and 10000." + + - name: Add another HSRP interface policy in check mode + cisco.aci.aci_interface_policy_hsrp: &hsrp2 + <<: *tenant_present + hsrp: hsrp2 + controls: ["bfd"] + state: present + register: add_hsrp2 + + - name: Query hsrp interface policy 1 + cisco.aci.aci_interface_policy_hsrp: + <<: *hsrp_update + state: query + register: query_hsrp + + - name: Query all hsrp interface policies under the tenant + cisco.aci.aci_interface_policy_hsrp: + <<: *tenant_present + state: query + register: query_all_tenant + + - name: Query all hsrp interface policies + cisco.aci.aci_interface_policy_hsrp: + <<: *tenant_present + state: query + register: query_all + + - name: Verify query hsrp + ansible.builtin.assert: + that: + - query_hsrp is not changed + - query_all_tenant is not changed + - query_all is not changed + - query_hsrp.current.0.hsrpIfPol.attributes.delay == "3" + - query_hsrp.current.0.hsrpIfPol.attributes.reloadDelay == "2" + - query_hsrp.current.0.hsrpIfPol.attributes.name == "hsrp1" + - query_hsrp.current.0.hsrpIfPol.attributes.dn == "uni/tn-ansible_test/hsrpIfPol-hsrp1" + - query_all_tenant.current.0.fvTenant.children | length == 2 + - query_all.current.0.fvTenant.children | length >= 2 + + - name: Remove hsrp interface policy 1 in check mode + cisco.aci.aci_interface_policy_hsrp: + <<: *hsrp_update + state: absent + check_mode: true + register: cm_remove_hsrp + + - name: Remove hsrp interface policy 1 + cisco.aci.aci_interface_policy_hsrp: + <<: *hsrp_update + state: absent + register: remove_hsrp + + - name: Remove hsrp interface policy 2 + cisco.aci.aci_interface_policy_hsrp: + <<: *hsrp2 + state: absent + register: remove_hsrp2 + + - name: Remove hsrp interface policy again + cisco.aci.aci_interface_policy_hsrp: + <<: *hsrp2 + state: absent + register: remove_hsrp2_again + + - name: Verify remove hsrp + ansible.builtin.assert: + that: + - cm_remove_hsrp is changed + - cm_remove_hsrp.proposed == {} + - remove_hsrp is changed + - remove_hsrp2 is changed + - remove_hsrp.current == [] + - remove_hsrp2.current == [] + - remove_hsrp2_again is not changed diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_interface_policy_l2/tasks/main.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_interface_policy_l2/tasks/main.yml index f52b74fdb..ccfb3a641 100644 --- a/ansible_collections/cisco/aci/tests/integration/targets/aci_interface_policy_l2/tasks/main.yml +++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_interface_policy_l2/tasks/main.yml @@ -4,12 +4,12 @@ # GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) - name: Test that we have an ACI APIC host, ACI username and ACI password - fail: + ansible.builtin.fail: msg: 'Please define the following variables: aci_hostname, aci_username and aci_password.' when: aci_hostname is not defined or aci_username is not defined or aci_password is not defined - name: Set vars - set_fact: + ansible.builtin.set_fact: aci_info: &aci_info host: "{{ aci_hostname }}" username: "{{ aci_username }}" @@ -20,14 +20,14 @@ output_level: debug - name: Verify Cloud and Non-Cloud Sites in use. - include_tasks: ../../../../../../integration/targets/aci_cloud_provider/tasks/main.yml + ansible.builtin.include_tasks: ../../../../../../integration/targets/aci_cloud_provider/tasks/main.yml - name: Execute tasks only for non-cloud sites when: query_cloud.current == [] # This condition will execute only non-cloud sites block: # block specifies execution of tasks within, based on conditions # Clean Environment - name: Ensure first l2 interface policy does not exist - aci_interface_policy_l2: &aci_interface_policy_l2_absent + cisco.aci.aci_interface_policy_l2: &aci_interface_policy_l2_absent <<: *aci_info name: anstest_policy description: test for l2 interface policy @@ -37,36 +37,36 @@ state: absent - name: Ensure second l2 interface policy does not exist - aci_interface_policy_l2: &aci_interface_policy_l2_2_absent + cisco.aci.aci_interface_policy_l2: &aci_interface_policy_l2_2_absent <<: *aci_info name: anstest_policy_2 state: absent - name: Create first l2 interface policy (check_mode) - aci_interface_policy_l2: &aci_interface_policy_l2_present + cisco.aci.aci_interface_policy_l2: &aci_interface_policy_l2_present <<: *aci_interface_policy_l2_absent state: present check_mode: true register: cm_add_interface_policy_l2_1 - name: Create first l2 interface policy (normal_mode) - aci_interface_policy_l2: + cisco.aci.aci_interface_policy_l2: <<: *aci_interface_policy_l2_present register: nm_add_interface_policy_l2_1 - name: Create first l2 interface policy again - testing idempotency - aci_interface_policy_l2: + cisco.aci.aci_interface_policy_l2: <<: *aci_interface_policy_l2_present register: idempotency_add_interface_policy_l2_1 - name: Create second l2 interface policy - aci_interface_policy_l2: &aci_interface_policy_l2_2_present + cisco.aci.aci_interface_policy_l2: &aci_interface_policy_l2_2_present <<: *aci_interface_policy_l2_2_absent state: present register: nm_add_interface_policy_l2_2 - name: Asserts for creation tasks - assert: + ansible.builtin.assert: that: - cm_add_interface_policy_l2_1 is changed - cm_add_interface_policy_l2_1.previous == [] @@ -84,19 +84,19 @@ - nm_add_interface_policy_l2_2.current.0.l2IfPol.attributes.vepa == "disabled" - name: Query all l2 interface policies - aci_interface_policy_l2: + cisco.aci.aci_interface_policy_l2: <<: *aci_info state: query register: query_all_interface_policy_l2 - name: Query first l2 interface policy - aci_interface_policy_l2: + cisco.aci.aci_interface_policy_l2: <<: *aci_interface_policy_l2_present state: query register: query_first_interface_policy_l2 - name: Asserts for query tasks - assert: + ansible.builtin.assert: that: - query_all_interface_policy_l2 is not changed - query_all_interface_policy_l2.current | length >= 2 @@ -108,32 +108,32 @@ - query_first_interface_policy_l2.current.0.l2IfPol.attributes.vepa == "enabled" - name: Delete first l2 interface policy (check_mode) - aci_interface_policy_l2: + cisco.aci.aci_interface_policy_l2: <<: *aci_interface_policy_l2_present state: absent check_mode: true register: cm_delete_interface_policy_l2_1 - name: Delete first l2 interface policy (normal_mode) - aci_interface_policy_l2: + cisco.aci.aci_interface_policy_l2: <<: *aci_interface_policy_l2_present state: absent register: nm_delete_interface_policy_l2_1 - name: Delete first l2 interface policy again - testing idempotency - aci_interface_policy_l2: + cisco.aci.aci_interface_policy_l2: <<: *aci_interface_policy_l2_present state: absent register: idempotency_delete_interface_policy_l2_1 - name: Delete second l2 interface policy (normal_mode) - aci_interface_policy_l2: + cisco.aci.aci_interface_policy_l2: <<: *aci_interface_policy_l2_2_present state: absent register: nm_delete_interface_policy_l2_2 - name: Asserts for deletion tasks - assert: + ansible.builtin.assert: that: - cm_delete_interface_policy_l2_1 is changed - cm_delete_interface_policy_l2_1.proposed == {} diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_interface_policy_leaf_breakout_port_group/tasks/main.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_interface_policy_leaf_breakout_port_group/tasks/main.yml index b84f64b9a..25c8a1aec 100644 --- a/ansible_collections/cisco/aci/tests/integration/targets/aci_interface_policy_leaf_breakout_port_group/tasks/main.yml +++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_interface_policy_leaf_breakout_port_group/tasks/main.yml @@ -4,13 +4,13 @@ # GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) - name: Test that we have an ACI APIC host, ACI username and ACI password - fail: + ansible.builtin.fail: msg: 'Please define the following variables: aci_hostname, aci_username and aci_password.' when: aci_hostname is not defined or aci_username is not defined or aci_password is not defined # CLEAN ENVIRONMENT - name: Set vars - set_fact: + ansible.builtin.set_fact: aci_info: &aci_info host: '{{ aci_hostname }}' username: '{{ aci_username }}' @@ -21,7 +21,7 @@ output_level: '{{ aci_output_level | default("info") }}' - name: Verify Cloud and Non-Cloud Sites in use. - include_tasks: ../../../../../../integration/targets/aci_cloud_provider/tasks/main.yml + ansible.builtin.include_tasks: ../../../../../../integration/targets/aci_cloud_provider/tasks/main.yml - name: Execute tasks only for non-cloud sites when: query_cloud.current == [] # This condition will execute only non-cloud sites @@ -55,7 +55,7 @@ register: nm_create_brkout_port - name: Verify cm_create_brkout_port and nm_create_brkout_port - assert: + ansible.builtin.assert: that: - cm_create_brkout_port is changed - cm_create_brkout_port.previous == [] @@ -81,7 +81,7 @@ register: nm_create_brkout_port_again - name: Verify nm_create_brkout_port_again - assert: + ansible.builtin.assert: that: - nm_create_brkout_port_again is not changed @@ -93,7 +93,7 @@ register: nm_create_another_brkout_port - name: Verify nm_create_another_brkout_port - assert: + ansible.builtin.assert: that: - nm_create_another_brkout_port is changed - nm_create_another_brkout_port.previous == [] @@ -110,7 +110,7 @@ register: query_all - name: Verify query_all - assert: + ansible.builtin.assert: that: query_all.current | length >= 2 @@ -122,7 +122,7 @@ register: query_one - name: Verify query_one - assert: + ansible.builtin.assert: that: - query_one is not changed - query_one.current.0.infraBrkoutPortGrp.attributes.name == "ansible_breakout_port" @@ -137,7 +137,7 @@ register: change_ansible_breakout_port - name: Verify change_ansible_breakout_port - assert: + ansible.builtin.assert: that: - change_ansible_breakout_port is changed - change_ansible_breakout_port.current.0.infraBrkoutPortGrp.attributes.brkoutMap == "none" @@ -151,7 +151,7 @@ register: rm_breakout_port - name: Verify rm_breakout_port - assert: + ansible.builtin.assert: that: - rm_breakout_port is changed - rm_breakout_port.current == [] @@ -164,6 +164,6 @@ register: query_removed_breakout_port - name: Verify query_removed_breakout_port - assert: + ansible.builtin.assert: that: - query_removed_breakout_port.current == [] \ No newline at end of file diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_interface_policy_leaf_fc_policy_group/tasks/main.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_interface_policy_leaf_fc_policy_group/tasks/main.yml index 5a758bb3d..ed646ec01 100644 --- a/ansible_collections/cisco/aci/tests/integration/targets/aci_interface_policy_leaf_fc_policy_group/tasks/main.yml +++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_interface_policy_leaf_fc_policy_group/tasks/main.yml @@ -4,12 +4,12 @@ # GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) - name: Test that we have an ACI APIC host, ACI username and ACI password - fail: + ansible.builtin.fail: msg: 'Please define the following variables: aci_hostname, aci_username and aci_password.' when: aci_hostname is not defined or aci_username is not defined or aci_password is not defined - name: Set vars - set_fact: + ansible.builtin.set_fact: aci_info: &aci_info host: "{{ aci_hostname }}" username: "{{ aci_username }}" @@ -20,7 +20,7 @@ output_level: debug - name: Verify Cloud and Non-Cloud Sites in use. - include_tasks: ../../../../../../integration/targets/aci_cloud_provider/tasks/main.yml + ansible.builtin.include_tasks: ../../../../../../integration/targets/aci_cloud_provider/tasks/main.yml - name: Execute tasks only for non-cloud sites when: query_cloud.current == [] # This condition will execute only non-cloud sites @@ -71,7 +71,7 @@ register: intf_policy_leaf_access_fc_port_polgrp_update - name: Verify present assertions for FC Port Policy Group - assert: + ansible.builtin.assert: that: - intf_policy_leaf_access_fc_port_polgrp_check_mode_present is changed - intf_policy_leaf_access_fc_port_polgrp_present is changed @@ -116,7 +116,7 @@ register: intf_policy_leaf_access_fc_pc_polgrp_update - name: Verify present assertions for FC PC Policy Group - assert: + ansible.builtin.assert: that: - intf_policy_leaf_access_fc_pc_polgrp_check_mode_present is changed - intf_policy_leaf_access_fc_pc_polgrp_present is changed @@ -149,7 +149,7 @@ register: query_leaf_access_fc_port_policy_group - name: Verify query assertions for Leaf Access FC Port Policy Group - assert: + ansible.builtin.assert: that: - query_leaf_access_fc_port_policy_group is not changed - query_leaf_access_fc_port_policy_group.current[0] | length >= 1 @@ -172,7 +172,7 @@ register: query_leaf_access_fc_pc_policy_group - name: Verify query assertions for Leaf Access FC PC Policy Group - assert: + ansible.builtin.assert: that: - query_leaf_access_fc_pc_policy_group is not changed - query_leaf_access_fc_pc_policy_group.current[0] | length >= 1 @@ -196,7 +196,7 @@ register: intf_policy_leaf_access_fc_port_polgrp_absent_idempotent - name: Verify absent assertions for FC Port Policy Group - assert: + ansible.builtin.assert: that: - intf_policy_leaf_access_fc_port_polgrp_check_mode_absent is changed - intf_policy_leaf_access_fc_port_polgrp_check_mode_absent.previous != [] @@ -222,7 +222,7 @@ register: intf_policy_leaf_access_fc_pc_polgrp_absent_idempotent - name: Verify absent assertions for FC PC policy group - assert: + ansible.builtin.assert: that: - intf_policy_leaf_access_fc_pc_polgrp_check_mode_absent is changed - intf_policy_leaf_access_fc_pc_polgrp_check_mode_absent.previous != [] diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_interface_policy_leaf_policy_group/tasks/main.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_interface_policy_leaf_policy_group/tasks/main.yml index 3f6e25505..730710869 100644 --- a/ansible_collections/cisco/aci/tests/integration/targets/aci_interface_policy_leaf_policy_group/tasks/main.yml +++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_interface_policy_leaf_policy_group/tasks/main.yml @@ -5,13 +5,13 @@ # GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) - name: Test that we have an ACI APIC host, ACI username and ACI password - fail: + ansible.builtin.fail: msg: 'Please define the following variables: aci_hostname, aci_username and aci_password.' when: aci_hostname is not defined or aci_username is not defined or aci_password is not defined # GET Credentials from the inventory - name: Set vars - set_fact: + ansible.builtin.set_fact: aci_info: &aci_info host: "{{ aci_hostname }}" username: "{{ aci_username }}" @@ -29,7 +29,7 @@ register: version - name: Verify Cloud and Non-Cloud Sites in use. - include_tasks: ../../../../../../integration/targets/aci_cloud_provider/tasks/main.yml + ansible.builtin.include_tasks: ../../../../../../integration/targets/aci_cloud_provider/tasks/main.yml - name: Execute tasks only for non-cloud sites when: query_cloud.current == [] # This condition will execute only non-cloud sites @@ -86,7 +86,7 @@ # TODO: also test for errors - name: present assertions for interface policy leaf policy group (PC) - assert: + ansible.builtin.assert: that: - intf_policy_leaf_polgrp_check_mode_present is changed - intf_policy_leaf_polgrp_present is changed @@ -110,7 +110,7 @@ register: binding_query - name: Query assertions for interface policy leaf policy group (PC) - assert: + ansible.builtin.assert: that: - binding_query is not changed - binding_query.current | length >= 1 @@ -142,7 +142,7 @@ register: intf_policy_leaf_polgrp_absent_missing_param - name: absent assertions for interface policy leaf policy group (PC) - assert: + ansible.builtin.assert: that: - intf_policy_leaf_polgrp_check_mode_absent is changed - intf_policy_leaf_polgrp_check_mode_absent.previous != [] @@ -191,7 +191,7 @@ # TODO: also test for errors - name: present assertions for interface policy leaf policy group (VPC) - assert: + ansible.builtin.assert: that: - intf_policy_leaf_polgrp_check_mode_present is changed - intf_policy_leaf_polgrp_present is changed @@ -215,7 +215,7 @@ register: binding_query - name: Query assertions for interface policy leaf policy group (VPC) - assert: + ansible.builtin.assert: that: - binding_query is not changed - binding_query.current | length >= 1 @@ -235,7 +235,7 @@ register: binding_query_node_all - name: Query assertions for interface policy leaf policy group (VPC) - assert: + ansible.builtin.assert: that: - binding_query_node_all is not changed - binding_query_node_all.current | length >= 1 @@ -267,7 +267,7 @@ register: intf_policy_leaf_polgrp_absent_missing_param - name: absent assertions for interface policy leaf policy group (VPC) - assert: + ansible.builtin.assert: that: - intf_policy_leaf_polgrp_check_mode_absent is changed - intf_policy_leaf_polgrp_check_mode_absent.previous != [] @@ -286,7 +286,7 @@ register: intf_policy_leaf_polgrp_pa_policy_error - name: VPC error assertions (adding invalid parameters) - assert: + ansible.builtin.assert: that: - intf_policy_leaf_polgrp_pa_policy_error.msg == 'port_authentication is not a valid parameter for link/node (Port Channel, Virtual Port Channel), if used assign null to it (port_authentication{{":"}} null).' @@ -343,7 +343,7 @@ # TODO: also test for errors - name: present assertions for interface policy leaf policy group (Leaf Access Port) - assert: + ansible.builtin.assert: that: - intf_policy_leaf_polgrp_check_mode_present is changed - intf_policy_leaf_polgrp_present is changed @@ -368,12 +368,12 @@ register: binding_query - name: Query assertions interface policy leaf policy group (Leaf Access Port) - assert: + ansible.builtin.assert: that: - binding_query is not changed - binding_query.current | length >= 1 - '"/api/mo/uni/infra/funcprof/accportgrp-policygroupname_leaf.json" in binding_query.url' - - binding_query.current.0.infraAccPortGrp.children.14.infraRsAttEntP.attributes.tDn == "uni/infra/attentp-test_aep" + - binding_query.current.0.infraAccPortGrp.children.10.infraRsAttEntP.attributes.tDn == "uni/infra/attentp-test_aep" - name: Remove interface policy leaf policy group (Leaf Access Port) - check mode cisco.aci.aci_interface_policy_leaf_policy_group: @@ -400,7 +400,7 @@ register: intf_policy_leaf_polgrp_absent_missing_param - name: absent assertions for interface policy leaf policy group (Leaf Access Port) - assert: + ansible.builtin.assert: that: - intf_policy_leaf_polgrp_check_mode_absent is changed - intf_policy_leaf_polgrp_check_mode_absent.previous != [] @@ -430,7 +430,7 @@ register: intf_policy_leaf_policy_group_link_present_2 - name: present assertions (PC) for APIC version > 5 - assert: + ansible.builtin.assert: that: - intf_policy_leaf_policy_group_link_present_2 is changed - intf_policy_leaf_policy_group_link_present_2.previous != [] @@ -446,7 +446,7 @@ register: intf_policy_leaf_polgrp_present_2 - name: present assertions (Leaf Access Port) for APIC version > 5 - assert: + ansible.builtin.assert: that: - intf_policy_leaf_polgrp_present_2 is changed - intf_policy_leaf_polgrp_present_2.previous == [] @@ -474,7 +474,7 @@ register: intf_policy_leaf_policy_group_node_present_2 - name: present assertions (VPC) for APIC version > 6 - assert: + ansible.builtin.assert: that: - intf_policy_leaf_policy_group_node_present_2 is changed - intf_policy_leaf_policy_group_node_present_2.previous == [] @@ -497,7 +497,7 @@ register: intf_policy_leaf_polgrp_present_3 - name: present assertions (Leaf Access Port) for APIC version >= 6.0.2 - assert: + ansible.builtin.assert: that: - intf_policy_leaf_polgrp_present_3 is changed - intf_policy_leaf_polgrp_present_3.previous != [] @@ -530,7 +530,7 @@ register: intf_policy_leaf_polgrp_all_policy_present - name: present assertions (Leaf Access Port) for all the policies. - assert: + ansible.builtin.assert: that: - intf_policy_leaf_polgrp_all_policy_present is changed - intf_policy_leaf_polgrp_all_policy_present.previous != [] diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_interface_policy_leaf_profile/tasks/main.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_interface_policy_leaf_profile/tasks/main.yml index 51d553c54..08bbd31b6 100644 --- a/ansible_collections/cisco/aci/tests/integration/targets/aci_interface_policy_leaf_profile/tasks/main.yml +++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_interface_policy_leaf_profile/tasks/main.yml @@ -5,12 +5,12 @@ # GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) - name: Test that we have an ACI APIC host, ACI username and ACI password - fail: + ansible.builtin.fail: msg: 'Please define the following variables: aci_hostname, aci_username and aci_password.' when: aci_hostname is not defined or aci_username is not defined or aci_password is not defined - name: Verify Cloud and Non-Cloud Sites in use. - include_tasks: ../../../../../../integration/targets/aci_cloud_provider/tasks/main.yml + ansible.builtin.include_tasks: ../../../../../../integration/targets/aci_cloud_provider/tasks/main.yml - name: Execute tasks only for non-cloud sites when: query_cloud.current == [] # This condition will execute only non-cloud sites @@ -70,7 +70,7 @@ register: nm_add_leaf_interface_profile_fex - name: Verify add_leaf_interface_profile - assert: + ansible.builtin.assert: that: - cm_add_leaf_interface_profile is changed - nm_add_leaf_interface_profile is changed @@ -115,7 +115,7 @@ register: nm_add_leaf_interface_profile_descr_fex - name: Verify add_leaf_interface_profile_descr - assert: + ansible.builtin.assert: that: - cm_add_leaf_interface_profile_descr is changed - nm_add_leaf_interface_profile_descr is changed @@ -141,7 +141,7 @@ register: nm_add_leaf_interface_profile_again_no_descr_fex - name: Verify add_leaf_interface_profile_again_no_descr - assert: + ansible.builtin.assert: that: - cm_add_leaf_interface_profile_again_no_descr is not changed - nm_add_leaf_interface_profile_again_no_descr is not changed @@ -171,7 +171,7 @@ type: fex - name: Verify query_all_leaf_interface_profiles - assert: + ansible.builtin.assert: that: - cm_query_all_leaf_interface_profiles is not changed - nm_query_all_leaf_interface_profiles is not changed @@ -200,7 +200,7 @@ register: nm_query_leaf_interface_profile_fex - name: Verify query_leaf_interface_profile - assert: + ansible.builtin.assert: that: - cm_query_leaf_interface_profile is not changed - nm_query_leaf_interface_profile is not changed @@ -234,7 +234,7 @@ register: nm_remove_leaf_interface_profile_again_fex - name: Verify remove_leaf_interface_profile - assert: + ansible.builtin.assert: that: - cm_remove_leaf_interface_profile is changed - nm_remove_leaf_interface_profile is changed @@ -265,7 +265,7 @@ # TODO: Implement more tests - name: Verify query_non_leaf_interface_profile - assert: + ansible.builtin.assert: that: - cm_query_non_leaf_interface_profile is not changed - nm_query_non_leaf_interface_profile is not changed diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_interface_policy_leaf_profile_fex_policy_group/tasks/main.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_interface_policy_leaf_profile_fex_policy_group/tasks/main.yml index 41853af11..2fc177909 100644 --- a/ansible_collections/cisco/aci/tests/integration/targets/aci_interface_policy_leaf_profile_fex_policy_group/tasks/main.yml +++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_interface_policy_leaf_profile_fex_policy_group/tasks/main.yml @@ -4,13 +4,13 @@ # GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) - name: Test that we have an ACI APIC host, ACI username and ACI password - fail: + ansible.builtin.fail: msg: "Please define the following variables: aci_hostname, aci_username and aci_password." when: aci_hostname is not defined or aci_username is not defined or aci_password is not defined # SET VARS - name: Set vars - set_fact: + ansible.builtin.set_fact: aci_info: &aci_info host: "{{ aci_hostname }}" username: "{{ aci_username }}" @@ -21,7 +21,7 @@ output_level: '{{ aci_output_level | default("info") }}' - name: Verify Cloud and Non-Cloud Sites in use. - include_tasks: ../../../../../../integration/targets/aci_cloud_provider/tasks/main.yml + ansible.builtin.include_tasks: ../../../../../../integration/targets/aci_cloud_provider/tasks/main.yml - name: Execute tasks only for non-cloud sites when: query_cloud.current == [] # This condition will execute only non-cloud sites @@ -50,7 +50,7 @@ register: cm_fex_policy_group_present - name: Assertions check for add Fex Policy Group to anstest_fex_profile - Interface Policy Fex profile with check mode - assert: + ansible.builtin.assert: that: - cm_fex_policy_group_present is changed - cm_fex_policy_group_present.current | length == 0 @@ -65,7 +65,7 @@ register: nm_fex_policy_group_present - name: Assertions check for add Fex Policy Group to anstest_fex_profile - Interface Policy Fex profile with normal mode - assert: + ansible.builtin.assert: that: - nm_fex_policy_group_present is changed - nm_fex_policy_group_present.current | length == 1 @@ -80,7 +80,7 @@ register: idempotency_fex_policy_group_present - name: Idempotency assertions check for add Fex Policy Group to anstest_fex_profile - Interface Policy Fex profile with normal mode - assert: + ansible.builtin.assert: that: - idempotency_fex_policy_group_present is not changed - idempotency_fex_policy_group_present.current | length == 1 @@ -104,7 +104,7 @@ register: multiple_fex_policy_group_present - name: Assertions check for add multiple Fex Policy Group to anstest_fex_profile - Interface Policy Fex profile with normal mode - assert: + ansible.builtin.assert: that: - multiple_fex_policy_group_present is changed - multiple_fex_policy_group_present.results.0 is changed @@ -125,7 +125,7 @@ register: temp_anstest_fex_profile_absent - name: Assertions check for remove temp_anstest_fex_profile - Interface Policy Fex profile - assert: + ansible.builtin.assert: that: - temp_anstest_fex_profile_absent.current | length == 0 @@ -136,7 +136,7 @@ register: temp_anstest_fex_profile_present - name: Assertions check for add temp_anstest_fex_profile - Interface Policy Fex profile - assert: + ansible.builtin.assert: that: - temp_anstest_fex_profile_present is changed - temp_anstest_fex_profile_present.current | length == 1 @@ -151,7 +151,7 @@ register: temp_anstest_fex_policy_group_present - name: Assertions check for add Fex Policy Group to temp_anstest_fex_profile - Interface Policy Fex profile - assert: + ansible.builtin.assert: that: - temp_anstest_fex_policy_group_present is changed - temp_anstest_fex_policy_group_present.current | length == 1 @@ -168,7 +168,7 @@ register: query_res_fex_policy_group_with_profile - name: Assertions check for query anstest_fex_policy_group - fex policy group with fex_profile - assert: + ansible.builtin.assert: that: - query_res_fex_policy_group_with_profile is not changed - query_res_fex_policy_group_with_profile.current | length == 1 @@ -183,7 +183,7 @@ register: query_all_policy_groups_under_fex_profile - name: Assertions check for query all fex policy group under anstest_fex_profile - assert: + ansible.builtin.assert: that: - query_all_policy_groups_under_fex_profile is not changed - query_all_policy_groups_under_fex_profile.current.0.infraFexP.children | length == 3 @@ -196,7 +196,7 @@ register: query_res_anstest_fex_policy_group - name: Assertions check for query all anstest_fex_policy_group - fex policy groups - assert: + ansible.builtin.assert: that: - query_res_anstest_fex_policy_group is not changed - query_res_anstest_fex_policy_group.current | length >= 2 @@ -210,7 +210,7 @@ register: all_fex_policy_groups - name: Assertions check for query all - fex policy groups - assert: + ansible.builtin.assert: that: - all_fex_policy_groups is not changed - all_fex_policy_groups.current | length >= 4 @@ -226,7 +226,7 @@ register: cm_anstest_fex_policy_group_absent - name: Assertions check for remove anstest_fex_policy_group - Fex Policy Group from anstest_fex_profile with check mode - assert: + ansible.builtin.assert: that: - cm_anstest_fex_policy_group_absent is changed - cm_anstest_fex_policy_group_absent.current | length == 1 @@ -243,7 +243,7 @@ register: nm_anstest_fex_policy_group_absent - name: Assertions check for remove anstest_fex_policy_group - Fex Policy Group from anstest_fex_profile with normal mode - assert: + ansible.builtin.assert: that: - nm_anstest_fex_policy_group_absent is changed - nm_anstest_fex_policy_group_absent.current | length == 0 @@ -258,7 +258,7 @@ register: idempotency_anstest_fex_policy_group_absent - name: Idempotency assertions check for remove anstest_fex_policy_group - Fex Policy Group from anstest_fex_profile with normal mode - assert: + ansible.builtin.assert: that: - idempotency_anstest_fex_policy_group_absent is not changed - idempotency_anstest_fex_policy_group_absent.current | length == 0 @@ -271,7 +271,7 @@ register: temp_anstest_fex_profile_absent - name: Assertions check for remove temp_anstest_fex_profile Fex Profile - assert: + ansible.builtin.assert: that: - temp_anstest_fex_profile_absent is changed - temp_anstest_fex_profile_absent.current | length == 0 @@ -286,7 +286,7 @@ register: fex_profile_present_absent - name: Assertions check for remove anstest_fex_profile Fex Profile - assert: + ansible.builtin.assert: that: - fex_profile_present_absent is changed - fex_profile_present_absent.current | length == 0 diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_interface_policy_link_level/tasks/main.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_interface_policy_link_level/tasks/main.yml index a3ee0c4b8..c5a6843e5 100644 --- a/ansible_collections/cisco/aci/tests/integration/targets/aci_interface_policy_link_level/tasks/main.yml +++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_interface_policy_link_level/tasks/main.yml @@ -5,19 +5,32 @@ # 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: + ansible.builtin.fail: msg: 'Please define the following variables: aci_hostname, aci_username and aci_password.' when: aci_hostname is not defined or aci_username is not defined or aci_password is not defined - name: Verify Cloud and Non-Cloud Sites in use. - include_tasks: ../../../../../../integration/targets/aci_cloud_provider/tasks/main.yml + ansible.builtin.include_tasks: ../../../../../../integration/targets/aci_cloud_provider/tasks/main.yml - name: Execute tasks only for non-cloud sites when: query_cloud.current == [] # This condition will execute only non-cloud sites block: # block specifies execution of tasks within, based on conditions + # SET ACI_INFO VARS FOR SYSTEM LOGIN WITHIN TASKS + - name: Set vars for system login + ansible.builtin.set_fact: + aci_info: &aci_info + host: "{{ aci_hostname }}" + port: "{{ aci_port | default(omit) }}" + username: "{{ aci_username }}" + password: "{{ aci_password }}" + validate_certs: '{{ aci_validate_certs | default(false) }}' + use_ssl: '{{ aci_use_ssl | default(true) }}' + use_proxy: '{{ aci_use_proxy | default(true) }}' + output_level: '{{ aci_output_level | default("info") }}' + # CLEAN ENVIRONMENT - name: Remove Link Level Policy - aci_interface_policy_link_level: &interface_policy_link_level_absent + cisco.aci.aci_interface_policy_link_level: &interface_policy_link_level_absent host: '{{ aci_hostname }}' username: '{{ aci_username }}' password: '{{ aci_password }}' @@ -30,7 +43,7 @@ # ADD LINK LEVEL POLICY - name: Add Link Level Policy (check mode) - aci_interface_policy_link_level: &interface_policy_link_level_present + cisco.aci.aci_interface_policy_link_level: &interface_policy_link_level_present host: '{{ aci_hostname }}' username: '{{ aci_username }}' password: '{{ aci_password }}' @@ -44,11 +57,11 @@ register: cm_add_policy - name: Add Link Level Policy (normal mode) - aci_interface_policy_link_level: *interface_policy_link_level_present + cisco.aci.aci_interface_policy_link_level: *interface_policy_link_level_present register: nm_add_policy - name: Verify Add Link Level Policy - assert: + ansible.builtin.assert: that: - cm_add_policy is changed - nm_add_policy is changed @@ -59,16 +72,16 @@ - 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 + cisco.aci.aci_interface_policy_link_level: *interface_policy_link_level_present check_mode: true register: cm_add_policy_again - name: Add Link Level Policy again (normal mode) - aci_interface_policy_link_level: *interface_policy_link_level_present + cisco.aci.aci_interface_policy_link_level: *interface_policy_link_level_present register: nm_add_policy_again - name: Verify Add Link Level Policy again - assert: + ansible.builtin.assert: that: - cm_add_policy_again is not changed - nm_add_policy_again is not changed @@ -78,20 +91,20 @@ # CHANGE LINK LEVEL POLICY - name: Change description of Link Level Policy (check mode) - aci_interface_policy_link_level: + cisco.aci.aci_interface_policy_link_level: <<: *interface_policy_link_level_present description: Ansible test Link Level Policy check_mode: true register: cm_add_policy_descr - name: Change description of Link Level Policy (normal mode) - aci_interface_policy_link_level: + cisco.aci.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: + ansible.builtin.assert: that: - cm_add_policy_descr is changed - nm_add_policy_descr is changed @@ -99,20 +112,20 @@ - 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: + cisco.aci.aci_interface_policy_link_level: <<: *interface_policy_link_level_present description: Ansible test Link Level Policy check_mode: true register: cm_add_policy_descr_again - name: Change description of Link Level Policy again (normal mode) - aci_interface_policy_link_level: + cisco.aci.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: + ansible.builtin.assert: that: - cm_add_policy_descr_again is not changed - nm_add_policy_descr_again is not changed @@ -122,26 +135,88 @@ # 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 + cisco.aci.aci_interface_policy_link_level: *interface_policy_link_level_present check_mode: true register: cm_add_policy_again_no_descr - name: Add Link Level Policy again with no description (normal mode) - aci_interface_policy_link_level: *interface_policy_link_level_present + cisco.aci.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: + ansible.builtin.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' + + # CHANGE SPEED ON LINK LEVEL POLICY + - name: Test each speed setting for Link Level Policy + block: + - name: Query system information to fetch version + cisco.aci.aci_system: + <<: *aci_info + id: 1 + state: query + register: version + + - name: Define speed settings in version < 5.2 + set_fact: + supported_speed: ["100M", "1G", "10G", "25G", "40G", "50G", "100G", "200G", "400G", "inherit"] + when: version.current.0.topSystem.attributes.version is version('5.2', '<') + + - name: Define speed settings in version >= 5.2 + set_fact: + supported_speed: ["100M", "1G", "10G", "25G", "40G", "50G", "100G", "200G", "400G", "auto", "inherit"] + when: version.current.0.topSystem.attributes.version is version('5.2', '>=') + + - name: Add Link Level Policy with various speeds (check mode) + cisco.aci.aci_interface_policy_link_level: + <<: *interface_policy_link_level_present + speed: "{{ item }}" + check_mode: true + loop: "{{ supported_speed }}" + register: cm_add_policy_speed + loop_control: + label: "speed-{{ item }}" + + - name: Add Link Level Policy with various speeds (normal mode) + cisco.aci.aci_interface_policy_link_level: + <<: *interface_policy_link_level_present + speed: "{{ item }}" + loop: "{{ supported_speed }}" + register: nm_add_policy_speed + loop_control: + label: "speed-{{ item }}" + + - name: Verify each speed setting (normal mode) + ansible.builtin.assert: + that: + - "item.1.current.0.fabricHIfPol.attributes.name == 'ansible_test'" + - "item.1.current.0.fabricHIfPol.attributes.dn == 'uni/infra/hintfpol-ansible_test'" + - "item.1.current.0.fabricHIfPol.attributes.speed == item.0" + quiet: true + loop: "{{ supported_speed | zip(nm_add_policy_speed.results) }}" + loop_control: + label: "speed-{{ item.0 }}" + + - name: Verify each speed setting (check mode) + ansible.builtin.assert: + that: + - "item.1.current.0.fabricHIfPol.attributes.name == 'ansible_test'" + - "item.1.current.0.fabricHIfPol.attributes.dn == 'uni/infra/hintfpol-ansible_test'" + - "item.1.current.0.fabricHIfPol.attributes.speed == 'inherit'" + - "item.1.proposed.fabricHIfPol.attributes.speed == item.0" + quiet: true + loop: "{{ supported_speed | zip(cm_add_policy_speed.results) }}" + loop_control: + label: "speed-{{ item.0 }}" # QUERY ALL LINK LEVEL POLICIES - name: Query all Link Level Policies (check mode) - aci_interface_policy_link_level: &interface_policy_link_level_query + cisco.aci.aci_interface_policy_link_level: &interface_policy_link_level_query host: '{{ aci_hostname }}' username: '{{ aci_username }}' password: '{{ aci_password }}' @@ -154,11 +229,11 @@ register: cm_query_all_policies - name: Query all Link Level Policies (normal mode) - aci_interface_policy_link_level: *interface_policy_link_level_query + cisco.aci.aci_interface_policy_link_level: *interface_policy_link_level_query register: nm_query_all_policies - name: Verify query_all_policies - assert: + ansible.builtin.assert: that: - cm_query_all_policies is not changed - nm_query_all_policies is not changed @@ -167,20 +242,20 @@ # QUERY A LINK LEVEL POLICY - name: Query our Link Level Policy (check mode) - aci_interface_policy_link_level: + cisco.aci.aci_interface_policy_link_level: <<: *interface_policy_link_level_query link_level_policy: ansible_test check_mode: true register: cm_query_policy - name: Query our Link Level Policy (normal mode) - aci_interface_policy_link_level: + cisco.aci.aci_interface_policy_link_level: <<: *interface_policy_link_level_query link_level_policy: ansible_test register: nm_query_policy - name: Verify query_policy - assert: + ansible.builtin.assert: that: - cm_query_policy is not changed - nm_query_policy is not changed @@ -191,16 +266,16 @@ # REMOVE LINK LEVEL POLICY - name: Remove Link Level Policy (check mode) - aci_interface_policy_link_level: *interface_policy_link_level_absent + cisco.aci.aci_interface_policy_link_level: *interface_policy_link_level_absent check_mode: true register: cm_remove_policy - name: Remove Link Level Policy (normal mode) - aci_interface_policy_link_level: *interface_policy_link_level_absent + cisco.aci.aci_interface_policy_link_level: *interface_policy_link_level_absent register: nm_remove_policy - name: Verify remove_policy - assert: + ansible.builtin.assert: that: - cm_remove_policy is changed - nm_remove_policy is changed @@ -210,16 +285,16 @@ - nm_remove_policy.current == [] - name: Remove Link Level Policy again (check mode) - aci_interface_policy_link_level: *interface_policy_link_level_absent + cisco.aci.aci_interface_policy_link_level: *interface_policy_link_level_absent check_mode: true register: cm_remove_policy_again - name: Remove Link Level Policy again (normal mode) - aci_interface_policy_link_level: *interface_policy_link_level_absent + cisco.aci.aci_interface_policy_link_level: *interface_policy_link_level_absent register: nm_remove_policy_again - name: Verify remove_policy_again - assert: + ansible.builtin.assert: that: - cm_remove_policy_again is not changed - nm_remove_policy_again is not changed @@ -229,20 +304,20 @@ # QUERY NON-EXISTING LINK LEVEL POLICY - name: Query non-existing Link Level Policy (check mode) - aci_interface_policy_link_level: + cisco.aci.aci_interface_policy_link_level: <<: *interface_policy_link_level_query link_level_policy: ansible_test check_mode: true register: cm_query_non_policy - name: Query non-existing Link Level Policy (normal mode) - aci_interface_policy_link_level: + cisco.aci.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: + ansible.builtin.assert: that: - cm_query_non_policy is not changed - nm_query_non_policy is not changed @@ -251,7 +326,7 @@ # PROVOKE ERRORS - REQUIRED PARAMETER MISSING - name: Error when required parameter is missing - aci_interface_policy_link_level: + cisco.aci.aci_interface_policy_link_level: host: '{{ aci_hostname }}' username: '{{ aci_username }}' password: '{{ aci_password }}' @@ -264,14 +339,14 @@ register: error_on_missing_required_param - name: Verify error_on_missing_required_param - assert: + ansible.builtin.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: + cisco.aci.aci_interface_policy_link_level: host: '{{ aci_hostname }}' username: '{{ aci_username }}' password: '{{ aci_password }}' @@ -286,7 +361,7 @@ register: error_on_debounce_out_of_range - name: Verify error_on_debounce_out_of_range - assert: + ansible.builtin.assert: that: - error_on_debounce_out_of_range is failed - 'error_on_debounce_out_of_range.msg == "The \"link_debounce_interval\" must be a value between 0 and 5000"' \ No newline at end of file diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_interface_policy_lldp/tasks/main.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_interface_policy_lldp/tasks/main.yml index 225e142ba..f06adae80 100644 --- a/ansible_collections/cisco/aci/tests/integration/targets/aci_interface_policy_lldp/tasks/main.yml +++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_interface_policy_lldp/tasks/main.yml @@ -4,12 +4,12 @@ # GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) - name: Test that we have an ACI APIC host, ACI username and ACI password - fail: + ansible.builtin.fail: msg: 'Please define the following variables: aci_hostname, aci_username and aci_password.' when: aci_hostname is not defined or aci_username is not defined or aci_password is not defined - name: Set vars - set_fact: + ansible.builtin.set_fact: aci_info: &aci_info host: "{{ aci_hostname }}" username: "{{ aci_username }}" @@ -20,14 +20,14 @@ output_level: debug - name: Verify Cloud and Non-Cloud Sites in use. - include_tasks: ../../../../../../integration/targets/aci_cloud_provider/tasks/main.yml + ansible.builtin.include_tasks: ../../../../../../integration/targets/aci_cloud_provider/tasks/main.yml - name: Execute tasks only for non-cloud sites when: query_cloud.current == [] # This condition will execute only non-cloud sites block: # block specifies execution of tasks within, based on conditions # Clean Environment - name: Ensure first lldp interface policy does not exist - aci_interface_policy_lldp: &aci_interface_policy_lldp_absent + cisco.aci.aci_interface_policy_lldp: &aci_interface_policy_lldp_absent <<: *aci_info name: anstest_policy description: test for lldp interface policy @@ -36,36 +36,36 @@ state: absent - name: Ensure second lldp interface policy does not exist - aci_interface_policy_lldp: &aci_interface_policy_lldp_2_absent + cisco.aci.aci_interface_policy_lldp: &aci_interface_policy_lldp_2_absent <<: *aci_info name: anstest_policy_2 state: absent - name: Create first lldp interface policy (check_mode) - aci_interface_policy_lldp: &aci_interface_policy_lldp_present + cisco.aci.aci_interface_policy_lldp: &aci_interface_policy_lldp_present <<: *aci_interface_policy_lldp_absent state: present check_mode: true register: cm_add_interface_policy_lldp_1 - name: Create first lldp interface policy (normal_mode) - aci_interface_policy_lldp: + cisco.aci.aci_interface_policy_lldp: <<: *aci_interface_policy_lldp_present register: nm_add_interface_policy_lldp_1 - name: Create first lldp interface policy again - testing idempotency - aci_interface_policy_lldp: + cisco.aci.aci_interface_policy_lldp: <<: *aci_interface_policy_lldp_present register: idempotency_add_interface_policy_lldp_1 - name: Create second lldp interface policy - aci_interface_policy_lldp: &aci_interface_policy_lldp_2_present + cisco.aci.aci_interface_policy_lldp: &aci_interface_policy_lldp_2_present <<: *aci_interface_policy_lldp_2_absent state: present register: nm_add_interface_policy_lldp_2 - name: Asserts for creation tasks - assert: + ansible.builtin.assert: that: - cm_add_interface_policy_lldp_1 is changed - cm_add_interface_policy_lldp_1.previous == [] @@ -81,19 +81,19 @@ - nm_add_interface_policy_lldp_2.current.0.lldpIfPol.attributes.adminTxSt == "enabled" - name: Query all lldp interface policies - aci_interface_policy_lldp: + cisco.aci.aci_interface_policy_lldp: <<: *aci_info state: query register: query_all_interface_policy_lldp - name: Query first lldp interface policy - aci_interface_policy_lldp: + cisco.aci.aci_interface_policy_lldp: <<: *aci_interface_policy_lldp_present state: query register: query_first_interface_policy_lldp - name: Asserts for query tasks - assert: + ansible.builtin.assert: that: - query_all_interface_policy_lldp is not changed - query_all_interface_policy_lldp.current | length >= 2 @@ -104,32 +104,32 @@ - query_first_interface_policy_lldp.current.0.lldpIfPol.attributes.adminTxSt == "disabled" - name: Delete first lldp interface policy (check_mode) - aci_interface_policy_lldp: + cisco.aci.aci_interface_policy_lldp: <<: *aci_interface_policy_lldp_present state: absent check_mode: true register: cm_delete_interface_policy_lldp_1 - name: Delete first lldp interface policy (normal_mode) - aci_interface_policy_lldp: + cisco.aci.aci_interface_policy_lldp: <<: *aci_interface_policy_lldp_present state: absent register: nm_delete_interface_policy_lldp_1 - name: Delete first lldp interface policy again - testing idempotency - aci_interface_policy_lldp: + cisco.aci.aci_interface_policy_lldp: <<: *aci_interface_policy_lldp_present state: absent register: idempotency_delete_interface_policy_lldp_1 - name: Delete second lldp interface policy (normal_mode) - aci_interface_policy_lldp: + cisco.aci.aci_interface_policy_lldp: <<: *aci_interface_policy_lldp_2_present state: absent register: nm_delete_interface_policy_lldp_2 - name: Asserts for deletion tasks - assert: + ansible.builtin.assert: that: - cm_delete_interface_policy_lldp_1 is changed - cm_delete_interface_policy_lldp_1.proposed == {} diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_interface_policy_mcp/tasks/main.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_interface_policy_mcp/tasks/main.yml index 7255c14ad..63ceb0f45 100644 --- a/ansible_collections/cisco/aci/tests/integration/targets/aci_interface_policy_mcp/tasks/main.yml +++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_interface_policy_mcp/tasks/main.yml @@ -4,12 +4,12 @@ # GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) - name: Test that we have an ACI APIC host, ACI username and ACI password - fail: + ansible.builtin.fail: msg: 'Please define the following variables: aci_hostname, aci_username and aci_password.' when: aci_hostname is not defined or aci_username is not defined or aci_password is not defined - name: Set vars - set_fact: + ansible.builtin.set_fact: aci_info: &aci_info host: "{{ aci_hostname }}" username: "{{ aci_username }}" @@ -20,14 +20,14 @@ output_level: debug - name: Verify Cloud and Non-Cloud Sites in use. - include_tasks: ../../../../../../integration/targets/aci_cloud_provider/tasks/main.yml + ansible.builtin.include_tasks: ../../../../../../integration/targets/aci_cloud_provider/tasks/main.yml - name: Execute tasks only for non-cloud sites when: query_cloud.current == [] # This condition will execute only non-cloud sites block: # block specifies execution of tasks within, based on conditions # Clean Environment - name: Ensure first mcp interface policy does not exist - APIC version >= 5.0 - aci_interface_policy_mcp: &aci_interface_policy_mcp_absent_5 + cisco.aci.aci_interface_policy_mcp: &aci_interface_policy_mcp_absent_5 <<: *aci_info name: anstest_policy description: test for mcp interface policy @@ -42,7 +42,7 @@ when: version.current.0.topSystem.attributes.version is version('5', '>=') - name: Ensure first mcp interface policy does not exist - aci_interface_policy_mcp: &aci_interface_policy_mcp_absent + cisco.aci.aci_interface_policy_mcp: &aci_interface_policy_mcp_absent <<: *aci_info name: anstest_policy description: test for mcp interface policy @@ -51,13 +51,13 @@ when: version.current.0.topSystem.attributes.version is version('5', '<') - name: Ensure second mcp interface policy does not exist - aci_interface_policy_mcp: &aci_interface_policy_mcp_2_absent + cisco.aci.aci_interface_policy_mcp: &aci_interface_policy_mcp_2_absent <<: *aci_info name: anstest_policy_2 state: absent - name: Create first mcp interface policy (check_mode) - APIC version >= 5.0 - aci_interface_policy_mcp: &aci_interface_policy_mcp_present_5 + cisco.aci.aci_interface_policy_mcp: &aci_interface_policy_mcp_present_5 <<: *aci_interface_policy_mcp_absent_5 state: present check_mode: true @@ -65,19 +65,19 @@ when: version.current.0.topSystem.attributes.version is version('5', '>=') - name: Create first mcp interface policy (normal_mode) - APIC version >= 5.0 - aci_interface_policy_mcp: + cisco.aci.aci_interface_policy_mcp: <<: *aci_interface_policy_mcp_present_5 register: nm_add_interface_policy_mcp_1_5 when: version.current.0.topSystem.attributes.version is version('5', '>=') - name: Create first mcp interface policy again - testing idempotency - APIC version >= 5.0 - aci_interface_policy_mcp: + cisco.aci.aci_interface_policy_mcp: <<: *aci_interface_policy_mcp_present_5 register: idempotency_add_interface_policy_mcp_1_5 when: version.current.0.topSystem.attributes.version is version('5', '>=') - name: Create first mcp interface policy (check_mode) - APIC version < 5.0 - aci_interface_policy_mcp: &aci_interface_policy_mcp_present + cisco.aci.aci_interface_policy_mcp: &aci_interface_policy_mcp_present <<: *aci_interface_policy_mcp_absent state: present check_mode: true @@ -85,25 +85,25 @@ when: version.current.0.topSystem.attributes.version is version('5', '<') - name: Create first mcp interface policy (normal_mode) - APIC version < 5.0 - aci_interface_policy_mcp: + cisco.aci.aci_interface_policy_mcp: <<: *aci_interface_policy_mcp_present register: nm_add_interface_policy_mcp_1 when: version.current.0.topSystem.attributes.version is version('5', '<') - name: Create first mcp interface policy again - testing idempotency - APIC version < 5.0 - aci_interface_policy_mcp: + cisco.aci.aci_interface_policy_mcp: <<: *aci_interface_policy_mcp_present register: idempotency_add_interface_policy_mcp_1 when: version.current.0.topSystem.attributes.version is version('5', '<') - name: Create second mcp interface policy - aci_interface_policy_mcp: &aci_interface_policy_mcp_2_present + cisco.aci.aci_interface_policy_mcp: &aci_interface_policy_mcp_2_present <<: *aci_interface_policy_mcp_2_absent state: present register: nm_add_interface_policy_mcp_2 - name: Asserts for creation tasks for first mcp interface policy - APIC version >= 5.0 - assert: + ansible.builtin.assert: that: - cm_add_interface_policy_mcp_1_5 is changed - cm_add_interface_policy_mcp_1_5.previous == [] @@ -115,7 +115,7 @@ when: version.current.0.topSystem.attributes.version is version('5', '>=') - name: Asserts for creation tasks for first mcp interface policy - APIC version < 5.0 - assert: + ansible.builtin.assert: that: - cm_add_interface_policy_mcp_1 is changed - cm_add_interface_policy_mcp_1.previous == [] @@ -127,55 +127,55 @@ when: version.current.0.topSystem.attributes.version is version('5', '<') - name: Asserts for creation tasks for second mcp interface policy - assert: + ansible.builtin.assert: that: - nm_add_interface_policy_mcp_2 is changed - nm_add_interface_policy_mcp_2.current.0.mcpIfPol.attributes.name == "anstest_policy_2" - nm_add_interface_policy_mcp_2.current.0.mcpIfPol.attributes.adminSt == "enabled" - name: Query all mcp interface policies - aci_interface_policy_mcp: + cisco.aci.aci_interface_policy_mcp: <<: *aci_info state: query register: query_all_interface_policy_mcp - name: Query first mcp interface policy - aci_interface_policy_mcp: + cisco.aci.aci_interface_policy_mcp: <<: *aci_interface_policy_mcp_present_5 state: query register: query_first_interface_policy_mcp_5 when: version.current.0.topSystem.attributes.version is version('5', '>=') - name: Query first mcp interface policy - aci_interface_policy_mcp: + cisco.aci.aci_interface_policy_mcp: <<: *aci_interface_policy_mcp_present state: query register: query_first_interface_policy_mcp when: version.current.0.topSystem.attributes.version is version('5', '<') - name: Asserts for query tasks - assert: + ansible.builtin.assert: that: - query_all_interface_policy_mcp is not changed - query_all_interface_policy_mcp.current | length >= 2 - '"class/mcpIfPol.json" in query_all_interface_policy_mcp.url' - name: Asserts for individual query tasks - APIC version >= 5.0 - assert: + ansible.builtin.assert: that: - query_first_interface_policy_mcp_5.current.0.mcpIfPol.attributes.name == "anstest_policy" - query_first_interface_policy_mcp_5.current.0.mcpIfPol.attributes.adminSt == "disabled" when: version.current.0.topSystem.attributes.version is version('5', '>=') - name: Asserts for individual query tasks - APIC version < 5.0 - assert: + ansible.builtin.assert: that: - query_first_interface_policy_mcp.current.0.mcpIfPol.attributes.name == "anstest_policy" - query_first_interface_policy_mcp.current.0.mcpIfPol.attributes.adminSt == "disabled" when: version.current.0.topSystem.attributes.version is version('5', '<') - name: Delete first mcp interface policy (check_mode) - APIC version >= 5.0 - aci_interface_policy_mcp: + cisco.aci.aci_interface_policy_mcp: <<: *aci_interface_policy_mcp_present_5 state: absent check_mode: true @@ -183,21 +183,21 @@ when: version.current.0.topSystem.attributes.version is version('5', '>=') - name: Delete first mcp interface policy (normal_mode) - APIC version >= 5.0 - aci_interface_policy_mcp: + cisco.aci.aci_interface_policy_mcp: <<: *aci_interface_policy_mcp_present_5 state: absent register: nm_delete_interface_policy_mcp_1_5 when: version.current.0.topSystem.attributes.version is version('5', '>=') - name: Delete first mcp interface policy again - testing idempotency - APIC version >= 5.0 - aci_interface_policy_mcp: + cisco.aci.aci_interface_policy_mcp: <<: *aci_interface_policy_mcp_present_5 state: absent register: idempotency_delete_interface_policy_mcp_1_5 when: version.current.0.topSystem.attributes.version is version('5', '>=') - name: Delete first mcp interface policy (check_mode) - APIC version < 5.0 - aci_interface_policy_mcp: + cisco.aci.aci_interface_policy_mcp: <<: *aci_interface_policy_mcp_present state: absent check_mode: true @@ -205,27 +205,27 @@ when: version.current.0.topSystem.attributes.version is version('5', '<') - name: Delete first mcp interface policy (normal_mode) - APIC version < 5.0 - aci_interface_policy_mcp: + cisco.aci.aci_interface_policy_mcp: <<: *aci_interface_policy_mcp_present state: absent register: nm_delete_interface_policy_mcp_1 when: version.current.0.topSystem.attributes.version is version('5', '<') - name: Delete first mcp interface policy again - testing idempotency - APIC version < 5.0 - aci_interface_policy_mcp: + cisco.aci.aci_interface_policy_mcp: <<: *aci_interface_policy_mcp_present state: absent register: idempotency_delete_interface_policy_mcp_1 when: version.current.0.topSystem.attributes.version is version('5', '<') - name: Delete second mcp interface policy (normal_mode) - aci_interface_policy_mcp: + cisco.aci.aci_interface_policy_mcp: <<: *aci_interface_policy_mcp_2_present state: absent register: nm_delete_interface_policy_mcp_2 - name: Asserts for first mcp interface policy deletion tasks - APIC version >= 5.0 - assert: + ansible.builtin.assert: that: - cm_delete_interface_policy_mcp_1_5 is changed - cm_delete_interface_policy_mcp_1_5.proposed == {} @@ -237,7 +237,7 @@ when: version.current.0.topSystem.attributes.version is version('5', '>=') - name: Asserts for first mcp interface policy deletion tasks - APIC version < 5.0 - assert: + ansible.builtin.assert: that: - cm_delete_interface_policy_mcp_1 is changed - cm_delete_interface_policy_mcp_1.proposed == {} @@ -249,7 +249,7 @@ when: version.current.0.topSystem.attributes.version is version('5', '<') - name: Asserts for second mcp interface policy deletion tasks - assert: + ansible.builtin.assert: that: - nm_delete_interface_policy_mcp_2.previous != [] - nm_delete_interface_policy_mcp_2.current == [] diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_interface_policy_ospf/tasks/main.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_interface_policy_ospf/tasks/main.yml index 71e096435..5dce71fcb 100644 --- a/ansible_collections/cisco/aci/tests/integration/targets/aci_interface_policy_ospf/tasks/main.yml +++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_interface_policy_ospf/tasks/main.yml @@ -4,12 +4,12 @@ # GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) - name: Test that we have an ACI APIC host, ACI username and ACI password - fail: + ansible.builtin.fail: msg: 'Please define the following variables: aci_hostname, aci_username and aci_password.' when: aci_hostname is not defined or aci_username is not defined or aci_password is not defined - name: Set vars - set_fact: + ansible.builtin.set_fact: aci_info: &aci_info host: '{{ aci_hostname }}' username: '{{ aci_username }}' @@ -53,7 +53,7 @@ register: nm_add_ospf_interface_policy_again - name: Verify add_ospf_interface_policy - assert: + ansible.builtin.assert: that: - cm_add_ospf_interface_policy is changed - cm_add_ospf_interface_policy.current == [] @@ -134,7 +134,7 @@ register: nm_add_ospf_descr_again - name: Verify add_ospf_descr - assert: + ansible.builtin.assert: that: - cm_add_ospf_descr is changed - cm_add_ospf_descr.previous.0.ospfIfPol.attributes.annotation == "orchestrator:ansible" @@ -256,7 +256,7 @@ register: err_change_ospf_transmit_delay - name: Verify cost change and error input values - assert: + ansible.builtin.assert: that: - err_change_ospf_cost is not changed - err_change_ospf_cost.msg == "Parameter 'cost' is only valid in range between 1 and 450." @@ -282,7 +282,7 @@ register: nm_add_ospf_again_no_descr - name: Verify add_ospf_again_no_descr - assert: + ansible.builtin.assert: that: - cm_add_ospf_again_no_descr is not changed - nm_add_ospf_again_no_descr is not changed @@ -308,7 +308,7 @@ register: nm_query_all_ospfs - name: Verify query_all_ospfs - assert: + ansible.builtin.assert: that: - cm_query_all_ospfs is not changed - nm_query_all_ospfs is not changed @@ -333,7 +333,7 @@ register: nm_query_ospf - name: Verify query_ospf - assert: + ansible.builtin.assert: that: - cm_query_ospf is not changed - nm_query_ospf is not changed @@ -360,7 +360,7 @@ register: nm_remove_ospf_again - name: Verify remove_ospf - assert: + ansible.builtin.assert: that: - cm_remove_ospf is changed - nm_remove_ospf is changed @@ -384,7 +384,7 @@ # TODO: Implement more tests - name: Verify query_non_ospf - assert: + ansible.builtin.assert: that: - cm_query_non_ospf is not changed - nm_query_non_ospf is not changed diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_interface_policy_pim/aliases b/ansible_collections/cisco/aci/tests/integration/targets/aci_interface_policy_pim/aliases new file mode 100644 index 000000000..209b793f9 --- /dev/null +++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_interface_policy_pim/aliases @@ -0,0 +1,2 @@ +# No ACI simulator yet, so not enabled +# unsupported diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_interface_policy_pim/tasks/main.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_interface_policy_pim/tasks/main.yml new file mode 100644 index 000000000..df4914b7a --- /dev/null +++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_interface_policy_pim/tasks/main.yml @@ -0,0 +1,275 @@ +# Test code for the ACI modules +# Copyright: (c) 2023, Gaspard Micol (@gmicol) + +# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) + +- name: Test that we have an ACI APIC host, ACI username and ACI password + ansible.builtin.fail: + msg: 'Please define the following variables: aci_hostname, aci_username and aci_password.' + when: aci_hostname is not defined or aci_username is not defined or aci_password is not defined + +- name: Set vars + ansible.builtin.set_fact: + aci_info: &aci_info + host: "{{ aci_hostname }}" + username: "{{ aci_username }}" + password: "{{ aci_password }}" + validate_certs: '{{ aci_validate_certs | default(false) }}' + use_ssl: '{{ aci_use_ssl | default(true) }}' + use_proxy: '{{ aci_use_proxy | default(true) }}' + output_level: '{{ aci_output_level | default("info") }}' + +# CLEAN ENVIRONMENT +- name: Remove the ansible_tenant + cisco.aci.aci_tenant: &aci_tenant_absent + <<: *aci_info + tenant: ansible_tenant + state: absent + +- name: Verify Cloud and Non-Cloud Sites in use. + ansible.builtin.include_tasks: ../../../../../../integration/targets/aci_cloud_provider/tasks/main.yml + +- name: Execute tasks only for non-cloud sites + when: query_cloud.current == [] # This condition will execute only non-cloud sites + block: # block specifies execution of tasks within, based on conditions + - name: Add a new tenant + cisco.aci.aci_tenant: &aci_tenant_present + <<: *aci_info + tenant: ansible_tenant + description: Ansible tenant + state: present + + - name: Add a new PIM route map policy + cisco.aci.aci_pim_route_map_policy: + <<: *aci_info + tenant: ansible_tenant + pim_route_map_policy: ansible_pim_route_map_policy + description: PIM route map policy 1 for ansible_tenant tenant + state: present + + # CREATION TASKS + - name: Add a pim interface policy (check_mode) + cisco.aci.aci_interface_policy_pim: &aci_interface_policy_pim_present + <<: *aci_info + tenant: ansible_tenant + pim: ansible_pim_interface_1 + description: pim interface policy 1 for ansible_tenant tenant + authentication_key: my_password + authentication_type: md5_hmac + control_state: [multicast_domain_boundary, strict_rfc_compliant, passive] + designated_router_delay: 6 + designated_router_priority: 2 + hello_interval: 60000 + join_prune_interval: 120 + inbound_join_prune_filter_policy: ansible_pim_route_map_policy + outbound_join_prune_filter_policy: ansible_pim_route_map_policy + neighbor_filter_policy: ansible_pim_route_map_policy + state: present + check_mode: true + register: cm_add_pim_interface + + - name: Add a pim interface policy (normal_mode) + cisco.aci.aci_interface_policy_pim: + <<: *aci_interface_policy_pim_present + register: nm_add_pim_interface + + - name: Add a second pim interface policy (normal_mode) + cisco.aci.aci_interface_policy_pim: + <<: *aci_info + tenant: ansible_tenant + pim: ansible_pim_interface_2 + description: pim interface policy 2 for ansible_tenant tenant + state: present + register: nm_add_pim_interface_2 + + - name: Add a third pim interface policy - designed router delay out of bounds + cisco.aci.aci_interface_policy_pim: + <<: *aci_info + tenant: ansible_tenant + pim: ansible_pim_interface_3 + designated_router_delay: 65536 + state: present + ignore_errors: true + register: error_dr_relay_out_of_bounds + + - name: Add a fourth pim interface policy - designed router priority out of bounds + cisco.aci.aci_interface_policy_pim: + <<: *aci_info + tenant: ansible_tenant + pim: ansible_pim_interface_4 + designated_router_priority: 4294967296 + state: present + ignore_errors: true + register: error_dr_priority_out_of_bounds + + - name: Add a fifth pim interface policy - hello interval out of bounds + cisco.aci.aci_interface_policy_pim: + <<: *aci_info + tenant: ansible_tenant + pim: ansible_pim_interface_5 + hello_interval: 18724287 + state: present + ignore_errors: true + register: error_helloIntvl_out_of_bounds + + - name: Add a sixth pim interface policy - join prune interval out of bounds + cisco.aci.aci_interface_policy_pim: + <<: *aci_info + tenant: ansible_tenant + pim: ansible_pim_interface_6 + join_prune_interval: 65521 + state: present + ignore_errors: true + register: error_jpIntvl_out_of_bounds + + - name: Asserts for pim interface policy creation tasks + ansible.builtin.assert: + that: + - cm_add_pim_interface is changed + - cm_add_pim_interface.previous == [] + - cm_add_pim_interface.current == [] + - nm_add_pim_interface is changed + - nm_add_pim_interface.current.0.pimIfPol.attributes.name == "ansible_pim_interface_1" + - nm_add_pim_interface.current.0.pimIfPol.attributes.authT == "ah-md5" + - nm_add_pim_interface.current.0.pimIfPol.attributes.ctrl == "border,passive,strict-rfc-compliant" + - nm_add_pim_interface.current.0.pimIfPol.attributes.drDelay == "6" + - nm_add_pim_interface.current.0.pimIfPol.attributes.drPrio == "2" + - nm_add_pim_interface.current.0.pimIfPol.attributes.helloItvl == "60000" + - nm_add_pim_interface.current.0.pimIfPol.attributes.jpInterval == "120" + - nm_add_pim_interface.sent.pimIfPol.attributes.authKey == "VALUE_SPECIFIED_IN_NO_LOG_PARAMETER" + - nm_add_pim_interface_2 is changed + - nm_add_pim_interface_2.previous == [] + - nm_add_pim_interface_2.current.0.pimIfPol.attributes.name == "ansible_pim_interface_2" + - nm_add_pim_interface_2.current.0.pimIfPol.attributes.authT == "none" + - nm_add_pim_interface_2.current.0.pimIfPol.attributes.ctrl == "" + - nm_add_pim_interface_2.current.0.pimIfPol.attributes.drDelay == "3" + - nm_add_pim_interface_2.current.0.pimIfPol.attributes.drPrio == "1" + - nm_add_pim_interface_2.current.0.pimIfPol.attributes.helloItvl == "30000" + - nm_add_pim_interface_2.current.0.pimIfPol.attributes.jpInterval == "60" + - error_dr_relay_out_of_bounds.msg == "Parameter 'designated_router_delay' is only valid in range between 1 and 65535." + - error_dr_priority_out_of_bounds.msg == "Parameter 'designated_router_priority' is only valid in range between 1 and 4294967295." + - error_helloIntvl_out_of_bounds.msg == "Parameter 'hello_interval' is only valid in range between 1 and 18724286." + - error_jpIntvl_out_of_bounds.msg == "Parameter 'join_prune_interval' is only valid in range between 60 and 65520." + + # CREATION TASKS + - name: Query all pim interface policies + cisco.aci.aci_interface_policy_pim: + <<: *aci_info + state: query + register: query_all_pim_interface + + - name: Query ansible_pim_interface_1 + cisco.aci.aci_interface_policy_pim: + <<: *aci_interface_policy_pim_present + state: query + register: query_ansible_pim_interface_1 + + - name: Asserts query tasks + ansible.builtin.assert: + that: + - query_all_pim_interface is not changed + - query_all_pim_interface.current|length >= 2 + - query_ansible_pim_interface_1 is not changed + - query_ansible_pim_interface_1.current.0.pimIfPol.attributes.name == "ansible_pim_interface_1" + - query_ansible_pim_interface_1.current.0.pimIfPol.attributes.authT == "ah-md5" + - query_ansible_pim_interface_1.current.0.pimIfPol.attributes.ctrl == "border,passive,strict-rfc-compliant" + - query_ansible_pim_interface_1.current.0.pimIfPol.attributes.drDelay == "6" + - query_ansible_pim_interface_1.current.0.pimIfPol.attributes.drPrio == "2" + - query_ansible_pim_interface_1.current.0.pimIfPol.attributes.helloItvl == "60000" + - query_ansible_pim_interface_1.current.0.pimIfPol.attributes.jpInterval == "120" + + # UPDATE TASKS + - name: Update first pim interface policy (check_mode) + cisco.aci.aci_interface_policy_pim: &aci_interface_policy_pim_update + <<: *aci_interface_policy_pim_present + control_state: passive + designated_router_delay: 4 + designated_router_priority: 1 + hello_interval: 30000 + join_prune_interval: 60 + check_mode: true + register: cm_update_pim_interface + + - name: Update first pim interface policy (normal_mode) + cisco.aci.aci_interface_policy_pim: + <<: *aci_interface_policy_pim_update + register: nm_update_pim_interface + + - name: Asserts for pim interface policy update tasks + ansible.builtin.assert: + that: + - cm_update_pim_interface is changed + - cm_update_pim_interface.previous == cm_update_pim_interface.current + - nm_update_pim_interface is changed + - nm_update_pim_interface.current.0.pimIfPol.attributes.name == "ansible_pim_interface_1" + - nm_update_pim_interface.current.0.pimIfPol.attributes.authT == "ah-md5" + - nm_update_pim_interface.current.0.pimIfPol.attributes.ctrl == "passive" + - nm_update_pim_interface.current.0.pimIfPol.attributes.drDelay == "4" + - nm_update_pim_interface.current.0.pimIfPol.attributes.drPrio == "1" + - nm_update_pim_interface.current.0.pimIfPol.attributes.helloItvl == "30000" + - nm_update_pim_interface.current.0.pimIfPol.attributes.jpInterval == "60" + - nm_update_pim_interface.sent.pimIfPol.attributes.authKey == "VALUE_SPECIFIED_IN_NO_LOG_PARAMETER" + + # CHILDREN DELETION TASKS + - name: Remove inbound join prune filter from pim interface policy (check_mode) + cisco.aci.aci_interface_policy_pim: &pim_interface_inbound_jp_absent + <<: *aci_interface_policy_pim_update + inbound_join_prune_filter_policy: "" + check_mode: true + register: cm_remove_pim_interface_inbound_jp + + - name: Remove inbound join prune filter from pim interface policy (normal_mode) + cisco.aci.aci_interface_policy_pim: + <<: *pim_interface_inbound_jp_absent + register: nm_remove_pim_interface_inbound_jp + + - name: Remove outbound join prune filter and neighbor filter from pim interface policy (normal_mode) + cisco.aci.aci_interface_policy_pim: + <<: *pim_interface_inbound_jp_absent + outbound_join_prune_filter_policy: "" + neighbor_filter_policy: "" + register: cm_remove_pim_interface_all_child_classes + + - name: Asserts child classes deletion tasks + ansible.builtin.assert: + that: + - cm_remove_pim_interface_inbound_jp is changed + - cm_remove_pim_interface_inbound_jp.current == cm_remove_pim_interface_inbound_jp.previous + - nm_remove_pim_interface_inbound_jp is changed + - nm_remove_pim_interface_inbound_jp.current.0.pimIfPol.children | length == 2 + - cm_remove_pim_interface_all_child_classes is changed + - cm_remove_pim_interface_all_child_classes.current.0.pimIfPol.children is not defined + + # DELETION TASKS + - name: Remove pim interface policy (check_mode) + cisco.aci.aci_interface_policy_pim: &pim_interface_absent + <<: *aci_interface_policy_pim_update + state: absent + check_mode: true + register: cm_remove_pim_interface + + - name: Remove pim interface policy (normal_mode) + cisco.aci.aci_interface_policy_pim: + <<: *pim_interface_absent + register: nm_remove_pim_interface + + - name: Remove pim interface policy - testing idempotency + cisco.aci.aci_interface_policy_pim: + <<: *pim_interface_absent + register: nm_remove_pim_interface_idempotency + + - name: Asserts deletion tasks + ansible.builtin.assert: + that: + - cm_remove_pim_interface is changed + - cm_remove_pim_interface.proposed == {} + - nm_remove_pim_interface is changed + - nm_remove_pim_interface.previous != [] + - nm_remove_pim_interface.current == [] + - nm_remove_pim_interface_idempotency is not changed + - nm_remove_pim_interface_idempotency.previous == [] + + - name: Remove the ansible_tenant - cleanup before ending tests + cisco.aci.aci_tenant: + <<: *aci_tenant_present + state: absent diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_interface_policy_port_channel/tasks/main.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_interface_policy_port_channel/tasks/main.yml index 36c84b30f..cac1bb65a 100644 --- a/ansible_collections/cisco/aci/tests/integration/targets/aci_interface_policy_port_channel/tasks/main.yml +++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_interface_policy_port_channel/tasks/main.yml @@ -4,12 +4,12 @@ # GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) - name: Test that we have an ACI APIC host, ACI username and ACI password - fail: + ansible.builtin.fail: msg: 'Please define the following variables: aci_hostname, aci_username and aci_password.' when: aci_hostname is not defined or aci_username is not defined or aci_password is not defined - name: Set vars - set_fact: + ansible.builtin.set_fact: aci_info: &aci_info host: "{{ aci_hostname }}" username: "{{ aci_username }}" @@ -20,14 +20,14 @@ output_level: debug - name: Verify Cloud and Non-Cloud Sites in use. - include_tasks: ../../../../../../integration/targets/aci_cloud_provider/tasks/main.yml + ansible.builtin.include_tasks: ../../../../../../integration/targets/aci_cloud_provider/tasks/main.yml - name: Execute tasks only for non-cloud sites when: query_cloud.current == [] # This condition will execute only non-cloud sites block: # block specifies execution of tasks within, based on conditions # Clean Environment - name: Ensure first port channel interface policy does not exist - aci_interface_policy_port_channel: &aci_interface_policy_port_channel_absent + cisco.aci.aci_interface_policy_port_channel: &aci_interface_policy_port_channel_absent <<: *aci_info name: anstest_policy description: test for port channel interface policy @@ -42,7 +42,7 @@ state: absent - name: Ensure second port channel interface policy does not exist - aci_interface_policy_port_channel: &aci_interface_policy_port_channel_2_absent + cisco.aci.aci_interface_policy_port_channel: &aci_interface_policy_port_channel_2_absent <<: *aci_info name: anstest_policy_2 fast_select: true @@ -51,44 +51,44 @@ state: absent - name: Create first port channel interface policy (check_mode) - aci_interface_policy_port_channel: &aci_interface_policy_port_channel_present + cisco.aci.aci_interface_policy_port_channel: &aci_interface_policy_port_channel_present <<: *aci_interface_policy_port_channel_absent state: present check_mode: true register: cm_add_interface_policy_port_channel_1 - name: Create first port channel interface policy (normal_mode) - aci_interface_policy_port_channel: + cisco.aci.aci_interface_policy_port_channel: <<: *aci_interface_policy_port_channel_present register: nm_add_interface_policy_port_channel_1 - name: Create first port channel interface policy again - testing idempotency - aci_interface_policy_port_channel: + cisco.aci.aci_interface_policy_port_channel: <<: *aci_interface_policy_port_channel_present register: idempotency_add_interface_policy_port_channel_1 - name: Create second port channel interface policy - aci_interface_policy_port_channel: &aci_interface_policy_port_channel_2_present + cisco.aci.aci_interface_policy_port_channel: &aci_interface_policy_port_channel_2_present <<: *aci_interface_policy_port_channel_2_absent state: present register: nm_add_interface_policy_port_channel_2 - name: Modify first port channel interface policy with max links above 16 - testing failure message - aci_interface_policy_port_channel: + cisco.aci.aci_interface_policy_port_channel: <<: *aci_interface_policy_port_channel_present max_links: 17 ignore_errors: true register: nm_policy_port_channel_max_links_failure - name: Modify first port channel interface policy with min links bellow 1 - testing failure message - aci_interface_policy_port_channel: + cisco.aci.aci_interface_policy_port_channel: <<: *aci_interface_policy_port_channel_present min_links: 0 ignore_errors: true register: nm_policy_port_channel_min_links_failure - name: Asserts for creation tasks - assert: + ansible.builtin.assert: that: - cm_add_interface_policy_port_channel_1 is changed - cm_add_interface_policy_port_channel_1.previous == [] @@ -110,19 +110,19 @@ - nm_policy_port_channel_min_links_failure.msg == "The \"min_links\" must be a value between 1 and 16" - name: Query all port channel interface policies - aci_interface_policy_port_channel: + cisco.aci.aci_interface_policy_port_channel: <<: *aci_info state: query register: query_all_interface_policy_port_channel - name: Query first port channel interface policy - aci_interface_policy_port_channel: + cisco.aci.aci_interface_policy_port_channel: <<: *aci_interface_policy_port_channel_present state: query register: query_first_interface_policy_port_channel - name: Asserts for query tasks - assert: + ansible.builtin.assert: that: - query_all_interface_policy_port_channel is not changed - query_all_interface_policy_port_channel.current | length >= 2 @@ -135,32 +135,32 @@ - query_first_interface_policy_port_channel.current.0.lacpLagPol.attributes.mode == "active" - name: Delete first port channel interface policy (check_mode) - aci_interface_policy_port_channel: + cisco.aci.aci_interface_policy_port_channel: <<: *aci_interface_policy_port_channel_present state: absent check_mode: true register: cm_delete_interface_policy_port_channel_1 - name: Delete first port channel interface policy (normal_mode) - aci_interface_policy_port_channel: + cisco.aci.aci_interface_policy_port_channel: <<: *aci_interface_policy_port_channel_present state: absent register: nm_delete_interface_policy_port_channel_1 - name: Delete first port channel interface policy again - testing idempotency - aci_interface_policy_port_channel: + cisco.aci.aci_interface_policy_port_channel: <<: *aci_interface_policy_port_channel_present state: absent register: idempotency_delete_interface_policy_port_channel_1 - name: Delete second port channel interface policy (normal_mode) - aci_interface_policy_port_channel: + cisco.aci.aci_interface_policy_port_channel: <<: *aci_interface_policy_port_channel_2_present state: absent register: nm_delete_interface_policy_port_channel_2 - name: Asserts for deletion tasks - assert: + ansible.builtin.assert: that: - cm_delete_interface_policy_port_channel_1 is changed - cm_delete_interface_policy_port_channel_1.proposed == {} diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_interface_policy_port_security/tasks/main.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_interface_policy_port_security/tasks/main.yml index c040bfb1e..9f4e958c4 100644 --- a/ansible_collections/cisco/aci/tests/integration/targets/aci_interface_policy_port_security/tasks/main.yml +++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_interface_policy_port_security/tasks/main.yml @@ -4,12 +4,12 @@ # GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) - name: Test that we have an ACI APIC host, ACI username and ACI password - fail: + ansible.builtin.fail: msg: 'Please define the following variables: aci_hostname, aci_username and aci_password.' when: aci_hostname is not defined or aci_username is not defined or aci_password is not defined - name: Set vars - set_fact: + ansible.builtin.set_fact: aci_info: &aci_info host: "{{ aci_hostname }}" username: "{{ aci_username }}" @@ -20,14 +20,14 @@ output_level: debug - name: Verify Cloud and Non-Cloud Sites in use. - include_tasks: ../../../../../../integration/targets/aci_cloud_provider/tasks/main.yml + ansible.builtin.include_tasks: ../../../../../../integration/targets/aci_cloud_provider/tasks/main.yml - name: Execute tasks only for non-cloud sites when: query_cloud.current == [] # This condition will execute only non-cloud sites block: # block specifies execution of tasks within, based on conditions # CLEAN ENVIRONMENT - name: Remove policy port security - aci_interface_policy_port_security: + cisco.aci.aci_interface_policy_port_security: <<: *aci_info port_security: '{{ item }}' state: absent @@ -38,7 +38,7 @@ # ADD - name: Add a port security interface policy - check mode - aci_interface_policy_port_security: + cisco.aci.aci_interface_policy_port_security: <<: *aci_info port_security: security1 description: security 1 @@ -49,7 +49,7 @@ register: port_security1_cm - name: Add a port security interface policy - normal mode - aci_interface_policy_port_security: + cisco.aci.aci_interface_policy_port_security: <<: *aci_info port_security: security1 description: security 1 @@ -59,7 +59,7 @@ register: port_security1_nm - name: Add a port security interface policy again - normal mode - aci_interface_policy_port_security: + cisco.aci.aci_interface_policy_port_security: <<: *aci_info port_security: security1 description: security 1 @@ -69,7 +69,7 @@ register: port_security1_nm_again - name: Add a port security interface policy - normal mode - aci_interface_policy_port_security: + cisco.aci.aci_interface_policy_port_security: <<: *aci_info port_security: security2 description: security 2 @@ -80,7 +80,7 @@ register: port_security1_nm_error_timeout - name: Add a port security interface policy - normal mode - aci_interface_policy_port_security: + cisco.aci.aci_interface_policy_port_security: <<: *aci_info port_security: security3 description: security 3 @@ -91,7 +91,7 @@ register: port_security1_nm_error_max - name: Add a port security interface policy again for security 3- normal mode - aci_interface_policy_port_security: + cisco.aci.aci_interface_policy_port_security: <<: *aci_info port_security: security3 description: security 3 @@ -102,7 +102,7 @@ register: port_security1_nm_with_no_error - name: Verify present cases - assert: + ansible.builtin.assert: that: - port_security1_cm is changed - port_security1_nm is changed @@ -123,20 +123,20 @@ # QUERY - name: Query a port security interface policy - normal mode - aci_interface_policy_port_security: + cisco.aci.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: + cisco.aci.aci_interface_policy_port_security: <<: *aci_info state: query register: port_all_query - name: Verify query cases - assert: + ansible.builtin.assert: that: - port_security1_query is not changed - port_all_query is not changed @@ -149,14 +149,14 @@ # REMOVE - name: Remove a port security interface policy - normal mode - aci_interface_policy_port_security: + cisco.aci.aci_interface_policy_port_security: <<: *aci_info port_security: security1 state: absent register: port_security1_remove - name: Verify remove cases - assert: + ansible.builtin.assert: that: - port_security1_remove is changed - port_security1_remove.previous.0.l2PortSecurityPol.attributes.dn == "uni/infra/portsecurityP-security1" @@ -167,7 +167,7 @@ # CLEAN END - name: Remove all policy port securities - aci_interface_policy_port_security: + cisco.aci.aci_interface_policy_port_security: <<: *aci_info port_security: '{{ item }}' state: absent diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_interface_policy_spanning_tree/tasks/main.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_interface_policy_spanning_tree/tasks/main.yml index 3bb33d896..aad106ae6 100644 --- a/ansible_collections/cisco/aci/tests/integration/targets/aci_interface_policy_spanning_tree/tasks/main.yml +++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_interface_policy_spanning_tree/tasks/main.yml @@ -4,12 +4,12 @@ # GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) - name: Test that we have an ACI APIC host, ACI username and ACI password - fail: + ansible.builtin.fail: msg: 'Please define the following variables: aci_hostname, aci_username and aci_password.' when: aci_hostname is not defined or aci_username is not defined or aci_password is not defined - name: Set vars - set_fact: + ansible.builtin.set_fact: aci_info: &aci_info host: "{{ aci_hostname }}" username: "{{ aci_username }}" @@ -20,14 +20,14 @@ output_level: "{{ aci_output_level | default('info') }}" - name: Verify Cloud and Non-Cloud Sites in use. - include_tasks: ../../../../../../integration/targets/aci_cloud_provider/tasks/main.yml + ansible.builtin.include_tasks: ../../../../../../integration/targets/aci_cloud_provider/tasks/main.yml - name: Execute tasks only for non-cloud sites when: query_cloud.current == [] # This condition will execute only non-cloud sites block: # block specifies execution of tasks within, based on conditions # CLEAN ENVIRONMENT - name: Remove policy spanning tree - aci_interface_policy_spanning_tree: + cisco.aci.aci_interface_policy_spanning_tree: <<: *aci_info stp_policy: "{{ item }}" state: absent @@ -38,7 +38,7 @@ # ADD - name: Add a spanning tree interface policy BPDU Guard - check mode - aci_interface_policy_spanning_tree: + cisco.aci.aci_interface_policy_spanning_tree: <<: *aci_info stp_policy: stp_bpduguard description: BPDU Guard @@ -48,7 +48,7 @@ register: stp_bpduguard_cm - name: Add a spanning tree interface policy BPDU Guard - normal mode - aci_interface_policy_spanning_tree: + cisco.aci.aci_interface_policy_spanning_tree: <<: *aci_info stp_policy: stp_bpduguard description: BPDU Guard @@ -57,7 +57,7 @@ register: stp_bpduguard_nm - name: Add a spanning tree interface policy BPDU Guard - normal mode again - aci_interface_policy_spanning_tree: + cisco.aci.aci_interface_policy_spanning_tree: <<: *aci_info stp_policy: stp_bpduguard description: BPDU Guard @@ -66,7 +66,7 @@ register: stp_bpduguard_nm_again - name: Add a spanning tree interface policy BPDU Filter - check mode - aci_interface_policy_spanning_tree: + cisco.aci.aci_interface_policy_spanning_tree: <<: *aci_info stp_policy: stp_bpdufilter description: BPDU Filter @@ -76,7 +76,7 @@ register: stp_bpdufilter_cm - name: Add a spanning tree interface policy BPDU Filter - normal mode - aci_interface_policy_spanning_tree: + cisco.aci.aci_interface_policy_spanning_tree: <<: *aci_info stp_policy: stp_bpdufilter description: BPDU Filter @@ -85,7 +85,7 @@ register: stp_bpdufilter_nm - name: Add a spanning tree interface policy BPDU Filter - normal mode again - aci_interface_policy_spanning_tree: + cisco.aci.aci_interface_policy_spanning_tree: <<: *aci_info stp_policy: stp_bpdufilter description: BPDU Filter @@ -94,7 +94,7 @@ register: stp_bpdufilter_nm_again - name: Add a spanning tree interface policy Both - normal mode - aci_interface_policy_spanning_tree: + cisco.aci.aci_interface_policy_spanning_tree: <<: *aci_info stp_policy: stp_both description: Both controls @@ -104,7 +104,7 @@ register: stp_both_nm - name: Add a spanning tree interface policy Both - normal mode again - aci_interface_policy_spanning_tree: + cisco.aci.aci_interface_policy_spanning_tree: <<: *aci_info stp_policy: stp_both description: Both controls @@ -114,7 +114,7 @@ register: stp_both_nm_again - name: verify add tasks - assert: + ansible.builtin.assert: that: - stp_bpduguard_cm is changed - stp_bpduguard_nm is changed @@ -130,20 +130,20 @@ # QUERY - name: Query a spanning tree interface policy - aci_interface_policy_spanning_tree: + cisco.aci.aci_interface_policy_spanning_tree: <<: *aci_info stp_policy: stp_both state: query register: stp_query_both - name: Query all spanning tree interface policies - aci_interface_policy_spanning_tree: + cisco.aci.aci_interface_policy_spanning_tree: <<: *aci_info state: query register: stp_query_all - name: verify query tasks - assert: + ansible.builtin.assert: that: - stp_query_both is not changed - stp_query_all is not changed @@ -152,7 +152,7 @@ # CLEAN ENVIRONMENT - name: Remove policy port security - aci_interface_policy_spanning_tree: + cisco.aci.aci_interface_policy_spanning_tree: <<: *aci_info stp_policy: "{{ item }}" state: absent diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_interface_policy_spine_policy_group/tasks/main.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_interface_policy_spine_policy_group/tasks/main.yml index fec8415a3..534614450 100644 --- a/ansible_collections/cisco/aci/tests/integration/targets/aci_interface_policy_spine_policy_group/tasks/main.yml +++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_interface_policy_spine_policy_group/tasks/main.yml @@ -4,12 +4,12 @@ # GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) - name: Test that we have an ACI APIC host, ACI username and ACI password - fail: + ansible.builtin.fail: msg: 'Please define the following variables: aci_hostname, aci_username and aci_password.' when: aci_hostname is not defined or aci_username is not defined or aci_password is not defined - name: Set vars - set_fact: + ansible.builtin.set_fact: aci_info: &aci_info host: "{{ aci_hostname }}" username: "{{ aci_username }}" @@ -20,7 +20,7 @@ output_level: debug - name: Verify Cloud and Non-Cloud Sites in use. - include_tasks: ../../../../../../integration/targets/aci_cloud_provider/tasks/main.yml + ansible.builtin.include_tasks: ../../../../../../integration/targets/aci_cloud_provider/tasks/main.yml - name: Execute tasks only for non-cloud sites when: query_cloud.current == [] # This condition will execute only non-cloud sites @@ -65,7 +65,7 @@ register: intf_policy_spine_polgrp_update - name: Verify present assertions for Spine Policy Group - assert: + ansible.builtin.assert: that: - intf_policy_spine_polgrp_check_mode_present is changed - intf_policy_spine_polgrp_present is changed @@ -97,7 +97,7 @@ register: query_spine_policy_group - name: Verify query assertions for Spine Policy Group - assert: + ansible.builtin.assert: that: - query_spine_policy_group is not changed - query_spine_policy_group.current[0] | length >= 1 @@ -120,7 +120,7 @@ register: intf_policy_spine_polgrp_absent_idempotent - name: Verify absent assertions for Spine Policy Group - assert: + ansible.builtin.assert: that: - intf_policy_spine_polgrp_check_mode_absent is changed - intf_policy_spine_polgrp_check_mode_absent.previous != [] diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_interface_policy_storm_control/aliases b/ansible_collections/cisco/aci/tests/integration/targets/aci_interface_policy_storm_control/aliases new file mode 100644 index 000000000..209b793f9 --- /dev/null +++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_interface_policy_storm_control/aliases @@ -0,0 +1,2 @@ +# No ACI simulator yet, so not enabled +# unsupported diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_interface_policy_storm_control/tasks/main.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_interface_policy_storm_control/tasks/main.yml new file mode 100644 index 000000000..656a50213 --- /dev/null +++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_interface_policy_storm_control/tasks/main.yml @@ -0,0 +1,285 @@ +# Test code for the ACI modules +# Copyright: (c) 2023, Eric Girard <@netgirard> +# Copyright: (c) 2024, Gaspard Micol (@gmicol) + +# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) + +- name: Test that we have an ACI APIC host, ACI username and ACI password + ansible.builtin.fail: + msg: 'Please define the following variables: aci_hostname, aci_username and aci_password.' + when: aci_hostname is not defined or aci_username is not defined or aci_password is not defined + +- name: Set vars + ansible.builtin.set_fact: + aci_info: &aci_info + host: "{{ aci_hostname }}" + username: "{{ aci_username }}" + password: "{{ aci_password }}" + validate_certs: '{{ aci_validate_certs | default(false) }}' + use_ssl: '{{ aci_use_ssl | default(true) }}' + use_proxy: '{{ aci_use_proxy | default(true) }}' + output_level: '{{ aci_output_level | default("info") }}' + +- name: Verify Cloud and Non-Cloud Sites in use. + ansible.builtin.include_tasks: ../../../../../../integration/targets/aci_cloud_provider/tasks/main.yml + +- name: Execute tasks only for non-cloud sites + when: query_cloud.current == [] # This condition will execute only non-cloud sites + block: # block specifies execution of tasks within, based on conditions + - name: Remove all ansible Storm Control policies before test begins + cisco.aci.aci_interface_policy_storm_control: &caci_storm_control_policies_cleanup + <<: *aci_info + storm_control_policy: '{{ item }}' + state: absent + loop: + - ansible_storm_control_policy_1 + - ansible_storm_control_policy_2 + - ansible_storm_control_policy_3 + - ansible_storm_control_policy_4 + + # CREATE STORM CONTROL POLICY + - name: Add a Storm Control policy (check_mode) + cisco.aci.aci_interface_policy_storm_control: &aci_interface_policy_storm_control_present + <<: *aci_info + storm_control_policy: ansible_storm_control_policy_1 + description: Storm Control policy 1 + all_types_configuration: + rate: 100 + burst_rate: 125 + rate_type: pps + storm_control_action: shutdown + storm_control_soak_action: 5 + check_mode: true + register: cm_add_storm_control_policy + + - name: Add a Storm Control policy (normal_mode) + cisco.aci.aci_interface_policy_storm_control: + <<: *aci_interface_policy_storm_control_present + register: nm_add_storm_control_policy + + - name: Add the first Storm Control policy again - testing idempotency + cisco.aci.aci_interface_policy_storm_control: + <<: *aci_interface_policy_storm_control_present + register: nm_add_storm_control_policy_idempotency + + - name: Add a second Storm Control policy (normal_mode) + cisco.aci.aci_interface_policy_storm_control: &aci_interface_policy_storm_control_2_present + <<: *aci_info + storm_control_policy: ansible_storm_control_policy_2 + description: Storm Control policy 2 + broadcast_configuration: + rate: 100 + burst_rate: 125 + rate_type: pps + multicast_configuration: + rate: 75 + burst_rate: 100 + rate_type: pps + unicast_configuration: + rate: 50 + burst_rate: 75 + rate_type: pps + register: nm_add_storm_control_policy_2 + + - name: Add a third Storm Control Policy (normal_mode) - testing empty configuration for multicast and unicast + cisco.aci.aci_interface_policy_storm_control: + <<: *aci_info + storm_control_policy: ansible_storm_control_policy_3 + broadcast_configuration: + rate: 25 + burst_rate: 50 + rate_type: pps + register: nm_add_storm_control_policy_3 + + - name: Add a fourth Storm Control Policy with rate in percentage out of bonds - testing error message + cisco.aci.aci_interface_policy_storm_control: + <<: *aci_info + storm_control_policy: ansible_storm_control_policy_4 + all_types_configuration: + rate: 125 + burst_rate: 100 + rate_type: percentage + ignore_errors: true + register: nm_test_error_msg_storm_control_policy + + - name: Asserts for Storm Control policy creation tasks + ansible.builtin.assert: + that: + - cm_add_storm_control_policy is changed + - cm_add_storm_control_policy.previous == [] + - cm_add_storm_control_policy.current == [] + - cm_add_storm_control_policy.proposed.stormctrlIfPol.attributes.name == "ansible_storm_control_policy_1" + - cm_add_storm_control_policy.proposed.stormctrlIfPol.attributes.descr == "Storm Control policy 1" + - cm_add_storm_control_policy.proposed.stormctrlIfPol.attributes.ratePps == "100" + - cm_add_storm_control_policy.proposed.stormctrlIfPol.attributes.burstPps == "125" + - cm_add_storm_control_policy.proposed.stormctrlIfPol.attributes.isUcMcBcStormPktCfgValid == "Invalid" + - cm_add_storm_control_policy.proposed.stormctrlIfPol.attributes.stormCtrlAction == "shutdown" + - cm_add_storm_control_policy.proposed.stormctrlIfPol.attributes.stormCtrlSoakInstCount == "5" + - nm_add_storm_control_policy is changed + - nm_add_storm_control_policy.previous == [] + - nm_add_storm_control_policy.current.0.stormctrlIfPol.attributes.name == "ansible_storm_control_policy_1" + - nm_add_storm_control_policy.current.0.stormctrlIfPol.attributes.descr == "Storm Control policy 1" + - nm_add_storm_control_policy.current.0.stormctrlIfPol.attributes.ratePps == "100" + - nm_add_storm_control_policy.current.0.stormctrlIfPol.attributes.burstPps == "125" + - nm_add_storm_control_policy.current.0.stormctrlIfPol.attributes.isUcMcBcStormPktCfgValid == "Invalid" + - nm_add_storm_control_policy.current.0.stormctrlIfPol.attributes.stormCtrlAction == "shutdown" + - nm_add_storm_control_policy.current.0.stormctrlIfPol.attributes.stormCtrlSoakInstCount == "5" + - nm_add_storm_control_policy_idempotency is not changed + - nm_add_storm_control_policy_idempotency.current.0.stormctrlIfPol.attributes.name == "ansible_storm_control_policy_1" + - nm_add_storm_control_policy_idempotency.current.0.stormctrlIfPol.attributes.descr == "Storm Control policy 1" + - nm_add_storm_control_policy_idempotency.current.0.stormctrlIfPol.attributes.ratePps == "100" + - nm_add_storm_control_policy_idempotency.current.0.stormctrlIfPol.attributes.burstPps == "125" + - nm_add_storm_control_policy_idempotency.current.0.stormctrlIfPol.attributes.isUcMcBcStormPktCfgValid == "Invalid" + - nm_add_storm_control_policy_idempotency.current.0.stormctrlIfPol.attributes.stormCtrlAction == "shutdown" + - nm_add_storm_control_policy_idempotency.current.0.stormctrlIfPol.attributes.stormCtrlSoakInstCount == "5" + - nm_add_storm_control_policy_2 is changed + - nm_add_storm_control_policy_2.previous == [] + - nm_add_storm_control_policy_2.current.0.stormctrlIfPol.attributes.name == "ansible_storm_control_policy_2" + - nm_add_storm_control_policy_2.current.0.stormctrlIfPol.attributes.descr == "Storm Control policy 2" + - nm_add_storm_control_policy_2.current.0.stormctrlIfPol.attributes.bcRatePps == "100" + - nm_add_storm_control_policy_2.current.0.stormctrlIfPol.attributes.bcBurstPps == "125" + - nm_add_storm_control_policy_2.current.0.stormctrlIfPol.attributes.mcRatePps == "75" + - nm_add_storm_control_policy_2.current.0.stormctrlIfPol.attributes.mcBurstPps == "100" + - nm_add_storm_control_policy_2.current.0.stormctrlIfPol.attributes.uucRatePps == "50" + - nm_add_storm_control_policy_2.current.0.stormctrlIfPol.attributes.uucBurstPps == "75" + - nm_add_storm_control_policy_2.current.0.stormctrlIfPol.attributes.isUcMcBcStormPktCfgValid == "Valid" + - nm_add_storm_control_policy_2.current.0.stormctrlIfPol.attributes.stormCtrlAction == "drop" + - nm_add_storm_control_policy_2.current.0.stormctrlIfPol.attributes.stormCtrlSoakInstCount == "3" + - nm_add_storm_control_policy_3 is changed + - nm_add_storm_control_policy_3.previous == [] + - nm_add_storm_control_policy_3.current.0.stormctrlIfPol.attributes.name == "ansible_storm_control_policy_3" + - nm_add_storm_control_policy_3.current.0.stormctrlIfPol.attributes.bcRatePps == "25" + - nm_add_storm_control_policy_3.current.0.stormctrlIfPol.attributes.bcBurstPps == "50" + - nm_add_storm_control_policy_3.current.0.stormctrlIfPol.attributes.mcRatePps == "unspecified" + - nm_add_storm_control_policy_3.current.0.stormctrlIfPol.attributes.mcRate == "100.000000" + - nm_add_storm_control_policy_3.current.0.stormctrlIfPol.attributes.mcBurstPps == "unspecified" + - nm_add_storm_control_policy_3.current.0.stormctrlIfPol.attributes.mcBurstRate == "100.000000" + - nm_add_storm_control_policy_3.current.0.stormctrlIfPol.attributes.uucRatePps == "unspecified" + - nm_add_storm_control_policy_3.current.0.stormctrlIfPol.attributes.uucRate == "100.000000" + - nm_add_storm_control_policy_3.current.0.stormctrlIfPol.attributes.uucBurstPps == "unspecified" + - nm_add_storm_control_policy_3.current.0.stormctrlIfPol.attributes.uucBurstRate == "100.000000" + - nm_add_storm_control_policy_3.current.0.stormctrlIfPol.attributes.isUcMcBcStormPktCfgValid == "Valid" + - nm_add_storm_control_policy_3.current.0.stormctrlIfPol.attributes.stormCtrlAction == "drop" + - nm_add_storm_control_policy_3.current.0.stormctrlIfPol.attributes.stormCtrlSoakInstCount == "3" + - nm_test_error_msg_storm_control_policy.msg == "If argument rate_type is percentage, the rate needs to be a value between 0 and 100 inclusive, got 125" + + # QUERY STORM CONTROL POLICY + - name: Query all Storm Control policies + cisco.aci.aci_interface_policy_storm_control: + <<: *aci_info + state: query + register: query_all_storm_control_policy + + - name: Query ansible_storm_control_policy_1 + cisco.aci.aci_interface_policy_storm_control: + <<: *aci_interface_policy_storm_control_present + state: query + register: query_ansible_storm_control_policy_1 + + - name: Asserts query tasks + ansible.builtin.assert: + that: + - query_all_storm_control_policy is not changed + - query_all_storm_control_policy.current|length >= 2 + - query_ansible_storm_control_policy_1 is not changed + - query_ansible_storm_control_policy_1.current|length == 1 + - query_ansible_storm_control_policy_1.current.0.stormctrlIfPol.attributes.name == "ansible_storm_control_policy_1" + - query_ansible_storm_control_policy_1.current.0.stormctrlIfPol.attributes.descr == "Storm Control policy 1" + - query_ansible_storm_control_policy_1.current.0.stormctrlIfPol.attributes.ratePps == "100" + - query_ansible_storm_control_policy_1.current.0.stormctrlIfPol.attributes.burstPps == "125" + - query_ansible_storm_control_policy_1.current.0.stormctrlIfPol.attributes.isUcMcBcStormPktCfgValid == "Invalid" + - query_ansible_storm_control_policy_1.current.0.stormctrlIfPol.attributes.stormCtrlAction == "shutdown" + - query_ansible_storm_control_policy_1.current.0.stormctrlIfPol.attributes.stormCtrlSoakInstCount == "5" + + # UPDATE STORM CONTROL POLICY + - name: Update first Storm Control policy (check_mode) + cisco.aci.aci_interface_policy_storm_control: &aci_interface_policy_storm_control_update + <<: *aci_interface_policy_storm_control_present + description: Updated description for first ansible Storm Control policy + all_types_configuration: + rate: 50 + burst_rate: 75 + rate_type: percentage + storm_control_action: drop + check_mode: true + register: cm_update_storm_control_policy + + - name: Update first Storm Control policy (normal_mode) + cisco.aci.aci_interface_policy_storm_control: + <<: *aci_interface_policy_storm_control_update + register: nm_update_storm_control_policy + + - name: Update first Storm Control policy again - testing idempotency + cisco.aci.aci_interface_policy_storm_control: + <<: *aci_interface_policy_storm_control_update + register: nm_udpate_storm_control_policy_idempotency + + - name: Asserts for Storm Control policy update tasks + ansible.builtin.assert: + that: + - cm_update_storm_control_policy is changed + - cm_update_storm_control_policy.previous == cm_update_storm_control_policy.current + - cm_update_storm_control_policy.proposed.stormctrlIfPol.attributes.descr == "Updated description for first ansible Storm Control policy" + - cm_update_storm_control_policy.proposed.stormctrlIfPol.attributes.rate == "50.000000" + - cm_update_storm_control_policy.proposed.stormctrlIfPol.attributes.burstRate == "75.000000" + - cm_update_storm_control_policy.proposed.stormctrlIfPol.attributes.ratePps == "unspecified" + - cm_update_storm_control_policy.proposed.stormctrlIfPol.attributes.burstPps == "unspecified" + - cm_update_storm_control_policy.proposed.stormctrlIfPol.attributes.stormCtrlAction == "drop" + - nm_update_storm_control_policy is changed + - nm_update_storm_control_policy.current.0.stormctrlIfPol.attributes.name == "ansible_storm_control_policy_1" + - nm_update_storm_control_policy.current.0.stormctrlIfPol.attributes.descr == "Updated description for first ansible Storm Control policy" + - nm_update_storm_control_policy.current.0.stormctrlIfPol.attributes.rate == "50.000000" + - nm_update_storm_control_policy.current.0.stormctrlIfPol.attributes.burstRate == "75.000000" + - nm_update_storm_control_policy.current.0.stormctrlIfPol.attributes.ratePps == "unspecified" + - nm_update_storm_control_policy.current.0.stormctrlIfPol.attributes.burstPps == "unspecified" + - nm_update_storm_control_policy.current.0.stormctrlIfPol.attributes.stormCtrlAction == "drop" + - nm_udpate_storm_control_policy_idempotency is not changed + - nm_udpate_storm_control_policy_idempotency.current.0.stormctrlIfPol.attributes.name == "ansible_storm_control_policy_1" + - nm_udpate_storm_control_policy_idempotency.current.0.stormctrlIfPol.attributes.descr == "Updated description for first ansible Storm Control policy" + - nm_udpate_storm_control_policy_idempotency.current.0.stormctrlIfPol.attributes.rate == "50.000000" + - nm_udpate_storm_control_policy_idempotency.current.0.stormctrlIfPol.attributes.burstRate == "75.000000" + - nm_udpate_storm_control_policy_idempotency.current.0.stormctrlIfPol.attributes.ratePps == "unspecified" + - nm_udpate_storm_control_policy_idempotency.current.0.stormctrlIfPol.attributes.burstPps == "unspecified" + - nm_udpate_storm_control_policy_idempotency.current.0.stormctrlIfPol.attributes.stormCtrlAction == "drop" + + # DELETE STORM CONTROL POLICY + - name: Remove Storm Control policy (check_mode) + cisco.aci.aci_interface_policy_storm_control: &storm_control_policy_absent + <<: *aci_interface_policy_storm_control_update + state: absent + check_mode: true + register: cm_remove_storm_control_policy + + - name: Remove Storm Control policy (normal_mode) + cisco.aci.aci_interface_policy_storm_control: + <<: *storm_control_policy_absent + register: nm_remove_storm_control_policy + + - name: Remove Storm Control policy - testing idempotency + cisco.aci.aci_interface_policy_storm_control: + <<: *storm_control_policy_absent + register: nm_remove_storm_control_policy_idempotency + + - name: Asserts deletion tasks + ansible.builtin.assert: + that: + - cm_remove_storm_control_policy is changed + - cm_remove_storm_control_policy.current == cm_remove_storm_control_policy.previous + - cm_remove_storm_control_policy.proposed == {} + - nm_remove_storm_control_policy is changed + - nm_remove_storm_control_policy.previous != [] + - nm_remove_storm_control_policy.proposed == {} + - nm_remove_storm_control_policy.current == [] + - nm_remove_storm_control_policy_idempotency is not changed + - nm_remove_storm_control_policy_idempotency.previous == [] + - nm_remove_storm_control_policy_idempotency.current == [] + + # CLEAN ENVIRONMENT BEFORE ENDING TESTS + - name: Remove all ansible Storm Control Policies - cleanup before ending tests + cisco.aci.aci_interface_policy_storm_control: + <<: *caci_storm_control_policies_cleanup + loop: + - ansible_storm_control_policy_1 + - ansible_storm_control_policy_2 + - ansible_storm_control_policy_3 + - ansible_storm_control_policy_4 diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_interface_selector_to_switch_policy_leaf_profile/tasks/main.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_interface_selector_to_switch_policy_leaf_profile/tasks/main.yml index 099b2eed9..4b5c32455 100644 --- a/ansible_collections/cisco/aci/tests/integration/targets/aci_interface_selector_to_switch_policy_leaf_profile/tasks/main.yml +++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_interface_selector_to_switch_policy_leaf_profile/tasks/main.yml @@ -4,12 +4,12 @@ # GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) - name: Test that we have an ACI APIC host, ACI username and ACI password - fail: + ansible.builtin.fail: msg: 'Please define the following variables: aci_hostname, aci_username and aci_password.' when: aci_hostname is not defined or aci_username is not defined or aci_password is not defined - name: Verify Cloud and Non-Cloud Sites in use. - include_tasks: ../../../../../../integration/targets/aci_cloud_provider/tasks/main.yml + ansible.builtin.include_tasks: ../../../../../../integration/targets/aci_cloud_provider/tasks/main.yml - name: Execute tasks only for non-cloud sites when: query_cloud.current == [] # This condition will execute only non-cloud sites @@ -83,7 +83,7 @@ # TODO: also test for errors - name: present assertions - assert: + ansible.builtin.assert: that: - intftoleaf_check_mode_present is changed - intftoleaf_present is changed @@ -101,7 +101,7 @@ register: binding_query1 - name: query 1 assertions - assert: + ansible.builtin.assert: that: - binding_query1 is not changed - binding_query1.current | length >= 1 @@ -121,7 +121,7 @@ register: binding_query2 - name: query 2 assertions - assert: + ansible.builtin.assert: that: - binding_query2 is not changed - binding_query2.current | length >= 1 @@ -153,7 +153,7 @@ register: intftoleaf_absent_missing_param - name: absent assertions - assert: + ansible.builtin.assert: that: - intftoleaf_check_mode_absent is changed - intftoleaf_check_mode_absent.previous != [] diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_key_policy/aliases b/ansible_collections/cisco/aci/tests/integration/targets/aci_key_policy/aliases new file mode 100644 index 000000000..209b793f9 --- /dev/null +++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_key_policy/aliases @@ -0,0 +1,2 @@ +# No ACI simulator yet, so not enabled +# unsupported diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_key_policy/tasks/main.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_key_policy/tasks/main.yml new file mode 100644 index 000000000..db44b6719 --- /dev/null +++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_key_policy/tasks/main.yml @@ -0,0 +1,153 @@ +# Test code for the ACI modules +# Copyright: (c) 2023, Gaspard Micol (@gmicol) + +# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) + +- name: Test that we have an ACI APIC host, ACI username and ACI password + ansible.builtin.fail: + msg: 'Please define the following variables: aci_hostname, aci_username and aci_password.' + when: aci_hostname is not defined or aci_username is not defined or aci_password is not defined + +- name: Set vars + ansible.builtin.set_fact: + aci_info: &aci_info + host: "{{ aci_hostname }}" + username: "{{ aci_username }}" + password: "{{ aci_password }}" + validate_certs: '{{ aci_validate_certs | default(false) }}' + use_ssl: '{{ aci_use_ssl | default(true) }}' + use_proxy: '{{ aci_use_proxy | default(true) }}' + output_level: debug + +# CLEAN ENVIRONMENT +- name: Remove the ansible_tenant + cisco.aci.aci_tenant: &aci_tenant_absent + <<: *aci_info + tenant: ansible_tenant + state: absent + +- name: Verify Cloud and Non-Cloud Sites in use. + ansible.builtin.include_tasks: ../../../../../../integration/targets/aci_cloud_provider/tasks/main.yml + +- name: Execute tasks only for non-cloud sites + when: query_cloud.current == [] # This condition will execute only non-cloud sites + block: # block specifies execution of tasks within, based on conditions + - name: Add a new tenant + cisco.aci.aci_tenant: &aci_tenant_present + <<: *aci_info + tenant: ansible_tenant + description: Ansible tenant + state: present + + - name: Add a new Keychain policy + cisco.aci.aci_keychain_policy: + <<: *aci_info + tenant: ansible_tenant + keychain_policy: ansible_keychain_policy_1 + description: Keychain policy 1 for ansible_tenant tenant + state: present + + - name: Add a Key policy (check_mode) + cisco.aci.aci_key_policy: &aci_key_policy_present + <<: *aci_info + tenant: ansible_tenant + keychain_policy: ansible_keychain_policy_1 + id: 1 + description: Key policy 1 for ansible_tenant tenant + start_time: "2024-01-01 00:00:00" + end_time: "2026-01-01 00:00:00" + pre_shared_key: my_password + state: present + check_mode: true + register: cm_add_key_policy + + - name: Add a Key policy (normal_mode) + cisco.aci.aci_key_policy: + <<: *aci_key_policy_present + register: nm_add_key_policy + + - name: Add the first Key policy again - testing hidden key authentification + cisco.aci.aci_key_policy: + <<: *aci_key_policy_present + register: nm_add_key_policy_idempotency + + - name: Add a second Key policy (normal_mode) + cisco.aci.aci_key_policy: + <<: *aci_info + tenant: ansible_tenant + keychain_policy: ansible_keychain_policy_1 + id: 2 + description: Key policy 2 for ansible_tenant tenant + state: present + register: nm_add_key_policy_2 + + - name: Asserts for Key policys creation tasks + ansible.builtin.assert: + that: + - cm_add_key_policy is changed + - cm_add_key_policy.previous == [] + - cm_add_key_policy.current == [] + - nm_add_key_policy is changed + - nm_add_key_policy.current.0.fvKeyPol.attributes.id == "1" + - nm_add_key_policy.current.0.fvKeyPol.attributes.startTime == "2024-01-01T00:00:00.000+00:00" + - nm_add_key_policy.current.0.fvKeyPol.attributes.endTime == "2026-01-01T00:00:00.000+00:00" + - nm_add_key_policy_idempotency is changed + - nm_add_key_policy_2 is changed + - nm_add_key_policy_2.previous == [] + - nm_add_key_policy_2.current.0.fvKeyPol.attributes.id == "2" + - nm_add_key_policy_2.current.0.fvKeyPol.attributes.endTime == "infinite" + + - name: Query all Key policies + cisco.aci.aci_key_policy: + <<: *aci_info + state: query + register: query_all_key_policy + + - name: Query ansible_key_policy_1 + cisco.aci.aci_key_policy: + <<: *aci_key_policy_present + state: query + register: query_ansible_key_policy_1 + + - name: Asserts query tasks + ansible.builtin.assert: + that: + - query_all_key_policy is not changed + - query_all_key_policy.current|length >= 2 + - query_ansible_key_policy_1 is not changed + - query_ansible_key_policy_1.current.0.fvKeyPol.attributes.id == "1" + - query_ansible_key_policy_1.current.0.fvKeyPol.attributes.startTime == "2024-01-01T00:00:00.000+00:00" + - query_ansible_key_policy_1.current.0.fvKeyPol.attributes.endTime == "2026-01-01T00:00:00.000+00:00" + + - name: Remove Key policy (check_mode) + cisco.aci.aci_key_policy: &key_policy_absent + <<: *aci_key_policy_present + state: absent + check_mode: true + register: cm_remove_key_policy + + - name: Remove Key policy (normal_mode) + cisco.aci.aci_key_policy: + <<: *key_policy_absent + register: nm_remove_key_policy + + - name: Remove Key policy - testing idempotency + cisco.aci.aci_key_policy: + <<: *key_policy_absent + register: nm_remove_key_policy_idempotency + + - name: Asserts deletion tasks + ansible.builtin.assert: + that: + - cm_remove_key_policy is changed + - cm_remove_key_policy.proposed == {} + - nm_remove_key_policy is changed + - nm_remove_key_policy.previous != [] + - nm_remove_key_policy.method == "DELETE" + - nm_remove_key_policy_idempotency is not changed + - nm_remove_key_policy_idempotency.previous == [] + + - name: Remove the ansible_tenant - cleanup before ending tests + cisco.aci.aci_tenant: + <<: *aci_tenant_present + state: absent diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_keychain_policy/aliases b/ansible_collections/cisco/aci/tests/integration/targets/aci_keychain_policy/aliases new file mode 100644 index 000000000..209b793f9 --- /dev/null +++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_keychain_policy/aliases @@ -0,0 +1,2 @@ +# No ACI simulator yet, so not enabled +# unsupported diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_keychain_policy/tasks/main.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_keychain_policy/tasks/main.yml new file mode 100644 index 000000000..0a0356cf7 --- /dev/null +++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_keychain_policy/tasks/main.yml @@ -0,0 +1,135 @@ +# Test code for the ACI modules +# Copyright: (c) 2023, Gaspard Micol (@gmicol) + +# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) + +- name: Test that we have an ACI APIC host, ACI username and ACI password + ansible.builtin.fail: + msg: 'Please define the following variables: aci_hostname, aci_username and aci_password.' + when: aci_hostname is not defined or aci_username is not defined or aci_password is not defined + +- name: Set vars + ansible.builtin.set_fact: + aci_info: &aci_info + host: "{{ aci_hostname }}" + username: "{{ aci_username }}" + password: "{{ aci_password }}" + validate_certs: '{{ aci_validate_certs | default(false) }}' + use_ssl: '{{ aci_use_ssl | default(true) }}' + use_proxy: '{{ aci_use_proxy | default(true) }}' + output_level: debug + +# CLEAN ENVIRONMENT +- name: Remove the ansible_tenant + cisco.aci.aci_tenant: &aci_tenant_absent + <<: *aci_info + tenant: ansible_tenant + state: absent + +- name: Verify Cloud and Non-Cloud Sites in use. + ansible.builtin.include_tasks: ../../../../../../integration/targets/aci_cloud_provider/tasks/main.yml + +- name: Execute tasks only for non-cloud sites + when: query_cloud.current == [] # This condition will execute only non-cloud sites + block: # block specifies execution of tasks within, based on conditions + - name: Add a new tenant + cisco.aci.aci_tenant: &aci_tenant_present + <<: *aci_info + tenant: ansible_tenant + description: Ansible tenant + state: present + + - name: Add a Keychain policy (check_mode) + cisco.aci.aci_keychain_policy: &aci_keychain_policy_present + <<: *aci_info + tenant: ansible_tenant + keychain_policy: ansible_keychain_policy_1 + description: Keychain policy 1 for ansible_tenant tenant + state: present + check_mode: true + register: cm_add_keychain_policy + + - name: Add a Keychain policy (normal_mode) + cisco.aci.aci_keychain_policy: + <<: *aci_keychain_policy_present + register: nm_add_keychain_policy + + - name: Add the first Keychain policy again - testing idempotency + cisco.aci.aci_keychain_policy: + <<: *aci_keychain_policy_present + register: nm_add_keychain_policy_idempotency + + - name: Add a second Keychain policy (normal_mode) + cisco.aci.aci_keychain_policy: + <<: *aci_info + tenant: ansible_tenant + keychain_policy: ansible_keychain_policy_2 + description: Keychain policy 2 for ansible_tenant tenant + state: present + register: nm_add_keychain_policy_2 + + - name: Asserts for Keychain policys creation tasks + ansible.builtin.assert: + that: + - cm_add_keychain_policy is changed + - cm_add_keychain_policy.previous == [] + - cm_add_keychain_policy.current == [] + - nm_add_keychain_policy is changed + - nm_add_keychain_policy.current.0.fvKeyChainPol.attributes.name == "ansible_keychain_policy_1" + - nm_add_keychain_policy_idempotency is not changed + - nm_add_keychain_policy_2 is changed + - nm_add_keychain_policy_2.previous == [] + - nm_add_keychain_policy_2.current.0.fvKeyChainPol.attributes.name == "ansible_keychain_policy_2" + + - name: Query all Keychain policies + cisco.aci.aci_keychain_policy: + <<: *aci_info + state: query + register: query_all_keychain_policy + + - name: Query ansible_keychain_policy_1 + cisco.aci.aci_keychain_policy: + <<: *aci_keychain_policy_present + state: query + register: query_ansible_keychain_policy_1 + + - name: Asserts query tasks + ansible.builtin.assert: + that: + - query_all_keychain_policy is not changed + - query_all_keychain_policy.current|length >= 2 + - query_ansible_keychain_policy_1 is not changed + - query_ansible_keychain_policy_1.current.0.fvKeyChainPol.attributes.name == "ansible_keychain_policy_1" + + - name: Remove Keychain policy (check_mode) + cisco.aci.aci_keychain_policy: &keychain_policy_absent + <<: *aci_keychain_policy_present + state: absent + check_mode: true + register: cm_remove_keychain_policy + + - name: Remove Keychain policy (normal_mode) + cisco.aci.aci_keychain_policy: + <<: *keychain_policy_absent + register: nm_remove_keychain_policy + + - name: Remove Keychain policy - testing idempotency + cisco.aci.aci_keychain_policy: + <<: *keychain_policy_absent + register: nm_remove_keychain_policy_idempotency + + - name: Asserts deletion tasks + ansible.builtin.assert: + that: + - cm_remove_keychain_policy is changed + - cm_remove_keychain_policy.proposed == {} + - nm_remove_keychain_policy is changed + - nm_remove_keychain_policy.previous != [] + - nm_remove_keychain_policy.method == "DELETE" + - nm_remove_keychain_policy_idempotency is not changed + - nm_remove_keychain_policy_idempotency.previous == [] + + - name: Remove the ansible_tenant - cleanup before ending tests + cisco.aci.aci_tenant: + <<: *aci_tenant_present + state: absent diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_l2out/tasks/main.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_l2out/tasks/main.yml index f72831322..2fcafc985 100644 --- a/ansible_collections/cisco/aci/tests/integration/targets/aci_l2out/tasks/main.yml +++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_l2out/tasks/main.yml @@ -4,12 +4,12 @@ # GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) - name: Test that we have an ACI APIC host, ACI username and ACI password - fail: + ansible.builtin.fail: msg: 'Please define the following variables: aci_hostname, aci_username and aci_password.' when: aci_hostname is not defined or aci_username is not defined or aci_password is not defined - name: Set vars - set_fact: + ansible.builtin.set_fact: aci_info: &aci_info host: "{{ aci_hostname }}" username: "{{ aci_username }}" @@ -21,26 +21,26 @@ # CLEAN ENVIRONMENT - name: Remove the ansible_tenant - aci_tenant: + cisco.aci.aci_tenant: <<: *aci_info tenant: ansible_tenant state: absent - name: Verify Cloud and Non-Cloud Sites in use. - include_tasks: ../../../../../../integration/targets/aci_cloud_provider/tasks/main.yml + ansible.builtin.include_tasks: ../../../../../../integration/targets/aci_cloud_provider/tasks/main.yml - name: Execute tasks only for non-cloud sites when: query_cloud.current == [] # This condition will execute only non-cloud sites block: # block specifies execution of tasks within, based on conditions - name: Add a new tenant - aci_tenant: + cisco.aci.aci_tenant: <<: *aci_info tenant: ansible_tenant description: Ansible tenant state: present - name: Add a new L2Out - aci_l2out: + cisco.aci.aci_l2out: <<: *aci_info tenant: ansible_tenant l2out: ansible_l2out @@ -52,14 +52,14 @@ register: add_l2out - name: Verify add_l2out - assert: + ansible.builtin.assert: that: - add_l2out.current.0.l2extOut.attributes.dn == "uni/tn-ansible_tenant/l2out-ansible_l2out" - add_l2out.current.0.l2extOut.attributes.name == "ansible_l2out" - add_l2out.current.0.l2extOut.attributes.annotation == 'orchestrator:ansible' - name: Add the L2Out again - aci_l2out: + cisco.aci.aci_l2out: <<: *aci_info tenant: ansible_tenant l2out: ansible_l2out @@ -71,12 +71,12 @@ register: add_l2out_again - name: Verify add_l2out_again - assert: + ansible.builtin.assert: that: - add_l2out_again is not changed - name: Add a new L2Out - aci_l2out: + cisco.aci.aci_l2out: <<: *aci_info tenant: ansible_tenant l2out: ansible_l2out_2 @@ -88,13 +88,13 @@ register: add_l2out_2 - name: Verify add_l2out_2 - assert: + ansible.builtin.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: + cisco.aci.aci_l2out: <<: *aci_info tenant: ansible_tenant l2out: ansible_l2out @@ -102,26 +102,26 @@ register: query_l2out - name: Verify query_l2out - assert: + ansible.builtin.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: + cisco.aci.aci_l2out: <<: *aci_info tenant: ansible_tenant state: query register: query_l2out_all - name: Verify query_l2out_all - assert: + ansible.builtin.assert: that: - query_l2out_all is not changed - name: Remove the L2Out - aci_l2out: + cisco.aci.aci_l2out: <<: *aci_info tenant: ansible_tenant l2out: ansible_l2out @@ -129,7 +129,7 @@ register: remove_l2out - name: Verify remove_l2out - assert: + ansible.builtin.assert: that: - remove_l2out is changed - remove_l2out.previous.0.l2extOut.attributes.dn == "uni/tn-ansible_tenant/l2out-ansible_l2out" diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_l2out_extepg/tasks/main.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_l2out_extepg/tasks/main.yml index 39feb5216..9b2698498 100644 --- a/ansible_collections/cisco/aci/tests/integration/targets/aci_l2out_extepg/tasks/main.yml +++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_l2out_extepg/tasks/main.yml @@ -4,12 +4,12 @@ # GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) - name: Test that we have an ACI APIC host, ACI username and ACI password - fail: + ansible.builtin.fail: msg: 'Please define the following variables: aci_hostname, aci_username and aci_password.' when: aci_hostname is not defined or aci_username is not defined or aci_password is not defined - name: Set vars - set_fact: + ansible.builtin.set_fact: aci_info: &aci_info host: "{{ aci_hostname }}" username: "{{ aci_username }}" @@ -21,26 +21,26 @@ # CLEAN ENVIRONMENT - name: Remove the ansible_tenant - aci_tenant: + cisco.aci.aci_tenant: <<: *aci_info tenant: ansible_tenant state: absent - name: Verify Cloud and Non-Cloud Sites in use. - include_tasks: ../../../../../../integration/targets/aci_cloud_provider/tasks/main.yml + ansible.builtin.include_tasks: ../../../../../../integration/targets/aci_cloud_provider/tasks/main.yml - name: Execute tasks only for non-cloud sites when: query_cloud.current == [] # This condition will execute only non-cloud sites block: # block specifies execution of tasks within, based on conditions - name: Add a new tenant - aci_tenant: + cisco.aci.aci_tenant: <<: *aci_info tenant: ansible_tenant description: Ansible tenant state: present - name: Add New L2Out - aci_l2out: + cisco.aci.aci_l2out: <<: *aci_info tenant: ansible_tenant l2out: ansible_l2out @@ -52,7 +52,7 @@ register: add_l2out - name: Add another L2Out - aci_l2out: + cisco.aci.aci_l2out: <<: *aci_info tenant: ansible_tenant l2out: ansible_l2out_2 @@ -64,7 +64,7 @@ register: add_l2out_2 - name: Add L2 external end point group - aci_l2out_extepg: + cisco.aci.aci_l2out_extepg: <<: *aci_info tenant: ansible_tenant l2out: ansible_l2out @@ -75,13 +75,13 @@ register: l2extepg - name: Verify l2extepg - assert: + ansible.builtin.assert: that: - l2extepg.current.0.l2extInstP.attributes.dn == "uni/tn-ansible_tenant/l2out-ansible_l2out/instP-ansible_extepg" - l2extepg.current.0.l2extInstP.attributes.annotation == 'orchestrator:ansible' - name: Add L2 external end point group again - aci_l2out_extepg: + cisco.aci.aci_l2out_extepg: <<: *aci_info tenant: ansible_tenant l2out: ansible_l2out @@ -92,13 +92,13 @@ register: l2extepg_again - name: Verify l2extepg_again - assert: + ansible.builtin.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: + cisco.aci.aci_l2out_extepg: <<: *aci_info tenant: ansible_tenant l2out: ansible_l2out_2 @@ -110,12 +110,12 @@ register: l2extepg_2 - name: Verify l2extepg_2 - assert: + ansible.builtin.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: + cisco.aci.aci_l2out_extepg: <<: *aci_info tenant: ansible_tenant l2out: ansible_l2out @@ -124,30 +124,30 @@ register: query_l2extepg - name: Query all L2 external epg in a tenant - aci_l2out_extepg: + cisco.aci.aci_l2out_extepg: <<: *aci_info tenant: ansible_tenant state: query register: query_all_in_tenant - name: Verify query_all_in_tenant - assert: + ansible.builtin.assert: that: - query_all_in_tenant is not changed - name: Query all L2 external epgs - aci_l2out_extepg: + cisco.aci.aci_l2out_extepg: <<: *aci_info state: query register: query_all - name: Verify query_all - assert: + ansible.builtin.assert: that: - query_all is not changed - name: Remove L2 external end point group - aci_l2out_extepg: + cisco.aci.aci_l2out_extepg: <<: *aci_info tenant: ansible_tenant l2out: ansible_l2out @@ -157,7 +157,7 @@ register: remove_l2extepg - name: Verify remove_l2extepg - assert: + ansible.builtin.assert: that: - remove_l2extepg is changed - remove_l2extepg.previous.0.l2extInstP.attributes.dn == "uni/tn-ansible_tenant/l2out-ansible_l2out/instP-ansible_extepg" \ No newline at end of file diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_l2out_extepg_to_contract/tasks/main.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_l2out_extepg_to_contract/tasks/main.yml index 25c211f6b..0781aa682 100644 --- a/ansible_collections/cisco/aci/tests/integration/targets/aci_l2out_extepg_to_contract/tasks/main.yml +++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_l2out_extepg_to_contract/tasks/main.yml @@ -4,12 +4,12 @@ # GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) - name: Test that we have an ACI APIC host, ACI username and ACI password - fail: + ansible.builtin.fail: msg: 'Please define the following variables: aci_hostname, aci_username and aci_password.' when: aci_hostname is not defined or aci_username is not defined or aci_password is not defined - name: Set vars - set_fact: + ansible.builtin.set_fact: aci_info: &aci_info host: "{{ aci_hostname }}" username: "{{ aci_username }}" @@ -21,26 +21,26 @@ # CLEAN ENVIRONMENT - name: Remove the ansible_tenant - aci_tenant: + cisco.aci.aci_tenant: <<: *aci_info tenant: ansible_tenant state: absent - name: Verify Cloud and Non-Cloud Sites in use. - include_tasks: ../../../../../../integration/targets/aci_cloud_provider/tasks/main.yml + ansible.builtin.include_tasks: ../../../../../../integration/targets/aci_cloud_provider/tasks/main.yml - name: Execute tasks only for non-cloud sites when: query_cloud.current == [] # This condition will execute only non-cloud sites block: # block specifies execution of tasks within, based on conditions - name: Add a new tenant - aci_tenant: + cisco.aci.aci_tenant: <<: *aci_info tenant: ansible_tenant description: Ansible tenant state: present - name: Add New L2Out - aci_l2out: + cisco.aci.aci_l2out: <<: *aci_info tenant: ansible_tenant l2out: ansible_l2out @@ -52,7 +52,7 @@ register: add_l2out - name: Add another L2Out - aci_l2out: + cisco.aci.aci_l2out: <<: *aci_info tenant: ansible_tenant l2out: ansible_l2out_2 @@ -64,7 +64,7 @@ register: add_l2out_2 - name: Add L2 external end point group - aci_l2out_extepg: + cisco.aci.aci_l2out_extepg: <<: *aci_info tenant: ansible_tenant l2out: ansible_l2out @@ -75,13 +75,13 @@ register: l2extepg - name: Verify l2extepg - assert: + ansible.builtin.assert: that: - l2extepg is changed - l2extepg.current.0.l2extInstP.attributes.dn == "uni/tn-ansible_tenant/l2out-ansible_l2out/instP-ansible_extepg" - name: Add L2 external end point group again - aci_l2out_extepg: + cisco.aci.aci_l2out_extepg: <<: *aci_info tenant: ansible_tenant l2out: ansible_l2out @@ -92,13 +92,13 @@ register: l2extepg_again - name: Verify l2extepg_again - assert: + ansible.builtin.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: + cisco.aci.aci_l2out_extepg: <<: *aci_info tenant: ansible_tenant l2out: ansible_l2out_2 @@ -110,13 +110,13 @@ register: l2extepg_2 - name: Verify l2extepg_2 - assert: + ansible.builtin.assert: that: - l2extepg_2 is changed - l2extepg_2.current.0.l2extInstP.attributes.dn == "uni/tn-ansible_tenant/l2out-ansible_l2out_2/instP-ansible_extepg_2" - name: Bind External End Point Groups to Contracts - aci_l2out_extepg_to_contract: + cisco.aci.aci_l2out_extepg_to_contract: <<: *aci_info tenant: ansible_tenant l2out: ansible_l2out @@ -127,14 +127,14 @@ register: bind_extepg_provider_contract - name: Verify bind_extepg_provider_contract - assert: + ansible.builtin.assert: that: - bind_extepg_provider_contract is changed - bind_extepg_provider_contract.current.0.fvRsProv.attributes.dn == "uni/tn-ansible_tenant/l2out-ansible_l2out/instP-ansible_extepg/rsprov-ansible_contract" - bind_extepg_provider_contract.current.0.fvRsProv.attributes.annotation == 'orchestrator:ansible' - name: Bind second External End Point Groups to Contracts - aci_l2out_extepg_to_contract: + cisco.aci.aci_l2out_extepg_to_contract: <<: *aci_info tenant: ansible_tenant l2out: ansible_l2out_2 @@ -145,13 +145,13 @@ register: bind_extepg_provider_contract - name: Verify bind_extepg_provider_contract - assert: + ansible.builtin.assert: that: - bind_extepg_provider_contract is changed - bind_extepg_provider_contract.current.0.fvRsProv.attributes.dn == "uni/tn-ansible_tenant/l2out-ansible_l2out_2/instP-ansible_extepg_2/rsprov-ansible_contract2" - name: Query the External End Point Groups - aci_l2out_extepg_to_contract: + cisco.aci.aci_l2out_extepg_to_contract: <<: *aci_info tenant: ansible_tenant l2out: ansible_l2out @@ -162,26 +162,26 @@ register: query_extepg - name: Verify query_extepg - assert: + ansible.builtin.assert: that: - query_extepg is not changed - query_extepg.current.0.fvRsProv.attributes.dn == "uni/tn-ansible_tenant/l2out-ansible_l2out/instP-ansible_extepg/rsprov-ansible_contract" - name: Query all the External End Point Groups - aci_l2out_extepg_to_contract: + cisco.aci.aci_l2out_extepg_to_contract: <<: *aci_info contract_type: provider state: query register: query_all - name: Verify query_extepg - assert: + ansible.builtin.assert: that: - query_extepg is not changed - query_extepg.current | length > 0 - name: Remove existing contract to External End Point Groups - aci_l2out_extepg_to_contract: + cisco.aci.aci_l2out_extepg_to_contract: <<: *aci_info tenant: ansible_tenant l2out: ansible_l2out @@ -192,14 +192,14 @@ register: remove_contract_extepg - name: Verify remove_contract_extepg - assert: + ansible.builtin.assert: that: - remove_contract_extepg is changed - remove_contract_extepg.current == [] - remove_contract_extepg.previous.0.fvRsProv.attributes.dn == "uni/tn-ansible_tenant/l2out-ansible_l2out/instP-ansible_extepg/rsprov-ansible_contract" - name: Bind External End Point Groups to Contracts - aci_l2out_extepg_to_contract: + cisco.aci.aci_l2out_extepg_to_contract: <<: *aci_info tenant: ansible_tenant l2out: ansible_l2out @@ -212,7 +212,7 @@ register: bind_extepg_consumer_contract - name: Verify bind_extepg_consumer_contract - assert: + ansible.builtin.assert: that: - bind_extepg_consumer_contract is not changed - bind_extepg_consumer_contract.msg == "the 'provider_match' is only configurable for Provided Contracts" \ No newline at end of file diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_l2out_logical_interface_path/tasks/main.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_l2out_logical_interface_path/tasks/main.yml index a573668de..62440ce64 100644 --- a/ansible_collections/cisco/aci/tests/integration/targets/aci_l2out_logical_interface_path/tasks/main.yml +++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_l2out_logical_interface_path/tasks/main.yml @@ -4,12 +4,12 @@ # GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) - name: Test that we have an ACI APIC host, ACI username and ACI password - fail: + ansible.builtin.fail: msg: 'Please define the following variables: aci_hostname, aci_username and aci_password.' when: aci_hostname is not defined or aci_username is not defined or aci_password is not defined - name: Set vars - set_fact: + ansible.builtin.set_fact: aci_info: &aci_info host: "{{ aci_hostname }}" username: "{{ aci_username }}" @@ -26,7 +26,7 @@ state: absent - name: Verify Cloud and Non-Cloud Sites in use. - include_tasks: ../../../../../../integration/targets/aci_cloud_provider/tasks/main.yml + ansible.builtin.include_tasks: ../../../../../../integration/targets/aci_cloud_provider/tasks/main.yml - name: Execute tasks only for non-cloud sites when: query_cloud.current == [] # This condition will execute only non-cloud sites @@ -83,7 +83,7 @@ register: nm_path_to_intfp - name: Verify path to interface profile - assert: + ansible.builtin.assert: that: - cm_path_to_intfp is changed - nm_path_to_intfp is changed @@ -111,7 +111,7 @@ register: third_path - name: Verify path to interface profile - assert: + ansible.builtin.assert: that: - second_path is changed - third_path is changed @@ -166,7 +166,7 @@ register: query_path - name: Verify query - assert: + ansible.builtin.assert: that: - query_all is not changed - query_all.current.0.l2extLIfP.children | length >= 3 @@ -192,7 +192,7 @@ register: rm_non_existing - name: Verify remove path - assert: + ansible.builtin.assert: that: - cm_rm_path is changed - nm_rm_path is changed diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_l2out_logical_interface_profile/tasks/main.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_l2out_logical_interface_profile/tasks/main.yml index 7e28c1cd4..86e6548f8 100644 --- a/ansible_collections/cisco/aci/tests/integration/targets/aci_l2out_logical_interface_profile/tasks/main.yml +++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_l2out_logical_interface_profile/tasks/main.yml @@ -5,7 +5,7 @@ # SET VARS - name: Set vars - set_fact: + ansible.builtin.set_fact: aci_info: &aci_info host: '{{ aci_hostname }}' username: '{{ aci_username }}' @@ -23,7 +23,7 @@ state: absent - name: Verify Cloud and Non-Cloud Sites in use. - include_tasks: ../../../../../../integration/targets/aci_cloud_provider/tasks/main.yml + ansible.builtin.include_tasks: ../../../../../../integration/targets/aci_cloud_provider/tasks/main.yml - name: Execute tasks only for non-cloud sites when: query_cloud.current == [] # This condition will execute only non-cloud sites @@ -65,7 +65,7 @@ register: nm_add_intf - name: Verify nm_add_intf - assert: + ansible.builtin.assert: that: - cm_add_intf is changed - nm_add_intf is changed @@ -79,7 +79,7 @@ register: add_intf_again - name: Verify add_intf_again - assert: + ansible.builtin.assert: that: - add_intf_again is not changed @@ -100,7 +100,7 @@ register: query_all_profiles - name: Verify query_all_profiles - assert: + ansible.builtin.assert: that: - query_all_profiles is not changed - query_all_profiles.current.0.l2extLNodeP.children | length > 1 @@ -113,7 +113,7 @@ register: query_spec_profile - name: Verify query_spec_profile - assert: + ansible.builtin.assert: that: - query_spec_profile is not changed - query_spec_profile.current|length == 1 @@ -129,7 +129,7 @@ register: query_nonexist_profile - name: Verify query_nonexist_profile - assert: + ansible.builtin.assert: that: - query_nonexist_profile is not changed - query_nonexist_profile.current == [] @@ -142,7 +142,7 @@ register: remove_profile - name: Verify remove_profile - assert: + ansible.builtin.assert: that: - remove_profile is changed - remove_profile.current == [] @@ -154,7 +154,7 @@ register: remove_nonexist_profile - name: Verify remove_nonexist_profile - assert: + ansible.builtin.assert: that: - remove_nonexist_profile is not changed - remove_nonexist_profile.current == [] diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_l2out_logical_node_profile/tasks/main.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_l2out_logical_node_profile/tasks/main.yml index 82b4aaac5..d8b8f8b21 100644 --- a/ansible_collections/cisco/aci/tests/integration/targets/aci_l2out_logical_node_profile/tasks/main.yml +++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_l2out_logical_node_profile/tasks/main.yml @@ -4,12 +4,12 @@ # GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) - name: Test that we have an ACI APIC host, ACI username and ACI password - fail: + ansible.builtin.fail: msg: 'Please define the following variables: aci_hostname, aci_username and aci_password.' when: aci_hostname is not defined or aci_username is not defined or aci_password is not defined - name: Set vars - set_fact: + ansible.builtin.set_fact: aci_info: &aci_info host: "{{ aci_hostname }}" username: "{{ aci_username }}" @@ -27,7 +27,7 @@ state: absent - name: Verify Cloud and Non-Cloud Sites in use. - include_tasks: ../../../../../../integration/targets/aci_cloud_provider/tasks/main.yml + ansible.builtin.include_tasks: ../../../../../../integration/targets/aci_cloud_provider/tasks/main.yml - name: Execute tasks only for non-cloud sites when: query_cloud.current == [] # This condition will execute only non-cloud sites @@ -74,7 +74,7 @@ register: nm_add_second_node_profile - name: Verify add_node_profile - assert: + ansible.builtin.assert: that: - cm_add_node_profile is changed - nm_add_node_profile is changed @@ -121,7 +121,7 @@ register: nm_query_all_node_profiles - name: Verify query_node_profile - assert: + ansible.builtin.assert: that: - cm_query_node_profile is not changed - nm_query_node_profile is not changed @@ -166,7 +166,7 @@ register: nm_remove_second_node_profile - name: Verify remove_node_profile - assert: + ansible.builtin.assert: that: - cm_remove_node_profile is changed - cm_remove_second_node_profile is changed diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_l3out/tasks/main.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_l3out/tasks/main.yml index 65474048c..352f9d5b4 100644 --- a/ansible_collections/cisco/aci/tests/integration/targets/aci_l3out/tasks/main.yml +++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_l3out/tasks/main.yml @@ -1,15 +1,16 @@ # Test code for the ACI modules # Copyright: (c) 2023, Gaspard Micol (@gmicol) +# Copyright: (c) 2023, Akini Ross (@akinross) # GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) - name: Test that we have an ACI APIC host, ACI username and ACI password - fail: + ansible.builtin.fail: msg: 'Please define the following variables: aci_hostname, aci_username and aci_password.' when: aci_hostname is not defined or aci_username is not defined or aci_password is not defined - name: Set vars - set_fact: + ansible.builtin.set_fact: aci_info: &aci_info host: "{{ aci_hostname }}" username: "{{ aci_username }}" @@ -18,29 +19,36 @@ use_ssl: '{{ aci_use_ssl | default(true) }}' use_proxy: '{{ aci_use_proxy | default(true) }}' output_level: debug - + +- name: Query system information + cisco.aci.aci_system: + <<: *aci_info + id: 1 + state: query + register: version + # CLEAN ENVIRONMENT - name: Remove the ansible_tenant - aci_tenant: + cisco.aci.aci_tenant: <<: *aci_info tenant: ansible_tenant state: absent - name: Verify Cloud and Non-Cloud Sites in use. - include_tasks: ../../../../../../integration/targets/aci_cloud_provider/tasks/main.yml + ansible.builtin.include_tasks: ../../../../../../integration/targets/aci_cloud_provider/tasks/main.yml - name: Execute tasks only for non-cloud sites when: query_cloud.current == [] # This condition will execute only non-cloud sites block: # block specifies execution of tasks within, based on conditions - name: Add a new tenant - aci_tenant: + cisco.aci.aci_tenant: <<: *aci_info tenant: ansible_tenant description: Ansible tenant state: present - name: Remove the ansible_l3out - aci_l3out: &aci_l3out_absent + cisco.aci.aci_l3out: &aci_l3out_absent <<: *aci_info tenant: ansible_tenant name: ansible_l3out @@ -50,7 +58,7 @@ state: absent - name: Remove the second ansible_l3out - aci_l3out: &aci_l3out_2_absent + cisco.aci.aci_l3out: &aci_l3out_2_absent <<: *aci_info tenant: ansible_tenant name: ansible_l3out_2 @@ -61,30 +69,30 @@ state: absent - name: Add a new L3Out (check_mode) - aci_l3out: &aci_l3out_present + cisco.aci.aci_l3out: &aci_l3out_present <<: *aci_l3out_absent state: present check_mode: true register: cm_add_l3out - name: Add a new L3Out (normal_mode) - aci_l3out: + cisco.aci.aci_l3out: <<: *aci_l3out_present register: nm_add_l3out - name: create L3Out again - testing idempotency - aci_l3out: + cisco.aci.aci_l3out: <<: *aci_l3out_present register: create_idempotency - name: Add the second ansible_l3out - aci_l3out: + cisco.aci.aci_l3out: <<: *aci_l3out_2_absent state: present register: cm_add_l3out_2 - name: asserts for l3out creation tasks - assert: + ansible.builtin.assert: that: - cm_add_l3out is changed - cm_add_l3out.previous == [] @@ -95,26 +103,26 @@ - create_idempotency is not changed - name: Add export and import to route_control - aci_l3out: + cisco.aci.aci_l3out: <<: *aci_l3out_present route_control: [ import, export ] register: nm_add_l3out_import_export - name: Add export to route_control - aci_l3out: + cisco.aci.aci_l3out: <<: *aci_l3out_present route_control: export register: nm_add_l3out_export - name: Add just import to route_control - testing failure message - aci_l3out: + cisco.aci.aci_l3out: <<: *aci_l3out_present route_control: import register: nm_add_l3out_import_error ignore_errors: true - name: asserts for l3out route control tasks - assert: + ansible.builtin.assert: that: - nm_add_l3out_import_export is changed - nm_add_l3out_import_export.current.0.l3extOut.attributes.enforceRtctrl == "export,import" @@ -123,26 +131,44 @@ - nm_add_l3out_import_error.msg == "The route_control parameter is invalid{{':'}} allowed options are export or import,export only" - name: Add BGP protocol - aci_l3out: + cisco.aci.aci_l3out: <<: *aci_l3out_present l3protocol: bgp register: nm_add_l3out_bgp - name: Add BGP protocol again - testing L3protocol changes - aci_l3out: + cisco.aci.aci_l3out: <<: *aci_l3out_present l3protocol: bgp register: nm_add_l3out_bgp_again + - name: Remove OSPF protocol - testing L3protocol changes + cisco.aci.aci_l3out: &aci_l3out_remove_ospf + <<: *aci_l3out_2_absent + l3protocol: [ eigrp, pim ] + asn: 1 + state: present + register: nm_add_l3out_bgp_without_ospf + + - name: Remove OSPF protocol again - testing L3protocol changes + cisco.aci.aci_l3out: + <<: *aci_l3out_remove_ospf + register: nm_add_l3out_bgp_without_ospf_again + - name: Add PIM protocol, ospf_spec and asn - testing warning message for asn - aci_l3out: + aci_l3out: &aci_l3out_add_pim <<: *aci_l3out_present l3protocol: pim asn: 1 register: nm_add_l3out_pim + - name: Add PIM protocol, ospf_spec and asn again - testing warning message for asn + aci_l3out: + <<: *aci_l3out_add_pim + register: nm_add_l3out_pim_again + - name: Add EIGRP protocol - testing warning message for OSPF spec - aci_l3out: + cisco.aci.aci_l3out: &aci_l3out_add_eigrp <<: *aci_l3out_present l3protocol: eigrp asn: 1 @@ -150,8 +176,13 @@ description: OSPF warnings message works register: nm_add_l3out_eigrp - - name: remove asn - testing failure message + - name: Add EIGRP protocol again - testing warning message for OSPF spec aci_l3out: + <<: *aci_l3out_add_eigrp + register: nm_add_l3out_eigrp_again + + - name: remove asn - testing failure message + cisco.aci.aci_l3out: <<: *aci_l3out_present l3protocol: eigrp asn: null @@ -159,26 +190,30 @@ ignore_errors: true - name: remove protocol - testing static protocol - aci_l3out: + cisco.aci.aci_l3out: <<: *aci_l3out_present l3protocol: static register: nm_remove_l3protocol - name: asserts for l3out protocols tasks - assert: + ansible.builtin.assert: that: - nm_add_l3out_bgp is changed - - nm_add_l3out_bgp_again is changed + - nm_add_l3out_bgp_again is not changed + - nm_add_l3out_bgp_without_ospf is changed + - nm_add_l3out_bgp_without_ospf_again is not changed - nm_add_l3out_pim is changed - nm_add_l3out_pim.warnings.0 == "Parameter 'asn' is only applicable when l3protocol is 'eigrp'. The ASN will be ignored" + - nm_add_l3out_pim_again is not changed - nm_add_l3out_eigrp is changed - nm_add_l3out_eigrp.current.0.l3extOut.children.0.eigrpExtP.attributes.asn == "1" - nm_add_l3out_eigrp.warnings.0 == "Parameter 'ospf' is only applicable when l3protocol is 'ospf'. The OPSF specifications will be ignored" + - nm_add_l3out_eigrp_again is not changed - add_l3out_without_asn.msg == "Parameter 'asn' is required when l3protocol is 'eigrp'" - nm_remove_l3protocol is changed - name: Add OSPF protocol - aci_l3out: + cisco.aci.aci_l3out: <<: *aci_l3out_present l3protocol: ospf ospf: @@ -191,7 +226,7 @@ register: nm_add_l3out_ospf - name: asserts for l3out OSPF protocol tasks - assert: + ansible.builtin.assert: that: - nm_add_l3out_ospf is changed - nm_add_l3out_ospf.current.0.l3extOut.children.2.ospfExtP.attributes.areaCost == "1" @@ -202,58 +237,58 @@ - nm_add_l3out_ospf.current.0.l3extOut.children.2.ospfExtP.attributes.multipodInternal == "no" - name: get ansible_l3out - aci_l3out: + cisco.aci.aci_l3out: <<: *aci_l3out_present state: query register: get_l3out - name: get all l3outs in ansible_tenant - aci_l3out: + cisco.aci.aci_l3out: <<: *aci_info tenant: ansible_tenant state: query register: get_all_l3out_ansible_tenant - name: get all l3outs - aci_l3out: + cisco.aci.aci_l3out: <<: *aci_info state: query register: get_all_l3out - name: asserts query tasks - assert: + ansible.builtin.assert: that: - get_l3out is not changed - '"rsp-subtree=full&rsp-subtree-class=bgpExtP,eigrpExtP,l3extRsEctx,l3extRsL3DomAtt,ospfExtP,pimExtP" in get_l3out.filter_string' - '"tn-ansible_tenant/out-ansible_l3out.json" in get_l3out.url' - get_all_l3out_ansible_tenant is not changed - - '"ospfExtP" in get_all_l3out_ansible_tenant.current.0.fvTenant.children.0.l3extOut.children.2' + - '"pimExtP" in get_all_l3out_ansible_tenant.current.0.fvTenant.children.0.l3extOut.children.0' + - '"eigrpExtP" in get_all_l3out_ansible_tenant.current.0.fvTenant.children.0.l3extOut.children.1' - '"ospfExtP" in get_all_l3out_ansible_tenant.current.0.fvTenant.children.1.l3extOut.children.2' - - '"bgpExtP" in get_all_l3out_ansible_tenant.current.0.fvTenant.children.1.l3extOut.children.3' - get_all_l3out is not changed - get_all_l3out.current | length >= 2 - name: delete l3out (check_mode) - aci_l3out: + cisco.aci.aci_l3out: <<: *aci_l3out_present state: absent check_mode: true register: delete_cm - name: delete l3out (normal_mode) - aci_l3out: + cisco.aci.aci_l3out: <<: *aci_l3out_present state: absent register: delete_l3out - name: delete l3out again - testing idempotency - aci_l3out: + cisco.aci.aci_l3out: <<: *aci_l3out_present state: absent register: delete_idempotency - name: asserts for deletion tasks - assert: + ansible.builtin.assert: that: - delete_cm is changed - delete_cm.proposed == {} @@ -263,8 +298,120 @@ - delete_idempotency is not changed - delete_idempotency.previous == [] + - name: Execute tasks only for ACI v5+ because SR-MPLS L3Out is not supported lower versions + when: version.current.0.topSystem.attributes.version is version('5', '>=') + block: + + - name: Add a SR-MPLS l3out + cisco.aci.aci_l3out: &aci_sr_mpls_l3out + <<: *aci_info + tenant: ansible_tenant + name: ansible_sr_mpls_l3out + domain: ansible_dom + vrf: ansible_vrf + mpls: "yes" + state: present + register: add_sr_mpls_l3out + + - name: Add a SR-MPLS l3out again + cisco.aci.aci_l3out: + <<: *aci_sr_mpls_l3out + register: add_sr_mpls_l3out_again + + - name: Delete a SR-MPLS l3out + cisco.aci.aci_l3out: + <<: *aci_sr_mpls_l3out + state: absent + register: delete_sr_mpls_l3out + + - name: Ensure infra SR-MPLS l3out does not exist + cisco.aci.aci_l3out: &aci_infra_sr_mpls_l3out_absent + <<: *aci_info + tenant: infra + name: ansible_infra_sr_mpls_l3out + mpls: "yes" + state: absent + + - name: Add a infra SR-MPLS l3out (error) + cisco.aci.aci_l3out: &aci_infra_sr_mpls_l3out + <<: *aci_info + tenant: infra + name: ansible_infra_sr_mpls_l3out + domain: ansible_dom + vrf: ansible_vrf + l3protocol: ospf + mpls: "yes" + ignore_errors: true + register: err_infra_sr_mpls_l3out_no_bgp + + - name: Add a infra SR-MPLS l3out (error) + cisco.aci.aci_l3out: + <<: *aci_infra_sr_mpls_l3out + l3protocol: bgp + ignore_errors: true + register: err_infra_sr_mpls_l3out_no_overlay_1_vrf + + - name: Add a infra SR-MPLS l3out + cisco.aci.aci_l3out: + <<: *aci_infra_sr_mpls_l3out + vrf: overlay-1 + l3protocol: bgp + register: add_infra_sr_mpls_l3out + + - name: Add a infra SR-MPLS l3out again + cisco.aci.aci_l3out: + <<: *aci_infra_sr_mpls_l3out + vrf: overlay-1 + l3protocol: bgp + register: add_infra_sr_mpls_l3out_again + + - name: Delete a infra SR-MPLS l3out + cisco.aci.aci_l3out: + <<: *aci_infra_sr_mpls_l3out_absent + register: delete_infra_sr_mpls_l3out + + - name: Asserts SR-MPLS l3out + ansible.builtin.assert: + that: + - add_sr_mpls_l3out is changed + - add_sr_mpls_l3out.previous == [] + - add_sr_mpls_l3out.current.0.l3extOut.attributes.mplsEnabled == "yes" + - add_sr_mpls_l3out.current.0.l3extOut.attributes.name == "ansible_sr_mpls_l3out" + - add_sr_mpls_l3out.current.0.l3extOut.children.0.l3extRsL3DomAtt.attributes.tDn == "uni/l3dom-ansible_dom" + - add_sr_mpls_l3out.current.0.l3extOut.children.1.l3extRsEctx.attributes.tnFvCtxName == "ansible_vrf" + - add_sr_mpls_l3out_again is not changed + - delete_sr_mpls_l3out is changed + - delete_sr_mpls_l3out.previous.0.l3extOut.attributes.mplsEnabled == "yes" + - delete_sr_mpls_l3out.previous.0.l3extOut.attributes.name == "ansible_sr_mpls_l3out" + - delete_sr_mpls_l3out.previous.0.l3extOut.children.0.l3extRsL3DomAtt.attributes.tDn == "uni/l3dom-ansible_dom" + - delete_sr_mpls_l3out.previous.0.l3extOut.children.1.l3extRsEctx.attributes.tnFvCtxName == "ansible_vrf" + - delete_sr_mpls_l3out.current == [] + - add_infra_sr_mpls_l3out is changed + - add_infra_sr_mpls_l3out.previous == [] + - add_infra_sr_mpls_l3out.current.0.l3extOut.attributes.mplsEnabled == "yes" + - add_infra_sr_mpls_l3out.current.0.l3extOut.attributes.name == "ansible_infra_sr_mpls_l3out" + - add_infra_sr_mpls_l3out.current.0.l3extOut.children.0.mplsExtP.children.0.mplsRsLabelPol.attributes.tDn == "uni/tn-infra/mplslabelpol-default" + - add_infra_sr_mpls_l3out.current.0.l3extOut.children.1.l3extRsL3DomAtt.attributes.tDn == "uni/l3dom-ansible_dom" + - add_infra_sr_mpls_l3out.current.0.l3extOut.children.2.l3extProvLbl.attributes.name == "ansible_infra_sr_mpls_l3out" + - add_infra_sr_mpls_l3out.current.0.l3extOut.children.3.l3extRsEctx.attributes.tnFvCtxName == "overlay-1" + - add_infra_sr_mpls_l3out.current.0.l3extOut.children.4.bgpExtP.attributes.descr == "" + - add_infra_sr_mpls_l3out_again is not changed + - delete_infra_sr_mpls_l3out is changed + - delete_infra_sr_mpls_l3out.previous.0.l3extOut.attributes.mplsEnabled == "yes" + - delete_infra_sr_mpls_l3out.previous.0.l3extOut.attributes.name == "ansible_infra_sr_mpls_l3out" + - delete_infra_sr_mpls_l3out.previous.0.l3extOut.children.0.mplsExtP.children.0.mplsRsLabelPol.attributes.tDn == "uni/tn-infra/mplslabelpol-default" + - delete_infra_sr_mpls_l3out.previous.0.l3extOut.children.1.l3extRsL3DomAtt.attributes.tDn == "uni/l3dom-ansible_dom" + - delete_infra_sr_mpls_l3out.previous.0.l3extOut.children.2.l3extProvLbl.attributes.name == "ansible_infra_sr_mpls_l3out" + - delete_infra_sr_mpls_l3out.previous.0.l3extOut.children.3.l3extRsEctx.attributes.tnFvCtxName == "overlay-1" + - delete_infra_sr_mpls_l3out.previous.0.l3extOut.children.4.bgpExtP.attributes.descr == "" + - delete_infra_sr_mpls_l3out.current == [] + - err_infra_sr_mpls_l3out_no_overlay_1_vrf.failed == true + - err_infra_sr_mpls_l3out_no_overlay_1_vrf.msg == "The vrf parameter must be 'overlay-1' when tenant is 'infra' and mpls is 'yes'" + - err_infra_sr_mpls_l3out_no_bgp.failed == true + - err_infra_sr_mpls_l3out_no_bgp.msg == "The l3protocol parameter must be 'bgp' when tenant is 'infra' and mpls is 'yes'" + - name: Delete the ansible_tenant - cleanup before ending tests - aci_tenant: + cisco.aci.aci_tenant: <<: *aci_info tenant: ansible_tenant state: absent diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_l3out_bfd_interface_profile/aliases b/ansible_collections/cisco/aci/tests/integration/targets/aci_l3out_bfd_interface_profile/aliases new file mode 100644 index 000000000..209b793f9 --- /dev/null +++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_l3out_bfd_interface_profile/aliases @@ -0,0 +1,2 @@ +# No ACI simulator yet, so not enabled +# unsupported diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_l3out_bfd_interface_profile/tasks/main.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_l3out_bfd_interface_profile/tasks/main.yml new file mode 100644 index 000000000..19c034eb8 --- /dev/null +++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_l3out_bfd_interface_profile/tasks/main.yml @@ -0,0 +1,226 @@ +# Test code for the ACI modules +# Copyright: (c) 2023, Anvitha Jain (@anvjain) + +# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) + +- name: Test that we have an ACI APIC host, ACI username and ACI password + fail: + msg: 'Please define the following variables: aci_hostname, aci_username and aci_password.' + when: aci_hostname is not defined or aci_username is not defined or aci_password is not defined + +- name: Set vars + ansible.builtin.set_fact: + aci_info: &aci_info + host: "{{ aci_hostname }}" + username: "{{ aci_username }}" + password: "{{ aci_password }}" + validate_certs: '{{ aci_validate_certs | default(false) }}' + use_ssl: '{{ aci_use_ssl | default(true) }}' + use_proxy: '{{ aci_use_proxy | default(true) }}' + output_level: debug + +- name: Query system information + cisco.aci.aci_system: + <<: *aci_info + id: 1 + state: query + register: version + +- name: Verify Cloud and Non-Cloud Sites in use. + include_tasks: ../../../../../../integration/targets/aci_cloud_provider/tasks/main.yml + +- name: Execute tasks only for non-cloud sites + # This condition will execute only when APIC version >= 5.2 and for non-cloud APICs + when: version.current.0.topSystem.attributes.version is version('5.2', '>=') and query_cloud.current == [] + block: # block specifies execution of tasks within, based on conditions + + # CLEAN ENVIRONMENT + - name: Remove the ansible_tenant + cisco.aci.aci_tenant: + <<: *aci_info + tenant: ansible_tenant + state: absent + + # Add a tenant + - name: Add a new tenant + cisco.aci.aci_tenant: + <<: *aci_info + tenant: ansible_tenant + description: Ansible tenant + state: present + + # Add VRF + - name: Add a new VRF + cisco.aci.aci_vrf: + <<: *aci_info + tenant: ansible_tenant + name: ansible_vrf + description: Ansible VRF + state: present + + # Add L3Out + - name: Add a new L3 Outside + cisco.aci.aci_l3out: + <<: *aci_info + tenant: ansible_tenant + name: ansible_l3out + description: Ansible L3 Outside + domain: ansible_dom + vrf: ansible_vrf + l3protocol: bgp + state: present + + # ADD l3out logical node profile + - name: l3out logical node profile + cisco.aci.aci_l3out_logical_node_profile: + <<: *aci_info + tenant: ansible_tenant + l3out: ansible_l3out + node_profile: ansible_node_profile + state: present + + # ADD l3out logical interface profile + - name: l3out logical interface profile + cisco.aci.aci_l3out_logical_interface_profile: + <<: *aci_info + tenant: ansible_tenant + l3out: ansible_l3out + node_profile: ansible_node_profile + interface_profile: ansible_interface_profile + state: present + + # CREATE L3Out BFD Interface policy + - name: Add a new L3Out BFD Interface policy + cisco.aci.aci_interface_policy_bfd: + <<: *aci_info + tenant: ansible_tenant + name: ansible_bfd__interface_policy + description: Ansible BFD Interface Policy + state: present + register: add_bfd_interface_pol + + # Add L3Out BFD Interface Profile + - name: Add a new L3Out BFD Interface Profile - check mode + cisco.aci.aci_l3out_bfd_interface_profile: &present_l3out_bfd_int_profile + <<: *aci_info + tenant: ansible_tenant + l3out: ansible_l3out + l3out_logical_node_profile: ansible_node_profile + l3out_logical_interface_profile: ansible_interface_profile + bfd_interface_policy: ansible_bfd_interface_policy + state: present + check_mode: true + register: cm_add_l3out_bfd_int_prof + + - name: Add a new L3Out BFD Interface Profile - normal mode + cisco.aci.aci_l3out_bfd_interface_profile: + <<: *present_l3out_bfd_int_profile + state: present + register: nm_add_l3out_bfd_int_prof + + - name: Verify adding L3Out BFD Interface Profile + assert: + that: + - cm_add_l3out_bfd_int_prof is changed + - nm_add_l3out_bfd_int_prof is changed + - cm_add_l3out_bfd_int_prof.previous == nm_add_l3out_bfd_int_prof.previous == [] + - cm_add_l3out_bfd_int_prof.proposed.bfdIfP.attributes.dn == nm_add_l3out_bfd_int_prof.proposed.bfdIfP.attributes.dn == "uni/tn-ansible_tenant/out-ansible_l3out/lnodep-ansible_node_profile/lifp-ansible_interface_profile/bfdIfP" + - cm_add_l3out_bfd_int_prof.proposed.bfdIfP.children.0.bfdRsIfPol.attributes.tnBfdIfPolName == cm_add_l3out_bfd_int_prof.proposed.bfdIfP.children.0.bfdRsIfPol.attributes.tnBfdIfPolName == "ansible_bfd_interface_policy" + + - name: Add L3Out BFD Interface Profile again- idempotency + cisco.aci.aci_l3out_bfd_interface_profile: + <<: *present_l3out_bfd_int_profile + state: present + register: add_l3out_bfd_int_prof_again + + - name: Verify adding L3Out BFD Interface Profile again - idempotency + assert: + that: + - add_l3out_bfd_int_prof_again is not changed + + # Update L3Out BFD Interface Profile + - name: Update L3Out BFD Interface Profile + cisco.aci.aci_l3out_bfd_interface_profile: + <<: *present_l3out_bfd_int_profile + authentication_type: sha1 + key: "abc*123" + key_id: 15 + state: present + register: update_l3out_bfd_int_prof + + - name: Verify updating L3Out BFD Interface Profile + assert: + that: + - update_l3out_bfd_int_prof is changed + - update_l3out_bfd_int_prof.sent.bfdIfP.attributes.keyId == "15" + - update_l3out_bfd_int_prof.sent.bfdIfP.attributes.key == "VALUE_SPECIFIED_IN_NO_LOG_PARAMETER" + - update_l3out_bfd_int_prof.sent.bfdIfP.attributes.type == "sha1" + + # Remove children from L3Out BFD Interface Profile + - name: Remove children from L3Out BFD Interface Profile + cisco.aci.aci_l3out_bfd_interface_profile: + <<: *present_l3out_bfd_int_profile + bfd_interface_policy: "" + register: remove_children_l3out_bfd_int_prof + + - name: Asserts for children removal tasks for the from L3Out BFD Interface Profile + ansible.builtin.assert: + that: + - remove_children_l3out_bfd_int_prof is changed + - remove_children_l3out_bfd_int_prof.sent.bfdIfP.children.0.bfdRsIfPol.attributes.tnBfdIfPolName == "" + + # Query L3Out BFD Interface Profile + - name: Query L3Out BFD Interface Profile + cisco.aci.aci_l3out_bfd_interface_profile: + <<: *present_l3out_bfd_int_profile + state: query + register: query_l3out_bfd_int_prof + + - name: Query all L3Out BFD Interface Profile + cisco.aci.aci_l3out_bfd_interface_profile: + <<: *aci_info + state: query + register: query_all_l3out_bfd_int_prof + + # Validating out of range parameters. + - name: Add out of range key_id + cisco.aci.aci_l3out_bfd_interface_profile: + <<: *present_l3out_bfd_int_profile + key_id: 256 + state: present + ignore_errors: true + register: out_of_range_key_id + + - name: Verify out of range key_id + assert: + that: + - out_of_range_key_id is not changed + - out_of_range_key_id.msg == "The \"key_id\" must be a value between 1 and 255" + + - name: Delete L3Out BFD Interface Profile - check mode + cisco.aci.aci_l3out_bfd_interface_profile: + <<: *present_l3out_bfd_int_profile + state: absent + check_mode: true + register: cm_remove_l3out_bfd_int_prof + + - name: Delete L3Out BFD Interface Profile - normal mode + cisco.aci.aci_l3out_bfd_interface_profile: + <<: *present_l3out_bfd_int_profile + state: absent + register: nm_remove_l3out_bfd_int_prof + + - name: Delete L3Out BFD Interface Profile again - idempotency + cisco.aci.aci_l3out_bfd_interface_profile: + <<: *present_l3out_bfd_int_profile + state: absent + register: remove_l3out_bfd_int_prof_again + + - name: Verify removing L3Out BFD Interface Profile + assert: + that: + - cm_remove_l3out_bfd_int_prof is changed + - nm_remove_l3out_bfd_int_prof is changed + - cm_remove_l3out_bfd_int_prof.proposed == nm_remove_l3out_bfd_int_prof.proposed == {} + - remove_l3out_bfd_int_prof_again is not changed + - nm_remove_l3out_bfd_int_prof.current == remove_l3out_bfd_int_prof_again.current == [] \ No newline at end of file diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_l3out_bfd_multihop_interface_profile/aliases b/ansible_collections/cisco/aci/tests/integration/targets/aci_l3out_bfd_multihop_interface_profile/aliases new file mode 100644 index 000000000..209b793f9 --- /dev/null +++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_l3out_bfd_multihop_interface_profile/aliases @@ -0,0 +1,2 @@ +# No ACI simulator yet, so not enabled +# unsupported diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_l3out_bfd_multihop_interface_profile/tasks/main.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_l3out_bfd_multihop_interface_profile/tasks/main.yml new file mode 100644 index 000000000..920453708 --- /dev/null +++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_l3out_bfd_multihop_interface_profile/tasks/main.yml @@ -0,0 +1,233 @@ +# Test code for the ACI modules +# Copyright: (c) 2023, Anvitha Jain (@anvjain) + +# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) + +- name: Test that we have an ACI APIC host, ACI username and ACI password + fail: + msg: 'Please define the following variables: aci_hostname, aci_username and aci_password.' + when: aci_hostname is not defined or aci_username is not defined or aci_password is not defined + +- name: Set vars + ansible.builtin.set_fact: + aci_info: &aci_info + host: "{{ aci_hostname }}" + username: "{{ aci_username }}" + password: "{{ aci_password }}" + validate_certs: '{{ aci_validate_certs | default(false) }}' + use_ssl: '{{ aci_use_ssl | default(true) }}' + use_proxy: '{{ aci_use_proxy | default(true) }}' + output_level: debug + +- name: Query system information + cisco.aci.aci_system: + <<: *aci_info + id: 1 + state: query + register: version + +- name: Verify Cloud and Non-Cloud Sites in use. + include_tasks: ../../../../../../integration/targets/aci_cloud_provider/tasks/main.yml + +- name: Execute tasks only for non-cloud sites + # This condition will execute only when APIC version >= 5.2 and for non-cloud APICs + when: version.current.0.topSystem.attributes.version is version('5.2', '>=') and query_cloud.current == [] + block: # block specifies execution of tasks within, based on conditions + + # CLEAN ENVIRONMENT + - name: Remove the ansible_tenant + cisco.aci.aci_tenant: + <<: *aci_info + tenant: ansible_tenant + state: absent + + # Add a tenant + - name: Add a new tenant + cisco.aci.aci_tenant: + <<: *aci_info + tenant: ansible_tenant + description: Ansible tenant + state: present + + # Add VRF + - name: Add a new VRF + cisco.aci.aci_vrf: + <<: *aci_info + tenant: ansible_tenant + name: ansible_vrf + description: Ansible VRF + state: present + + # Add L3Out + - name: Add a new L3 Outside + cisco.aci.aci_l3out: + <<: *aci_info + tenant: ansible_tenant + name: ansible_l3out + description: Ansible L3 Outside + domain: ansible_dom + vrf: ansible_vrf + l3protocol: bgp + state: present + + # ADD l3out logical node profile + - name: l3out logical node profile + cisco.aci.aci_l3out_logical_node_profile: + <<: *aci_info + tenant: ansible_tenant + l3out: ansible_l3out + node_profile: ansible_node_profile + state: present + + # ADD l3out logical interface profile + - name: l3out logical interface profile + cisco.aci.aci_l3out_logical_interface_profile: + <<: *aci_info + tenant: ansible_tenant + l3out: ansible_l3out + node_profile: ansible_node_profile + interface_profile: ansible_interface_profile + state: present + + # CREATE BFD Multihop Interface policy + - name: Add a new BFD Multihop Interface policy + cisco.aci.aci_interface_policy_bfd_multihop: + <<: *aci_info + tenant: ansible_tenant + name: ansible_bfd_multihop_interface_policy + description: Ansible BFD Multihop Interface Policy + state: present + register: add_bfd_multihop_interface_pol + + # Add BFD Multihop Interface Profile + - name: Add a new BFD Multihop Interface Profile - check mode + cisco.aci.aci_l3out_bfd_multihop_interface_profile: &present_bfd_mh_int_profile + <<: *aci_info + tenant: ansible_tenant + l3out: ansible_l3out + l3out_logical_node_profile: ansible_node_profile + l3out_logical_interface_profile: ansible_interface_profile + bfd_multihop_interface_policy: ansible_bfd_multihop_interface_policy + state: present + check_mode: true + register: cm_add_bfd_mh_int_prof + + - name: Add a new BFD Multihop Interface Profile - normal mode + cisco.aci.aci_l3out_bfd_multihop_interface_profile: + <<: *present_bfd_mh_int_profile + state: present + register: nm_add_bfd_mh_int_prof + + - name: Verify adding BFD Multihop Interface Profile + assert: + that: + - cm_add_bfd_mh_int_prof is changed + - nm_add_bfd_mh_int_prof is changed + - cm_add_bfd_mh_int_prof.previous == nm_add_bfd_mh_int_prof.previous == [] + - cm_add_bfd_mh_int_prof.proposed.bfdMhIfP.attributes.dn == nm_add_bfd_mh_int_prof.proposed.bfdMhIfP.attributes.dn == "uni/tn-ansible_tenant/out-ansible_l3out/lnodep-ansible_node_profile/lifp-ansible_interface_profile/bfdMhIfP" + - cm_add_bfd_mh_int_prof.proposed.bfdMhIfP.children.0.bfdRsMhIfPol.attributes.tnBfdMhIfPolName == nm_add_bfd_mh_int_prof.proposed.bfdMhIfP.children.0.bfdRsMhIfPol.attributes.tnBfdMhIfPolName == "ansible_bfd_multihop_interface_policy" + + # Query BFD Multihop Interface Profile + - name: Query BFD Multihop Interface Profile + cisco.aci.aci_l3out_bfd_multihop_interface_profile: + <<: *present_bfd_mh_int_profile + state: query + register: query_bfd_mh_int_prof + + - name: Add BFD Multihop Interface Profile again- idempotency + cisco.aci.aci_l3out_bfd_multihop_interface_profile: + <<: *present_bfd_mh_int_profile + state: present + register: add_bfd_mh_int_prof_again + + - name: Verify adding BFD Multihop Interface Profile again - idempotency + assert: + that: + - add_bfd_mh_int_prof_again is not changed + + # Update BFD Multihop Interface Profile + - name: Update BFD Multihop Interface Profile + cisco.aci.aci_l3out_bfd_multihop_interface_profile: + <<: *present_bfd_mh_int_profile + authentication_type: sha1 + key: "abc*123" + key_id: 15 + state: present + register: update_bfd_mh_int_prof + + - name: Verify updating BFD Multihop Interface Profile + assert: + that: + - update_bfd_mh_int_prof is changed + - update_bfd_mh_int_prof.sent.bfdMhIfP.attributes.keyId == "15" + - update_bfd_mh_int_prof.sent.bfdMhIfP.attributes.key == "VALUE_SPECIFIED_IN_NO_LOG_PARAMETER" + - update_bfd_mh_int_prof.sent.bfdMhIfP.attributes.type == "sha1" + + # Remove children from L3Out BFD Interface Profile + - name: Remove children from BFD Multihop Interface Profile + cisco.aci.aci_l3out_bfd_multihop_interface_profile: + <<: *present_bfd_mh_int_profile + bfd_multihop_interface_policy: "" + register: remove_children_bfd_mh_int_prof + + - name: Asserts for children removal tasks for the from BFD Multihop Interface Profile + ansible.builtin.assert: + that: + - remove_children_bfd_mh_int_prof is changed + - remove_children_bfd_mh_int_prof.sent.bfdMhIfP.children.0.bfdRsMhIfPol.attributes.tnBfdMhIfPolName == "" + + # Query BFD Multihop Interface Profile + - name: Query BFD Multihop Interface Profile + cisco.aci.aci_l3out_bfd_multihop_interface_profile: + <<: *present_bfd_mh_int_profile + state: query + register: query_bfd_mh_int_prof + + - name: Query all BFD Multihop Interface Profile + cisco.aci.aci_l3out_bfd_multihop_interface_profile: + <<: *aci_info + state: query + register: query_all_bfd_mh_int_prof + + # Validating out of range parameters. + - name: Add out of range key_id + cisco.aci.aci_l3out_bfd_multihop_interface_profile: + <<: *present_bfd_mh_int_profile + key_id: 256 + state: present + ignore_errors: true + register: out_of_range_key_id + + - name: Verify out of range key_id + assert: + that: + - out_of_range_key_id is not changed + - out_of_range_key_id.msg == "The \"key_id\" must be a value between 1 and 255" + + - name: Delete BFD Multihop Interface Profile - check mode + cisco.aci.aci_l3out_bfd_multihop_interface_profile: + <<: *present_bfd_mh_int_profile + state: absent + check_mode: true + register: cm_remove_bfd_mh_int_prof + + - name: Delete BFD Multihop Interface Profile - normal mode + cisco.aci.aci_l3out_bfd_multihop_interface_profile: + <<: *present_bfd_mh_int_profile + state: absent + register: nm_remove_bfd_mh_int_prof + + - name: Delete BFD Multihop Interface Profile again - idempotency + cisco.aci.aci_l3out_bfd_multihop_interface_profile: + <<: *present_bfd_mh_int_profile + state: absent + register: remove_bfd_mh_int_prof_again + + - name: Verify removing BFD Multihop Interface Profile + assert: + that: + - cm_remove_bfd_mh_int_prof is changed + - nm_remove_bfd_mh_int_prof is changed + - cm_remove_bfd_mh_int_prof.proposed == nm_remove_bfd_mh_int_prof.proposed == {} + - remove_bfd_mh_int_prof_again is not changed + - nm_remove_bfd_mh_int_prof.current == remove_bfd_mh_int_prof_again.current == [] \ No newline at end of file diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_l3out_bgp_peer/tasks/main.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_l3out_bgp_peer/tasks/main.yml index 8ed2daee3..e7588be41 100644 --- a/ansible_collections/cisco/aci/tests/integration/targets/aci_l3out_bgp_peer/tasks/main.yml +++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_l3out_bgp_peer/tasks/main.yml @@ -1,16 +1,18 @@ # Test code for the ACI modules # Copyright: (c) 2021, Tim Cragg (@timcragg) +# Copyright: (c) 2023, Akini ROss (@akinross) + # GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) - name: Test that we have an ACI APIC host, ACI username and ACI password - fail: + ansible.builtin.fail: msg: "Please define the following variables: aci_hostname, aci_username and aci_password." when: aci_hostname is not defined or aci_username is not defined or aci_password is not defined # GET Credentials from the inventory - name: Set vars - set_fact: + ansible.builtin.set_fact: aci_info: &aci_info host: "{{ aci_hostname }}" username: "{{ aci_username }}" @@ -28,17 +30,17 @@ register: version - name: Verify Cloud and Non-Cloud Sites in use. - include_tasks: ../../../../../../integration/targets/aci_cloud_provider/tasks/main.yml + ansible.builtin.include_tasks: ../../../../../../integration/targets/aci_cloud_provider/tasks/main.yml # CLEAN ENVIRONMENT - name: Remove ansible_tenant if it already exists - aci_tenant: + cisco.aci.aci_tenant: <<: *aci_info tenant: ansible_tenant state: absent - name: Remove ansible_l3ext_domain if it already exists - aci_domain: + cisco.aci.aci_domain: <<: *aci_info domain: ansible_l3ext_domain domain_type: l3dom @@ -48,21 +50,21 @@ when: query_cloud.current == [] # This condition will skip execution for cloud sites block: - name: Remove ansible_port_channel_ipg if it already exists - aci_interface_policy_leaf_policy_group: + cisco.aci.aci_interface_policy_leaf_policy_group: <<: *aci_info lag_type: link policy_group: ansible_port_channel_ipg state: absent - name: Remove ansible_vpc_ipg if it already exists - aci_interface_policy_leaf_policy_group: + cisco.aci.aci_interface_policy_leaf_policy_group: <<: *aci_info lag_type: node policy_group: ansible_vpc_ipg state: absent - name: Add a new tenant required for l3out - aci_tenant: + cisco.aci.aci_tenant: <<: *aci_info tenant: ansible_tenant description: Ansible tenant @@ -70,7 +72,7 @@ # ADD domain - name: Add domain for l3out - aci_domain: + cisco.aci.aci_domain: <<: *aci_info domain: ansible_l3ext_domain domain_type: l3dom @@ -78,7 +80,7 @@ # ADD VRF - name: Add VRF for l3out - aci_vrf: + cisco.aci.aci_vrf: <<: *aci_info tenant: ansible_tenant vrf: ansible_vrf @@ -86,7 +88,7 @@ # ADD PC IPG - name: Add port-channel IPG - aci_interface_policy_leaf_policy_group: + cisco.aci.aci_interface_policy_leaf_policy_group: <<: *aci_info lag_type: link policy_group: ansible_port_channel_ipg @@ -94,7 +96,7 @@ # ADD vPC IPG - name: Add vPC IPG - aci_interface_policy_leaf_policy_group: + cisco.aci.aci_interface_policy_leaf_policy_group: <<: *aci_info lag_type: node policy_group: ansible_vpc_ipg @@ -102,7 +104,7 @@ # ADD l3out - name: Add l3out - aci_l3out: + cisco.aci.aci_l3out: <<: *aci_info tenant: ansible_tenant name: ansible_l3out @@ -113,7 +115,7 @@ # ADD l3out logical node profile - name: l3out logical node profile - aci_l3out_logical_node_profile: + cisco.aci.aci_l3out_logical_node_profile: <<: *aci_info tenant: ansible_tenant l3out: ansible_l3out @@ -122,7 +124,7 @@ # ADD l3out logical interface profile - name: l3out logical interface profile - aci_l3out_logical_interface_profile: + cisco.aci.aci_l3out_logical_interface_profile: <<: *aci_info tenant: ansible_tenant l3out: ansible_l3out @@ -132,7 +134,7 @@ # ADD l3out interface - name: Add routed interface - aci_l3out_interface: + cisco.aci.aci_l3out_interface: <<: *aci_info tenant: ansible_tenant l3out: ansible_l3out @@ -148,7 +150,7 @@ # ADD l3out port-channel - name: Add routed interface port-channel - aci_l3out_interface: + cisco.aci.aci_l3out_interface: <<: *aci_info tenant: ansible_tenant l3out: ansible_l3out @@ -164,7 +166,7 @@ # ADD l3out vPC - name: Add interface vPC - aci_l3out_interface: + cisco.aci.aci_l3out_interface: <<: *aci_info tenant: ansible_tenant l3out: ansible_l3out @@ -181,7 +183,7 @@ # ADD BGP peer to ethernet port - name: add BGP peer to ethernet port (version >= 4) - aci_l3out_bgp_peer: + cisco.aci.aci_l3out_bgp_peer: <<: *aci_info tenant: ansible_tenant l3out: ansible_l3out @@ -207,7 +209,7 @@ when: version.current.0.topSystem.attributes.version is version('4', '>=') - name: add BGP peer to ethernet port (version < 4) - aci_l3out_bgp_peer: + cisco.aci.aci_l3out_bgp_peer: <<: *aci_info tenant: ansible_tenant l3out: ansible_l3out @@ -230,7 +232,7 @@ when: version.current.0.topSystem.attributes.version is version('4', '<') - name: verify BGP peer has been created with correct attributes (version >= 4) - assert: + ansible.builtin.assert: that: - add_eth_bgp_peer.current.0.bgpPeerP.attributes.dn == "uni/tn-ansible_tenant/out-ansible_l3out/lnodep-ansible_node_profile/lifp-ansible_interface_profile/rspathL3OutAtt-[topology/pod-1/paths-201/pathep-[eth1/15]]/peerP-[192.168.50.2]" - add_eth_bgp_peer.current.0.bgpPeerP.attributes.addr == "192.168.50.2" @@ -245,7 +247,7 @@ when: version.current.0.topSystem.attributes.version is version('4', '>=') - name: verify BGP peer has been created with correct attributes (version < 4) - assert: + ansible.builtin.assert: that: - add_eth_bgp_peer_32.current.0.bgpPeerP.attributes.dn == "uni/tn-ansible_tenant/out-ansible_l3out/lnodep-ansible_node_profile/lifp-ansible_interface_profile/rspathL3OutAtt-[topology/pod-1/paths-201/pathep-[eth1/15]]/peerP-[192.168.50.2]" - add_eth_bgp_peer_32.current.0.bgpPeerP.attributes.addr == "192.168.50.2" @@ -256,20 +258,20 @@ when: version.current.0.topSystem.attributes.version is version('4', '<') - name: verify remote AS object has been created correctly - assert: + ansible.builtin.assert: that: - add_eth_bgp_peer.current.0.bgpPeerP.children.2.bgpAsP.attributes.asn == "65456" when: version.current.0.topSystem.attributes.version is version('4', '>=') - name: verify remote AS object has been created correctly - assert: + ansible.builtin.assert: that: - add_eth_bgp_peer_32.current.0.bgpPeerP.children.1.bgpAsP.attributes.asn == "65456" when: version.current.0.topSystem.attributes.version is version('4', '<') # ADD BGP peer again to check idempotence - name: add BGP peer to ethernet port again (version >= 4) - aci_l3out_bgp_peer: + cisco.aci.aci_l3out_bgp_peer: <<: *aci_info tenant: ansible_tenant l3out: ansible_l3out @@ -294,7 +296,7 @@ when: version.current.0.topSystem.attributes.version is version('4', '>=') - name: add BGP peer to ethernet port again (version < 4) - aci_l3out_bgp_peer: + cisco.aci.aci_l3out_bgp_peer: <<: *aci_info tenant: ansible_tenant l3out: ansible_l3out @@ -317,7 +319,7 @@ when: version.current.0.topSystem.attributes.version is version('4', '<') - name: verify BGP peer has been created with correct attributes (version >= 4) - assert: + ansible.builtin.assert: that: - add_eth_bgp_peer_again is not changed - add_eth_bgp_peer_again.current.0.bgpPeerP.attributes.dn == "uni/tn-ansible_tenant/out-ansible_l3out/lnodep-ansible_node_profile/lifp-ansible_interface_profile/rspathL3OutAtt-[topology/pod-1/paths-201/pathep-[eth1/15]]/peerP-[192.168.50.2]" @@ -330,7 +332,7 @@ when: version.current.0.topSystem.attributes.version is version('4', '>=') - name: verify BGP peer has been created with correct attributes (version < 4) - assert: + ansible.builtin.assert: that: - add_eth_bgp_peer_again_32 is not changed - add_eth_bgp_peer_again_32.current.0.bgpPeerP.attributes.dn == "uni/tn-ansible_tenant/out-ansible_l3out/lnodep-ansible_node_profile/lifp-ansible_interface_profile/rspathL3OutAtt-[topology/pod-1/paths-201/pathep-[eth1/15]]/peerP-[192.168.50.2]" @@ -341,20 +343,20 @@ when: version.current.0.topSystem.attributes.version is version('4', '<') - name: verify remote AS object is still correct (version >= 4) - assert: + ansible.builtin.assert: that: - add_eth_bgp_peer_again.current.0.bgpPeerP.children.2.bgpAsP.attributes.asn == "65456" when: version.current.0.topSystem.attributes.version is version('4', '>=') - name: verify remote AS object his still correct (version < 4) - assert: + ansible.builtin.assert: that: - add_eth_bgp_peer_again_32.current.0.bgpPeerP.children.1.bgpAsP.attributes.asn == "65456" when: version.current.0.topSystem.attributes.version is version('4', '<') # MODIFY BGP peer - name: update BGP peer (version >= 4) - aci_l3out_bgp_peer: &interface_profile_bgp_peer_present + cisco.aci.aci_l3out_bgp_peer: &interface_profile_bgp_peer_present <<: *aci_info tenant: ansible_tenant l3out: ansible_l3out @@ -386,7 +388,7 @@ when: version.current.0.topSystem.attributes.version is version('4', '>=') - name: update BGP peer (version < 4) - aci_l3out_bgp_peer: + cisco.aci.aci_l3out_bgp_peer: <<: *aci_info tenant: ansible_tenant l3out: ansible_l3out @@ -412,7 +414,7 @@ when: version.current.0.topSystem.attributes.version is version('4', '<') - name: verify BGP peer has been updated with correct attributes (version >= 4) - assert: + ansible.builtin.assert: that: - update_eth_bgp_peer is changed - update_eth_bgp_peer.current.0.bgpPeerP.attributes.dn == "uni/tn-ansible_tenant/out-ansible_l3out/lnodep-ansible_node_profile/lifp-ansible_interface_profile/rspathL3OutAtt-[topology/pod-1/paths-201/pathep-[eth1/15]]/peerP-[192.168.50.2]" @@ -429,7 +431,7 @@ when: version.current.0.topSystem.attributes.version is version('4', '>=') - name: verify BGP peer has been updated with correct attributes (version < 4) - assert: + ansible.builtin.assert: that: - update_eth_bgp_peer_32 is changed - update_eth_bgp_peer_32.current.0.bgpPeerP.attributes.dn == "uni/tn-ansible_tenant/out-ansible_l3out/lnodep-ansible_node_profile/lifp-ansible_interface_profile/rspathL3OutAtt-[topology/pod-1/paths-201/pathep-[eth1/15]]/peerP-[192.168.50.2]" @@ -442,20 +444,20 @@ when: version.current.0.topSystem.attributes.version is version('4', '<') - name: verify remote AS object has been updated correctly (version >= 4) - assert: + ansible.builtin.assert: that: - update_eth_bgp_peer.current.0.bgpPeerP.children.2.bgpAsP.attributes.asn == "65457" when: version.current.0.topSystem.attributes.version is version('4', '>=') - name: verify remote AS object has been updated correctly (version < 4) - assert: + ansible.builtin.assert: that: - update_eth_bgp_peer_32.current.0.bgpPeerP.children.1.bgpAsP.attributes.asn == "65457" when: version.current.0.topSystem.attributes.version is version('4', '<') # QUERY BGP peer - name: query BGP peer (version >= 4) - aci_l3out_bgp_peer: + cisco.aci.aci_l3out_bgp_peer: <<: *aci_info tenant: ansible_tenant l3out: ansible_l3out @@ -470,7 +472,7 @@ when: version.current.0.topSystem.attributes.version is version('4', '>=') - name: query BGP peer (version < 4) - aci_l3out_bgp_peer: + cisco.aci.aci_l3out_bgp_peer: <<: *aci_info tenant: ansible_tenant l3out: ansible_l3out @@ -485,7 +487,7 @@ when: version.current.0.topSystem.attributes.version is version('4', '<') - name: verify BGP peer attributes (version >= 4) - assert: + ansible.builtin.assert: that: - query_eth_bgp_peer is not changed - query_eth_bgp_peer.current.0.bgpPeerP.attributes.dn == "uni/tn-ansible_tenant/out-ansible_l3out/lnodep-ansible_node_profile/lifp-ansible_interface_profile/rspathL3OutAtt-[topology/pod-1/paths-201/pathep-[eth1/15]]/peerP-[192.168.50.2]" @@ -500,7 +502,7 @@ when: version.current.0.topSystem.attributes.version is version('4', '>=') - name: verify BGP peer attributes (version < 4) - assert: + ansible.builtin.assert: that: - query_eth_bgp_peer_32 is not changed - query_eth_bgp_peer_32.current.0.bgpPeerP.attributes.dn == "uni/tn-ansible_tenant/out-ansible_l3out/lnodep-ansible_node_profile/lifp-ansible_interface_profile/rspathL3OutAtt-[topology/pod-1/paths-201/pathep-[eth1/15]]/peerP-[192.168.50.2]" @@ -513,13 +515,13 @@ when: version.current.0.topSystem.attributes.version is version('4', '<') - name: verify BGP remote AS (version >= 4) - assert: + ansible.builtin.assert: that: - query_eth_bgp_peer.current.0.bgpPeerP.children.2.bgpAsP.attributes.asn == "65457" when: version.current.0.topSystem.attributes.version is version('4', '>=') - name: verify BGP remote AS (version < 4) - assert: + ansible.builtin.assert: that: - query_eth_bgp_peer_32.current.0.bgpPeerP.children.1.bgpAsP.attributes.asn == "65457" when: version.current.0.topSystem.attributes.version is version('4', '<') @@ -529,7 +531,7 @@ block: # Route Control Profile validation check for Interface Profile level - name: Add Route Control Profile to the ansible_interface_profile (version >= 4) - check mode - aci_l3out_bgp_peer: + cisco.aci.aci_l3out_bgp_peer: <<: *interface_profile_bgp_peer_present route_control_profiles: - tenant: "ansible_tenant" @@ -544,13 +546,13 @@ register: cm_if_rtctrl_present - name: Assertions check for add Route Control Profile to the ansible_interface_profile (version >= 4) - check mode - assert: + ansible.builtin.assert: that: - cm_if_rtctrl_present is changed - cm_if_rtctrl_present.sent.bgpPeerP.children | length == 2 - name: Add Route Control Profile to the ansible_interface_profile (version >= 4) - normal mode - missing param - aci_l3out_bgp_peer: + cisco.aci.aci_l3out_bgp_peer: <<: *interface_profile_bgp_peer_present route_control_profiles: - tenant: "ansible_tenant" @@ -564,13 +566,13 @@ ignore_errors: true - name: Assertions check for add Route Control Profile to the ansible_interface_profile (version >= 4) - normal mode - missing param - assert: + ansible.builtin.assert: that: - nm_if_rtctrl_present_missing_param is failed - "nm_if_rtctrl_present_missing_param.msg == 'missing required arguments: direction found in route_control_profiles'" - name: Add Route Control Profile to the ansible_interface_profile (version >= 4) - normal mode - aci_l3out_bgp_peer: &nm_if_rtctrl_present + cisco.aci.aci_l3out_bgp_peer: &nm_if_rtctrl_present <<: *interface_profile_bgp_peer_present route_control_profiles: - tenant: "ansible_tenant" @@ -584,7 +586,7 @@ register: nm_if_rtctrl_present - name: Assertions check for add Route Control Profile to the ansible_interface_profile (version >= 4) - normal mode - assert: + ansible.builtin.assert: that: - nm_if_rtctrl_present is changed - nm_if_rtctrl_present.current | length == 1 @@ -594,13 +596,13 @@ - nm_if_rtctrl_present.current.0.bgpPeerP.children | length >= nm_if_rtctrl_present.previous.0.bgpPeerP.children | length - name: Add Route Control Profile to the ansible_interface_profile (version >= 4) - normal mode - idempotency works - aci_l3out_bgp_peer: + cisco.aci.aci_l3out_bgp_peer: <<: *nm_if_rtctrl_present state: present register: idempotency_nm_if_rtctrl_present - name: Idempotency assertions check for add Route Control Profile to the ansible_interface_profile (version >= 4) - normal mode - assert: + ansible.builtin.assert: that: - idempotency_nm_if_rtctrl_present is not changed - idempotency_nm_if_rtctrl_present.current | length == 1 @@ -611,7 +613,7 @@ - idempotency_nm_if_rtctrl_present.previous.0.bgpPeerP.children | length >= 2 - name: Query a BGP Peer with Interface Profile - aci_l3out_bgp_peer: + cisco.aci.aci_l3out_bgp_peer: <<: *aci_info tenant: ansible_tenant l3out: ansible_l3out @@ -625,7 +627,7 @@ register: query_if_bgp_peer - name: Assertions check for query a BGP Peer with Interface Profile - assert: + ansible.builtin.assert: that: - query_if_bgp_peer is not changed - query_if_bgp_peer.current | length == 1 @@ -634,7 +636,7 @@ # Route Control Profile validation check for Node Profile level - name: Add BGP Peer to the Node Profile level (version >= 4) - check mode - aci_l3out_bgp_peer: &cm_ln_rtctrl_present + cisco.aci.aci_l3out_bgp_peer: &cm_ln_rtctrl_present <<: *aci_info tenant: ansible_tenant l3out: ansible_l3out @@ -655,7 +657,7 @@ register: cm_ln_rtctrl_present - name: Assertions check for add BGP Peer to the Node Profile level (version >= 4) - check mode - assert: + ansible.builtin.assert: that: - cm_ln_rtctrl_present is changed - cm_ln_rtctrl_present.current | length == 0 @@ -664,13 +666,13 @@ - cm_ln_rtctrl_present.sent.bgpPeerP.children | length >= 2 - name: Add BGP Peer to the Node Profile level (version >= 4) - normal mode - aci_l3out_bgp_peer: + cisco.aci.aci_l3out_bgp_peer: <<: *cm_ln_rtctrl_present state: present register: nm_ln_rtctrl_present - name: Assertions check for add BGP Peer to the Node Profile level (version >= 4) - normal mode - assert: + ansible.builtin.assert: that: - nm_ln_rtctrl_present is changed - nm_ln_rtctrl_present.current | length == 1 @@ -681,13 +683,13 @@ - nm_ln_rtctrl_present.current.0.bgpPeerP.children.2.bgpLocalAsnP.attributes.localAsn == "100" - name: Add BGP Peer to the Node Profile level (version >= 4) - normal mode - idempotency works - aci_l3out_bgp_peer: + cisco.aci.aci_l3out_bgp_peer: <<: *cm_ln_rtctrl_present state: present register: idempotency_nm_ln_rtctrl_present - name: Idempotency assertions check for add BGP Peer to the Node Profile level (version >= 4) - normal mode - assert: + ansible.builtin.assert: that: - idempotency_nm_ln_rtctrl_present is not changed - idempotency_nm_ln_rtctrl_present.current | length == 1 @@ -697,7 +699,7 @@ - idempotency_nm_ln_rtctrl_present.previous.0.bgpPeerP.attributes.addr == "192.168.50.3" - name: Add BGP Peer to the Node Profile level (version >= 4) - normal mode - missing param - aci_l3out_bgp_peer: + cisco.aci.aci_l3out_bgp_peer: <<: *cm_ln_rtctrl_present route_control_profiles: - tenant: "ansible_tenant" @@ -711,13 +713,13 @@ ignore_errors: true - name: Assertions check for add BGP Peer to the Node Profile level (version >= 4) - normal mode - missing param - assert: + ansible.builtin.assert: that: - nm_ln_rtctrl_present_missing_param is failed - "nm_ln_rtctrl_present_missing_param.msg == 'missing required arguments: direction found in route_control_profiles'" - name: Query a BGP Peer from the Node Profile level - aci_l3out_bgp_peer: + cisco.aci.aci_l3out_bgp_peer: <<: *aci_info tenant: ansible_tenant l3out: ansible_l3out @@ -727,27 +729,27 @@ register: query_ln_bgp_peer - name: Assertions check for query a BGP Peer from the Node Profile level - assert: + ansible.builtin.assert: that: - query_ln_bgp_peer is not changed - query_ln_bgp_peer.current | length == 1 - query_ln_bgp_peer.current.0.bgpPeerP.attributes.addr == "192.168.50.3" - name: Query all BGP peers - aci_l3out_bgp_peer: + cisco.aci.aci_l3out_bgp_peer: <<: *aci_info state: query register: query_all_bgp_peer - name: Assertions check for query all BGP peers - assert: + ansible.builtin.assert: that: - query_all_bgp_peer is not changed - query_all_bgp_peer.current | length != 0 # DELETE BGP peer - name: delete BGP peer - aci_l3out_bgp_peer: + cisco.aci.aci_l3out_bgp_peer: <<: *aci_info tenant: ansible_tenant l3out: ansible_l3out @@ -761,7 +763,7 @@ register: remove_eth_bgp_peer - name: verify remove_eth_bgp_peer - assert: + ansible.builtin.assert: that: - remove_eth_bgp_peer is changed - remove_eth_bgp_peer.current == [] @@ -770,7 +772,7 @@ # ADD BGP peer to port-channel - name: add BGP peer to port-channel (version >= 4) - aci_l3out_bgp_peer: + cisco.aci.aci_l3out_bgp_peer: <<: *aci_info tenant: ansible_tenant l3out: ansible_l3out @@ -795,7 +797,7 @@ when: version.current.0.topSystem.attributes.version is version('4', '>=') - name: add BGP peer to port-channel (version < 4) - aci_l3out_bgp_peer: + cisco.aci.aci_l3out_bgp_peer: <<: *aci_info tenant: ansible_tenant l3out: ansible_l3out @@ -818,7 +820,7 @@ when: version.current.0.topSystem.attributes.version is version('4', '<') - name: verify BGP peer has been created with correct attributes (version >= 4) - assert: + ansible.builtin.assert: that: - add_pc_bgp_peer.current.0.bgpPeerP.attributes.dn == "uni/tn-ansible_tenant/out-ansible_l3out/lnodep-ansible_node_profile/lifp-ansible_interface_profile/rspathL3OutAtt-[topology/pod-1/paths-201/pathep-[ansible_port_channel_ipg]]/peerP-[192.168.50.2]" - add_pc_bgp_peer.current.0.bgpPeerP.attributes.addr == "192.168.50.2" @@ -830,7 +832,7 @@ when: version.current.0.topSystem.attributes.version is version('4', '>=') - name: verify BGP peer has been created with correct attributes (version < 4) - assert: + ansible.builtin.assert: that: - add_pc_bgp_peer_32.current.0.bgpPeerP.attributes.dn == "uni/tn-ansible_tenant/out-ansible_l3out/lnodep-ansible_node_profile/lifp-ansible_interface_profile/rspathL3OutAtt-[topology/pod-1/paths-201/pathep-[ansible_port_channel_ipg]]/peerP-[192.168.50.2]" - add_pc_bgp_peer_32.current.0.bgpPeerP.attributes.addr == "192.168.50.2" @@ -840,20 +842,20 @@ when: version.current.0.topSystem.attributes.version is version('4', '<') - name: verify remote AS object has been created correctly (version >= 4) - assert: + ansible.builtin.assert: that: - add_pc_bgp_peer.current.0.bgpPeerP.children.1.bgpAsP.attributes.asn == "65456" when: version.current.0.topSystem.attributes.version is version('4', '>=') - name: verify remote AS object has been created correctly (version < 4) - assert: + ansible.builtin.assert: that: - add_pc_bgp_peer_32.current.0.bgpPeerP.children.1.bgpAsP.attributes.asn == "65456" when: version.current.0.topSystem.attributes.version is version('4', '<') # ADD BGP peer again to check idempotence - name: add BGP peer to port-channel again (version >= 4) - aci_l3out_bgp_peer: + cisco.aci.aci_l3out_bgp_peer: <<: *aci_info tenant: ansible_tenant l3out: ansible_l3out @@ -878,7 +880,7 @@ when: version.current.0.topSystem.attributes.version is version('4', '>=') - name: add BGP peer to port-channel again (version < 4) - aci_l3out_bgp_peer: + cisco.aci.aci_l3out_bgp_peer: <<: *aci_info tenant: ansible_tenant l3out: ansible_l3out @@ -901,7 +903,7 @@ when: version.current.0.topSystem.attributes.version is version('4', '<') - name: verify BGP peer has been created with correct attributes (version >= 4) - assert: + ansible.builtin.assert: that: - add_pc_bgp_peer_again is not changed - add_pc_bgp_peer_again.current.0.bgpPeerP.attributes.dn == "uni/tn-ansible_tenant/out-ansible_l3out/lnodep-ansible_node_profile/lifp-ansible_interface_profile/rspathL3OutAtt-[topology/pod-1/paths-201/pathep-[ansible_port_channel_ipg]]/peerP-[192.168.50.2]" @@ -914,7 +916,7 @@ when: version.current.0.topSystem.attributes.version is version('4', '>=') - name: verify BGP peer has been created with correct attributes (version < 4) - assert: + ansible.builtin.assert: that: - add_pc_bgp_peer_again_32 is not changed - add_pc_bgp_peer_again_32.current.0.bgpPeerP.attributes.dn == "uni/tn-ansible_tenant/out-ansible_l3out/lnodep-ansible_node_profile/lifp-ansible_interface_profile/rspathL3OutAtt-[topology/pod-1/paths-201/pathep-[ansible_port_channel_ipg]]/peerP-[192.168.50.2]" @@ -925,20 +927,20 @@ when: version.current.0.topSystem.attributes.version is version('4', '<') - name: verify remote AS object has been created correctly (version >= 4) - assert: + ansible.builtin.assert: that: - add_pc_bgp_peer_again.current.0.bgpPeerP.children.1.bgpAsP.attributes.asn == "65456" when: version.current.0.topSystem.attributes.version is version('4', '>=') - name: verify remote AS object has been created correctly (version < 4) - assert: + ansible.builtin.assert: that: - add_pc_bgp_peer_again_32.current.0.bgpPeerP.children.1.bgpAsP.attributes.asn == "65456" when: version.current.0.topSystem.attributes.version is version('4', '<') # MODIFY BGP peer - name: update BGP peer (version >= 4) - aci_l3out_bgp_peer: + cisco.aci.aci_l3out_bgp_peer: <<: *aci_info tenant: ansible_tenant l3out: ansible_l3out @@ -971,7 +973,7 @@ when: version.current.0.topSystem.attributes.version is version('4', '>=') - name: update BGP peer (version < 4) - aci_l3out_bgp_peer: + cisco.aci.aci_l3out_bgp_peer: <<: *aci_info tenant: ansible_tenant l3out: ansible_l3out @@ -1000,7 +1002,7 @@ when: version.current.0.topSystem.attributes.version is version('4', '<') - name: verify BGP peer has been updated with correct attributes (version >= 4) - assert: + ansible.builtin.assert: that: - update_pc_bgp_peer is changed - update_pc_bgp_peer.current.0.bgpPeerP.attributes.dn == "uni/tn-ansible_tenant/out-ansible_l3out/lnodep-ansible_node_profile/lifp-ansible_interface_profile/rspathL3OutAtt-[topology/pod-1/paths-201/pathep-[ansible_port_channel_ipg]]/peerP-[192.168.50.2]" @@ -1015,7 +1017,7 @@ when: version.current.0.topSystem.attributes.version is version('4', '>=') - name: verify BGP peer has been updated with correct attributes (version < 4) - assert: + ansible.builtin.assert: that: - update_pc_bgp_peer_32 is changed - update_pc_bgp_peer_32.current.0.bgpPeerP.attributes.dn == "uni/tn-ansible_tenant/out-ansible_l3out/lnodep-ansible_node_profile/lifp-ansible_interface_profile/rspathL3OutAtt-[topology/pod-1/paths-201/pathep-[ansible_port_channel_ipg]]/peerP-[192.168.50.2]" @@ -1028,20 +1030,20 @@ when: version.current.0.topSystem.attributes.version is version('4', '<') - name: verify remote AS object has been created correctly (version >= 4) - assert: + ansible.builtin.assert: that: - update_pc_bgp_peer.current.0.bgpPeerP.children.1.bgpAsP.attributes.asn == "65457" when: version.current.0.topSystem.attributes.version is version('4', '>=') - name: verify remote AS object has been created correctly (version < 4) - assert: + ansible.builtin.assert: that: - update_pc_bgp_peer_32.current.0.bgpPeerP.children.1.bgpAsP.attributes.asn == "65457" when: version.current.0.topSystem.attributes.version is version('4', '<') # QUERY BGP peer - name: query BGP peer (version >= 4) - aci_l3out_bgp_peer: + cisco.aci.aci_l3out_bgp_peer: <<: *aci_info tenant: ansible_tenant l3out: ansible_l3out @@ -1056,7 +1058,7 @@ when: version.current.0.topSystem.attributes.version is version('4', '>=') - name: query BGP peer (version < 4) - aci_l3out_bgp_peer: + cisco.aci.aci_l3out_bgp_peer: <<: *aci_info tenant: ansible_tenant l3out: ansible_l3out @@ -1071,7 +1073,7 @@ when: version.current.0.topSystem.attributes.version is version('4', '<') - name: verify BGP peer attributes (version >= 4) - assert: + ansible.builtin.assert: that: - query_pc_bgp_peer is not changed - query_pc_bgp_peer.current.0.bgpPeerP.attributes.dn == "uni/tn-ansible_tenant/out-ansible_l3out/lnodep-ansible_node_profile/lifp-ansible_interface_profile/rspathL3OutAtt-[topology/pod-1/paths-201/pathep-[ansible_port_channel_ipg]]/peerP-[192.168.50.2]" @@ -1086,7 +1088,7 @@ when: version.current.0.topSystem.attributes.version is version('4', '>=') - name: verify BGP peer attributes (version < 4) - assert: + ansible.builtin.assert: that: - query_pc_bgp_peer_32 is not changed - query_pc_bgp_peer_32.current.0.bgpPeerP.attributes.dn == "uni/tn-ansible_tenant/out-ansible_l3out/lnodep-ansible_node_profile/lifp-ansible_interface_profile/rspathL3OutAtt-[topology/pod-1/paths-201/pathep-[ansible_port_channel_ipg]]/peerP-[192.168.50.2]" @@ -1099,20 +1101,20 @@ when: version.current.0.topSystem.attributes.version is version('4', '<') - name: verify BGP remote AS (version >= 4) - assert: + ansible.builtin.assert: that: - query_pc_bgp_peer.current.0.bgpPeerP.children.1.bgpAsP.attributes.asn == "65457" when: version.current.0.topSystem.attributes.version is version('4', '>=') - name: verify BGP remote AS (version < 4) - assert: + ansible.builtin.assert: that: - query_pc_bgp_peer_32.current.0.bgpPeerP.children.1.bgpAsP.attributes.asn == "65457" when: version.current.0.topSystem.attributes.version is version('4', '<') # DELETE BGP peer - name: delete BGP peer - aci_l3out_bgp_peer: + cisco.aci.aci_l3out_bgp_peer: <<: *aci_info tenant: ansible_tenant l3out: ansible_l3out @@ -1126,7 +1128,7 @@ register: remove_pc_bgp_peer - name: verify remove_pc_bgp_peer - assert: + ansible.builtin.assert: that: - remove_pc_bgp_peer is changed - remove_pc_bgp_peer.current == [] @@ -1135,7 +1137,7 @@ # ADD BGP peer to vPC - name: add BGP peer to vPC (version >= 4) - aci_l3out_bgp_peer: + cisco.aci.aci_l3out_bgp_peer: <<: *aci_info tenant: ansible_tenant l3out: ansible_l3out @@ -1160,7 +1162,7 @@ when: version.current.0.topSystem.attributes.version is version('4', '>=') - name: add BGP peer to vPC (version < 4) - aci_l3out_bgp_peer: + cisco.aci.aci_l3out_bgp_peer: <<: *aci_info tenant: ansible_tenant l3out: ansible_l3out @@ -1183,7 +1185,7 @@ when: version.current.0.topSystem.attributes.version is version('4', '<') - name: verify BGP peer has been created with correct attributes (version >= 4) - assert: + ansible.builtin.assert: that: - add_vpc_bgp_peer.current.0.bgpPeerP.attributes.dn == "uni/tn-ansible_tenant/out-ansible_l3out/lnodep-ansible_node_profile/lifp-ansible_interface_profile/rspathL3OutAtt-[topology/pod-1/protpaths-201-202/pathep-[ansible_vpc_ipg]]/peerP-[192.168.50.2]" - add_vpc_bgp_peer.current.0.bgpPeerP.attributes.addr == "192.168.50.2" @@ -1195,7 +1197,7 @@ when: version.current.0.topSystem.attributes.version is version('4', '>=') - name: verify BGP peer has been created with correct attributes (version < 4) - assert: + ansible.builtin.assert: that: - add_vpc_bgp_peer_32.current.0.bgpPeerP.attributes.dn == "uni/tn-ansible_tenant/out-ansible_l3out/lnodep-ansible_node_profile/lifp-ansible_interface_profile/rspathL3OutAtt-[topology/pod-1/protpaths-201-202/pathep-[ansible_vpc_ipg]]/peerP-[192.168.50.2]" - add_vpc_bgp_peer_32.current.0.bgpPeerP.attributes.addr == "192.168.50.2" @@ -1205,20 +1207,20 @@ when: version.current.0.topSystem.attributes.version is version('4', '<') - name: verify remote AS object has been created correctly (version >= 4) - assert: + ansible.builtin.assert: that: - add_vpc_bgp_peer.current.0.bgpPeerP.children.1.bgpAsP.attributes.asn == "65456" when: version.current.0.topSystem.attributes.version is version('4', '>=') - name: verify remote AS object has been created correctly (version < 4) - assert: + ansible.builtin.assert: that: - add_vpc_bgp_peer_32.current.0.bgpPeerP.children.1.bgpAsP.attributes.asn == "65456" when: version.current.0.topSystem.attributes.version is version('4', '<') # ADD BGP peer again to check idempotence - name: add BGP peer to vPC again (version >= 4) - aci_l3out_bgp_peer: + cisco.aci.aci_l3out_bgp_peer: <<: *aci_info tenant: ansible_tenant l3out: ansible_l3out @@ -1243,7 +1245,7 @@ when: version.current.0.topSystem.attributes.version is version('4', '>=') - name: add BGP peer to vPC again (version < 4) - aci_l3out_bgp_peer: + cisco.aci.aci_l3out_bgp_peer: <<: *aci_info tenant: ansible_tenant l3out: ansible_l3out @@ -1266,7 +1268,7 @@ when: version.current.0.topSystem.attributes.version is version('4', '<') - name: verify BGP peer has been created with correct attributes (version >= 4) - assert: + ansible.builtin.assert: that: - add_vpc_bgp_peer_again is not changed - add_vpc_bgp_peer_again.current.0.bgpPeerP.attributes.dn == "uni/tn-ansible_tenant/out-ansible_l3out/lnodep-ansible_node_profile/lifp-ansible_interface_profile/rspathL3OutAtt-[topology/pod-1/protpaths-201-202/pathep-[ansible_vpc_ipg]]/peerP-[192.168.50.2]" @@ -1279,7 +1281,7 @@ when: version.current.0.topSystem.attributes.version is version('4', '>=') - name: verify BGP peer has been created with correct attributes (version < 4) - assert: + ansible.builtin.assert: that: - add_vpc_bgp_peer_again_32 is not changed - add_vpc_bgp_peer_again_32.current.0.bgpPeerP.attributes.dn == "uni/tn-ansible_tenant/out-ansible_l3out/lnodep-ansible_node_profile/lifp-ansible_interface_profile/rspathL3OutAtt-[topology/pod-1/protpaths-201-202/pathep-[ansible_vpc_ipg]]/peerP-[192.168.50.2]" @@ -1290,20 +1292,20 @@ when: version.current.0.topSystem.attributes.version is version('4', '<') - name: verify remote AS object has been created correctly (version >= 4) - assert: + ansible.builtin.assert: that: - add_vpc_bgp_peer_again.current.0.bgpPeerP.children.1.bgpAsP.attributes.asn == "65456" when: version.current.0.topSystem.attributes.version is version('4', '>=') - name: verify remote AS object has been created correctly (version < 4) - assert: + ansible.builtin.assert: that: - add_vpc_bgp_peer_again_32.current.0.bgpPeerP.children.1.bgpAsP.attributes.asn == "65456" when: version.current.0.topSystem.attributes.version is version('4', '<') # MODIFY BGP peer - name: update BGP peer (version >= 4) - aci_l3out_bgp_peer: + cisco.aci.aci_l3out_bgp_peer: <<: *aci_info tenant: ansible_tenant l3out: ansible_l3out @@ -1336,7 +1338,7 @@ when: version.current.0.topSystem.attributes.version is version('4', '>=') - name: update BGP peer (version < 4) - aci_l3out_bgp_peer: + cisco.aci.aci_l3out_bgp_peer: <<: *aci_info tenant: ansible_tenant l3out: ansible_l3out @@ -1365,7 +1367,7 @@ when: version.current.0.topSystem.attributes.version is version('4', '<') - name: verify BGP peer has been updated with correct attributes (version >= 4) - assert: + ansible.builtin.assert: that: - update_vpc_bgp_peer is changed - update_vpc_bgp_peer.current.0.bgpPeerP.attributes.dn == "uni/tn-ansible_tenant/out-ansible_l3out/lnodep-ansible_node_profile/lifp-ansible_interface_profile/rspathL3OutAtt-[topology/pod-1/protpaths-201-202/pathep-[ansible_vpc_ipg]]/peerP-[192.168.50.2]" @@ -1380,7 +1382,7 @@ when: version.current.0.topSystem.attributes.version is version('4', '>=') - name: verify BGP peer has been updated with correct attributes (version < 4) - assert: + ansible.builtin.assert: that: - update_vpc_bgp_peer_32 is changed - update_vpc_bgp_peer_32.current.0.bgpPeerP.attributes.dn == "uni/tn-ansible_tenant/out-ansible_l3out/lnodep-ansible_node_profile/lifp-ansible_interface_profile/rspathL3OutAtt-[topology/pod-1/protpaths-201-202/pathep-[ansible_vpc_ipg]]/peerP-[192.168.50.2]" @@ -1393,20 +1395,20 @@ when: version.current.0.topSystem.attributes.version is version('4', '<') - name: verify remote AS object has been created correctly (version >= 4) - assert: + ansible.builtin.assert: that: - update_vpc_bgp_peer.current.0.bgpPeerP.children.1.bgpAsP.attributes.asn == "65457" when: version.current.0.topSystem.attributes.version is version('4', '>=') - name: verify remote AS object has been created correctly (version < 4) - assert: + ansible.builtin.assert: that: - update_vpc_bgp_peer_32.current.0.bgpPeerP.children.1.bgpAsP.attributes.asn == "65457" when: version.current.0.topSystem.attributes.version is version('4', '<') # QUERY BGP peer - name: query BGP peer (version >= 4) - aci_l3out_bgp_peer: + cisco.aci.aci_l3out_bgp_peer: <<: *aci_info tenant: ansible_tenant l3out: ansible_l3out @@ -1421,7 +1423,7 @@ when: version.current.0.topSystem.attributes.version is version('4', '>=') - name: query BGP peer (version < 4) - aci_l3out_bgp_peer: + cisco.aci.aci_l3out_bgp_peer: <<: *aci_info tenant: ansible_tenant l3out: ansible_l3out @@ -1436,7 +1438,7 @@ when: version.current.0.topSystem.attributes.version is version('4', '<') - name: verify BGP peer attributes (version >= 4) - assert: + ansible.builtin.assert: that: - query_vpc_bgp_peer is not changed - query_vpc_bgp_peer.current.0.bgpPeerP.attributes.dn == "uni/tn-ansible_tenant/out-ansible_l3out/lnodep-ansible_node_profile/lifp-ansible_interface_profile/rspathL3OutAtt-[topology/pod-1/protpaths-201-202/pathep-[ansible_vpc_ipg]]/peerP-[192.168.50.2]" @@ -1451,7 +1453,7 @@ when: version.current.0.topSystem.attributes.version is version('4', '>=') - name: verify BGP peer attributes (version < 4) - assert: + ansible.builtin.assert: that: - query_vpc_bgp_peer_32 is not changed - query_vpc_bgp_peer_32.current.0.bgpPeerP.attributes.dn == "uni/tn-ansible_tenant/out-ansible_l3out/lnodep-ansible_node_profile/lifp-ansible_interface_profile/rspathL3OutAtt-[topology/pod-1/protpaths-201-202/pathep-[ansible_vpc_ipg]]/peerP-[192.168.50.2]" @@ -1464,20 +1466,20 @@ when: version.current.0.topSystem.attributes.version is version('4', '<') - name: verify BGP remote AS (version >= 4) - assert: + ansible.builtin.assert: that: - query_pc_bgp_peer.current.0.bgpPeerP.children.1.bgpAsP.attributes.asn == "65457" when: version.current.0.topSystem.attributes.version is version('4', '>=') - name: verify BGP remote AS (version < 4) - assert: + ansible.builtin.assert: that: - query_pc_bgp_peer_32.current.0.bgpPeerP.children.1.bgpAsP.attributes.asn == "65457" when: version.current.0.topSystem.attributes.version is version('4', '<') # DELETE BGP peer - name: delete BGP peer - aci_l3out_bgp_peer: + cisco.aci.aci_l3out_bgp_peer: <<: *aci_info tenant: ansible_tenant l3out: ansible_l3out @@ -1491,36 +1493,170 @@ register: remove_vpc_bgp_peer - name: verify remove_vpc_bgp_peer - assert: + ansible.builtin.assert: that: - remove_vpc_bgp_peer is changed - remove_vpc_bgp_peer.current == [] - remove_vpc_bgp_peer.previous.0.bgpPeerP.attributes.dn == "uni/tn-ansible_tenant/out-ansible_l3out/lnodep-ansible_node_profile/lifp-ansible_interface_profile/rspathL3OutAtt-[topology/pod-1/protpaths-201-202/pathep-[ansible_vpc_ipg]]/peerP-[192.168.50.2]" - remove_vpc_bgp_peer.previous.0.bgpPeerP.attributes.addr == "192.168.50.2" + # Create BGP Peer with password + - name: Create BGP Peer with password + aci_l3out_bgp_peer: &bgp_peer_with_password + <<: *aci_info + tenant: ansible_tenant + l3out: ansible_l3out + node_profile: ansible_node_profile + interface_profile: ansible_interface_profile + pod_id: 1 + node_id: 201-202 + path_ep: ansible_vpc_ipg + peer_ip: 192.168.50.2 + description: ansible_test_description + bgp_password: ansible_test_password + remote_asn: 65450 + local_as_number: 65460 + bgp_controls: + - send-com + transport_data_plane: mpls + state: present + register: create_with_password + + - name: Update BGP Peer to remove remote as and local as number + aci_l3out_bgp_peer: + <<: *bgp_peer_with_password + remote_asn: 0 + local_as_number: 0 + state: present + register: update_remove_remote_local_as + + - name: Asser that BGP Peer with password, remote as and local as + assert: + that: + - create_with_password is changed + - create_with_password.previous == [] + - create_with_password.current.0.bgpPeerP.attributes.password is not defined + - create_with_password.current.0.bgpPeerP.children.0.bgpLocalAsnP.attributes.localAsn == "65460" + - create_with_password.current.0.bgpPeerP.children.2.bgpAsP.attributes.asn == "65450" + - update_remove_remote_local_as is changed + - update_remove_remote_local_as.previous != [] + - update_remove_remote_local_as.current.0.bgpPeerP.children | length == 1 + - update_remove_remote_local_as.current.0.bgpPeerP.children.0.bgpLocalAsnP is not defined + - update_remove_remote_local_as.current.0.bgpPeerP.children.0.bgpAsP is not defined + + - name: Execute tasks only for ACI v5+ because SR MPLS L3Out is not supported lower versions + when: version.current.0.topSystem.attributes.version is version('5', '>=') + block: + + - name: Create l3out in infra tenant + aci_l3out: &aci_infra_l3out + <<: *aci_info + tenant: infra + name: ansible_infra_l3out + vrf: overlay-1 + mpls: yes + domain: ansible_domain + route_control: export + l3protocol: bgp + state: present + + - name: Create l3out logical node profile in infra tenant + aci_l3out_logical_node_profile: + <<: *aci_info + tenant: infra + l3out: ansible_infra_l3out + node_profile: ansible_infra_l3out_node_profile + state: present + + - name: Create Infra BGP Peer with password + aci_l3out_bgp_peer: &infra_bgp_peer + <<: *aci_info + tenant: infra + l3out: ansible_infra_l3out + node_profile: ansible_infra_l3out_node_profile + ttl: 2 + bgp_infra_peer: true + bgp_password: ansible_test_password + peer_ip: 192.168.50.2 + remote_asn: 65450 + local_as_number: 65460 + peer_type: sr_mpls + bgp_controls: + - send-domain-path + transport_data_plane: sr_mpls + bgp_peer_prefix_policy: ansible_peer_prefix_profile + state: present + register: create_infra_bgp_peer + + - name: Query Infra BGP Peer + aci_l3out_bgp_peer: + <<: *infra_bgp_peer + state: query + register: query_infra_bgp_peer + + - name: Query all Infra BGP Peer + aci_l3out_bgp_peer: + <<: *infra_bgp_peer + bgp_infra_peer: true + state: query + register: query_all_infra_bgp_peer + + - name: Remove Infra BGP Peer + aci_l3out_bgp_peer: + <<: *infra_bgp_peer + state: absent + register: remove_infra_bgp_peer + + # CLEAN UP INFRA L3OUT + - name: Remove ansible_infra_l3out + aci_l3out: + <<: *aci_infra_l3out + state: absent + + - name: Asser that BGP Peer with password, remote as and local as + assert: + that: + - create_infra_bgp_peer is changed + - create_infra_bgp_peer.previous == [] + - create_infra_bgp_peer.current.0.bgpInfraPeerP.attributes.dn == "uni/tn-infra/out-ansible_infra_l3out/lnodep-ansible_infra_l3out_node_profile/infraPeerP-[192.168.50.2]" + - create_infra_bgp_peer.current.0.bgpInfraPeerP.attributes.peerT == "sr-mpls" + - create_infra_bgp_peer.current.0.bgpInfraPeerP.attributes.ctrlExt == "send-domain-path" + - create_infra_bgp_peer.current.0.bgpInfraPeerP.children.1.bgpRsPeerPfxPol.attributes.tnBgpPeerPfxPolName == "ansible_peer_prefix_profile" + - query_infra_bgp_peer is not changed + - query_infra_bgp_peer.current | length == 1 + - query_infra_bgp_peer.current.0.bgpInfraPeerP.attributes.dn == "uni/tn-infra/out-ansible_infra_l3out/lnodep-ansible_infra_l3out_node_profile/infraPeerP-[192.168.50.2]" + - query_all_infra_bgp_peer is not changed + - query_all_infra_bgp_peer.current | length >= 1 + - remove_infra_bgp_peer is changed + - remove_infra_bgp_peer.previous.0.bgpInfraPeerP.attributes.dn == "uni/tn-infra/out-ansible_infra_l3out/lnodep-ansible_infra_l3out_node_profile/infraPeerP-[192.168.50.2]" + - remove_infra_bgp_peer.previous.0.bgpInfraPeerP.attributes.peerT == "sr-mpls" + - remove_infra_bgp_peer.previous.0.bgpInfraPeerP.attributes.ctrlExt == "send-domain-path" + - remove_infra_bgp_peer.previous.0.bgpInfraPeerP.children.1.bgpRsPeerPfxPol.attributes.tnBgpPeerPfxPolName == "ansible_peer_prefix_profile" + - remove_infra_bgp_peer.current == [] + # CLEAN UP - name: Remove ansible_tenant - aci_tenant: + cisco.aci.aci_tenant: <<: *aci_info tenant: ansible_tenant state: absent - name: Remove ansible_l3ext_domain - aci_domain: + cisco.aci.aci_domain: <<: *aci_info domain: ansible_l3ext_domain domain_type: l3dom state: absent - name: Remove ansible_port_channel_ipg - aci_interface_policy_leaf_policy_group: + cisco.aci.aci_interface_policy_leaf_policy_group: <<: *aci_info lag_type: link policy_group: ansible_port_channel_ipg state: absent - name: Remove ansible_vpc_ipg - aci_interface_policy_leaf_policy_group: + cisco.aci.aci_interface_policy_leaf_policy_group: <<: *aci_info lag_type: node policy_group: ansible_vpc_ipg diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_l3out_bgp_protocol_profile/tasks/main.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_l3out_bgp_protocol_profile/tasks/main.yml index 85b43726c..26d0f436f 100644 --- a/ansible_collections/cisco/aci/tests/integration/targets/aci_l3out_bgp_protocol_profile/tasks/main.yml +++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_l3out_bgp_protocol_profile/tasks/main.yml @@ -4,12 +4,12 @@ # GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) - name: Test that we have an ACI APIC host, ACI username and ACI password - fail: + ansible.builtin.fail: msg: 'Please define the following variables: aci_hostname, aci_username and aci_password.' when: aci_hostname is not defined or aci_username is not defined or aci_password is not defined - name: Set vars - set_fact: + ansible.builtin.set_fact: aci_info: &aci_info host: "{{ aci_hostname }}" username: "{{ aci_username }}" @@ -21,26 +21,26 @@ # CLEAN ENVIRONMENT - name: Remove the ansible_tenant - aci_tenant: &aci_tenant_absent + cisco.aci.aci_tenant: &aci_tenant_absent <<: *aci_info tenant: ansible_tenant state: absent - name: Verify Cloud and Non-Cloud Sites in use. - include_tasks: ../../../../../../integration/targets/aci_cloud_provider/tasks/main.yml + ansible.builtin.include_tasks: ../../../../../../integration/targets/aci_cloud_provider/tasks/main.yml - name: Execute tasks only for non-cloud sites when: query_cloud.current == [] # This condition will execute only non-cloud sites block: # block specifies execution of tasks within, based on conditions - name: Add a new tenant - aci_tenant: &aci_tenant_present + cisco.aci.aci_tenant: &aci_tenant_present <<: *aci_info tenant: ansible_tenant description: Ansible tenant state: present - name: Add a new l3out - aci_l3out: + cisco.aci.aci_l3out: <<: *aci_info tenant: ansible_tenant l3out: ansible_l3out @@ -50,7 +50,7 @@ state: present - name: Add a new logical node profile - aci_l3out_logical_node_profile: + cisco.aci.aci_l3out_logical_node_profile: <<: *aci_info tenant: ansible_tenant l3out: ansible_l3out @@ -59,7 +59,7 @@ state: present - name: Add a second logical node profile - aci_l3out_logical_node_profile: + cisco.aci.aci_l3out_logical_node_profile: <<: *aci_info tenant: ansible_tenant l3out: ansible_l3out @@ -68,7 +68,7 @@ state: present - name: Add a new BGP timers policy - aci_bgp_timers_policy: + cisco.aci.aci_bgp_timers_policy: <<: *aci_info tenant: ansible_tenant bgp_timers_policy: ansible_bgp_timers_policy @@ -76,7 +76,7 @@ state: present - name: Add a new BGP protocol profile - aci_bgp_best_path_policy: + cisco.aci.aci_bgp_best_path_policy: <<: *aci_info tenant: ansible_tenant bgp_best_path_policy: ansible_bgp_best_path_policy @@ -84,7 +84,7 @@ state: present - name: Add a BGP protocol profile (check_mode) - aci_l3out_bgp_protocol_profile: &aci_l3out_bgp_protocol_profile_present + cisco.aci.aci_l3out_bgp_protocol_profile: &aci_l3out_bgp_protocol_profile_present <<: *aci_info tenant: ansible_tenant l3out: ansible_l3out @@ -96,17 +96,17 @@ register: cm_add_bgp_protocol_profile - name: Add a BGP protocol profile (normal_mode) - aci_l3out_bgp_protocol_profile: + cisco.aci.aci_l3out_bgp_protocol_profile: <<: *aci_l3out_bgp_protocol_profile_present register: nm_add_bgp_protocol_profile - name: Add the first BGP protocol profile again - testing idempotency - aci_l3out_bgp_protocol_profile: + cisco.aci.aci_l3out_bgp_protocol_profile: <<: *aci_l3out_bgp_protocol_profile_present register: nm_add_bgp_protocol_profile_idempotency - name: Add a second BGP protocol profile (normal_mode) - aci_l3out_bgp_protocol_profile: + cisco.aci.aci_l3out_bgp_protocol_profile: <<: *aci_info tenant: ansible_tenant l3out: ansible_l3out @@ -115,7 +115,7 @@ register: nm_add_bgp_protocol_profile_2 - name: Asserts for BGP protocol profiles creation tasks - assert: + ansible.builtin.assert: that: - cm_add_bgp_protocol_profile is changed - cm_add_bgp_protocol_profile.previous == [] @@ -128,19 +128,19 @@ - nm_add_bgp_protocol_profile_2.previous == [] - name: Query all BGP best path policies - aci_l3out_bgp_protocol_profile: + cisco.aci.aci_l3out_bgp_protocol_profile: <<: *aci_info state: query register: query_all_bgp_protocol_profile - name: Query ansible_bgp_protocol_profile_1 - aci_l3out_bgp_protocol_profile: + cisco.aci.aci_l3out_bgp_protocol_profile: <<: *aci_l3out_bgp_protocol_profile_present state: query register: query_ansible_bgp_protocol_profile_1 - name: Asserts query tasks - assert: + ansible.builtin.assert: that: - query_all_bgp_protocol_profile is not changed - query_all_bgp_protocol_profile.current|length >= 2 @@ -151,24 +151,24 @@ - query_ansible_bgp_protocol_profile_1.current.0.bgpProtP.children.1.bgpRsBgpNodeCtxPol.attributes.state == "formed" - name: Remove BGP protocol profile (check_mode) - aci_l3out_bgp_protocol_profile: &bgp_protocol_profile_absent + cisco.aci.aci_l3out_bgp_protocol_profile: &bgp_protocol_profile_absent <<: *aci_l3out_bgp_protocol_profile_present state: absent check_mode: true register: cm_remove_bgp_protocol_profile - name: Remove BGP protocol profile (normal_mode) - aci_l3out_bgp_protocol_profile: + cisco.aci.aci_l3out_bgp_protocol_profile: <<: *bgp_protocol_profile_absent register: nm_remove_bgp_protocol_profile - name: Remove BGP protocol profile - testing idempotency - aci_l3out_bgp_protocol_profile: + cisco.aci.aci_l3out_bgp_protocol_profile: <<: *bgp_protocol_profile_absent register: nm_remove_bgp_protocol_profile_idempotency - name: Asserts deletion tasks - assert: + ansible.builtin.assert: that: - cm_remove_bgp_protocol_profile is changed - cm_remove_bgp_protocol_profile.proposed == {} @@ -179,6 +179,6 @@ - nm_remove_bgp_protocol_profile_idempotency.previous == [] - name: Remove the ansible_tenant - cleanup before ending tests - aci_tenant: + cisco.aci.aci_tenant: <<: *aci_tenant_present state: absent \ No newline at end of file diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_l3out_dhcp_relay_label/aliases b/ansible_collections/cisco/aci/tests/integration/targets/aci_l3out_dhcp_relay_label/aliases new file mode 100644 index 000000000..209b793f9 --- /dev/null +++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_l3out_dhcp_relay_label/aliases @@ -0,0 +1,2 @@ +# No ACI simulator yet, so not enabled +# unsupported diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_l3out_dhcp_relay_label/tasks/main.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_l3out_dhcp_relay_label/tasks/main.yml new file mode 100644 index 000000000..5b34dadf1 --- /dev/null +++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_l3out_dhcp_relay_label/tasks/main.yml @@ -0,0 +1,242 @@ +# Test code for the ACI modules +# Copyright: (c) 2023, Gaspard Micol (@gmicol) + +# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) + +- name: Test that we have an ACI APIC host, ACI username and ACI password + ansible.builtin.fail: + msg: 'Please define the following variables: aci_hostname, aci_username and aci_password.' + when: aci_hostname is not defined or aci_username is not defined or aci_password is not defined + +- name: Set vars + ansible.builtin.set_fact: + aci_info: &aci_info + host: "{{ aci_hostname }}" + username: "{{ aci_username }}" + password: "{{ aci_password }}" + validate_certs: '{{ aci_validate_certs | default(false) }}' + use_ssl: '{{ aci_use_ssl | default(true) }}' + use_proxy: '{{ aci_use_proxy | default(true) }}' + output_level: debug + +# CLEAN ENVIRONMENT +- name: Remove the ansible_tenant + cisco.aci.aci_tenant: &aci_tenant_absent + <<: *aci_info + tenant: ansible_tenant + state: absent + +- name: Verify Cloud and Non-Cloud Sites in use. + ansible.builtin.include_tasks: ../../../../../../integration/targets/aci_cloud_provider/tasks/main.yml + +- name: Execute tasks only for non-cloud sites + when: query_cloud.current == [] # This condition will execute only non-cloud sites + block: # block specifies execution of tasks within, based on conditions + - name: Add a new tenant + cisco.aci.aci_tenant: &aci_tenant_present + <<: *aci_info + tenant: ansible_tenant + description: Ansible tenant + state: present + + - name: Add new Domain + cisco.aci.aci_domain: &aci_domain_present + <<: *aci_info + domain: ansible_dom + domain_type: l3dom + state: present + + - name: Addd a new VRF + cisco.aci.aci_vrf: &aci_vrf_present + <<: *aci_tenant_present + vrf: ansible_vrf + description: Ansible VRF + + - name: Add a new L3Out + cisco.aci.aci_l3out: &aci_l3out_present + <<: *aci_vrf_present + l3out: ansible_l3out + domain: ansible_dom + route_control: export + l3protocol: eigrp + asn: 1 + description: Ansible L3Out + + - name: Add a new L3Out logical node profile + cisco.aci.aci_l3out_logical_node_profile: &aci_l3out_node_profile_present + <<: *aci_tenant_present + l3out: ansible_l3out + node_profile: ansible_l3out_node_profile + description: Ansible L3Out Logical Node Profile + + - name: Add a new L3Out logical interface profile + cisco.aci.aci_l3out_logical_interface_profile: &aci_l3out_interface_profile_present + <<: *aci_l3out_node_profile_present + interface_profile: ansible_l3out_interface_profile + description: First Ansible L3Out Logical Interface Profile + + - name: Add a new DHCP relay policy in infra + cisco.aci.aci_dhcp_relay: + <<: *aci_info + relay_policy: ansible_dhcp_relay_policy_infra + description: Ansible DHCP Relay Policy in infra + state: present + + - name: Add a new DHCP relay policy in ansible tenant + cisco.aci.aci_dhcp_relay: + <<: *aci_tenant_present + relay_policy: ansible_dhcp_relay_policy_tenant + description: Ansible DHCP Relay Policy in tenant + state: present + + - name: Add a new DHCP option policy + cisco.aci.aci_dhcp_option_policy: + <<: *aci_tenant_present + dhcp_option_policy: ansible_dhcp_option_policy + description: Ansible DHCP Option Policy + state: present + + - name: Add L3Out DHCP Relay Label to first interface profile (check mode) + cisco.aci.aci_l3out_dhcp_relay_label: &aci_l3out_dhcp_relay_label_present + <<: *aci_l3out_interface_profile_present + dhcp_relay_label: ansible_dhcp_relay_policy_tenant + scope: tenant + dhcp_option_policy: ansible_dhcp_option_policy + description: First Ansible DHCP Relay Label + check_mode: true + register: cm_add_l3out_dhcp_relay_label + + - name: Add L3Out DHCP Relay Label to first interface profile (normal mode) + cisco.aci.aci_l3out_dhcp_relay_label: + <<: *aci_l3out_dhcp_relay_label_present + register: nm_add_l3out_dhcp_relay_label + + - name: Add L3Out DHCP relay label to first interface profile again - testing idempotency + cisco.aci.aci_l3out_dhcp_relay_label: + <<: *aci_l3out_dhcp_relay_label_present + register: nm_add_l3out_dhcp_relay_label_idempotency + + - name: Create a second L3Out logical interface profile + cisco.aci.aci_l3out_logical_interface_profile: &aci_l3out_interface_profile_present_2 + <<: *aci_l3out_node_profile_present + interface_profile: ansible_l3out_interface_profile_2 + description: Second Ansible L3Out Logical Interface Profile + + - name: Add L3Out DHCP Relay Label to second interface profile (normal_mode) + cisco.aci.aci_l3out_dhcp_relay_label: + <<: *aci_l3out_interface_profile_present_2 + dhcp_relay_label: ansible_dhcp_relay_policy_infra + description: Second Ansible DHCP Relay Label + state: present + register: nm_add_l3out_dhcp_relay_label_2 + + - name: Asserts for DHCP relay labels creation tasks + ansible.builtin.assert: + that: + - cm_add_l3out_dhcp_relay_label is changed + - cm_add_l3out_dhcp_relay_label.previous == [] + - cm_add_l3out_dhcp_relay_label.current == [] + - nm_add_l3out_dhcp_relay_label is changed + - nm_add_l3out_dhcp_relay_label.current.0.dhcpLbl.attributes.name == "ansible_dhcp_relay_policy_tenant" + - nm_add_l3out_dhcp_relay_label.current.0.dhcpLbl.attributes.owner == "tenant" + - nm_add_l3out_dhcp_relay_label.current.0.dhcpLbl.children.0.dhcpRsDhcpOptionPol.attributes.tnDhcpOptionPolName == "ansible_dhcp_option_policy" + - nm_add_l3out_dhcp_relay_label_idempotency is not changed + - nm_add_l3out_dhcp_relay_label_2 is changed + - nm_add_l3out_dhcp_relay_label_2.previous == [] + - nm_add_l3out_dhcp_relay_label_2.current.0.dhcpLbl.attributes.name == "ansible_dhcp_relay_policy_infra" + - nm_add_l3out_dhcp_relay_label_2.current.0.dhcpLbl.attributes.owner == "infra" + + - name: Query all l3Out DHCP relay labels + cisco.aci.aci_l3out_dhcp_relay_label: + <<: *aci_info + state: query + register: query_all_l3out_dhcp_relay_label + + - name: Query first L3Out DHCP relay label + cisco.aci.aci_l3out_dhcp_relay_label: + <<: *aci_l3out_dhcp_relay_label_present + state: query + register: query_ansible_l3out_dhcp_relay_label_1 + + - name: Asserts query tasks + ansible.builtin.assert: + that: + - query_all_l3out_dhcp_relay_label is not changed + - query_all_l3out_dhcp_relay_label.current|length >= 2 + - query_ansible_l3out_dhcp_relay_label_1 is not changed + - query_ansible_l3out_dhcp_relay_label_1.current.0.dhcpLbl.attributes.name == "ansible_dhcp_relay_policy_tenant" + - query_ansible_l3out_dhcp_relay_label_1.current.0.dhcpLbl.attributes.owner == "tenant" + - query_ansible_l3out_dhcp_relay_label_1.current.0.dhcpLbl.children.0.dhcpRsDhcpOptionPol.attributes.tnDhcpOptionPolName == "ansible_dhcp_option_policy" + + - name: Update first L3out DHCP relay label by deleting current DHCP options (check_mode) + cisco.aci.aci_l3out_dhcp_relay_label: &aci_l3out_dhcp_relay_label_update + <<: *aci_l3out_dhcp_relay_label_present + dhcp_option_policy: "" + check_mode: true + register: cm_update_l3out_dhcp_relay_label + + - name: Update first L3out DHCP relay label by deleting current DHCP options (normal_mode) + cisco.aci.aci_l3out_dhcp_relay_label: + <<: *aci_l3out_dhcp_relay_label_update + register: nm_update_l3out_dhcp_relay_label + + - name: Update first L3out DHCP relay label by deleting current DHCP options again - testing idempotency + cisco.aci.aci_l3out_dhcp_relay_label: + <<: *aci_l3out_dhcp_relay_label_update + register: nm_update_l3out_dhcp_relay_label_idempotency + + - name: Query updated first L3Out DHCP relay label + cisco.aci.aci_l3out_dhcp_relay_label: + <<: *aci_l3out_dhcp_relay_label_update + state: query + register: query_ansible_l3out_dhcp_relay_label_1_updated + + - name: Asserts for DHCP relay labels update tasks + ansible.builtin.assert: + that: + - cm_update_l3out_dhcp_relay_label is changed + - cm_update_l3out_dhcp_relay_label.previous == cm_update_l3out_dhcp_relay_label.current + - nm_update_l3out_dhcp_relay_label is changed + - nm_update_l3out_dhcp_relay_label.current.0.dhcpLbl.children.0.dhcpRsDhcpOptionPol.attributes.tnDhcpOptionPolName == "" + - nm_update_l3out_dhcp_relay_label_idempotency is not changed + - query_ansible_l3out_dhcp_relay_label_1_updated is not changed + - query_ansible_l3out_dhcp_relay_label_1_updated.current.0.dhcpLbl.children.0.dhcpRsDhcpOptionPol.attributes.tDn == "uni/tn-common/dhcpoptpol-default" + - query_ansible_l3out_dhcp_relay_label_1_updated.current.0.dhcpLbl.children.0.dhcpRsDhcpOptionPol.attributes.tnDhcpOptionPolName == "" + + - name: Remove L3Out DHCP relay label from interface profile (check_mode) + cisco.aci.aci_l3out_dhcp_relay_label: &l3out_dhcp_relay_label_absent + <<: *aci_l3out_dhcp_relay_label_update + state: absent + check_mode: true + register: cm_remove_l3out_dhcp_relay_label + + - name: Remove L3Out DHCP relay label from interface profile (normal_mode) + cisco.aci.aci_l3out_dhcp_relay_label: + <<: *l3out_dhcp_relay_label_absent + register: nm_remove_l3out_dhcp_relay_label + + - name: Remove L3Out DHCP relay label from interface profile - testing idempotency + cisco.aci.aci_l3out_dhcp_relay_label: + <<: *l3out_dhcp_relay_label_absent + register: nm_remove_l3out_dhcp_relay_label_idempotency + + - name: Asserts deletion tasks + ansible.builtin.assert: + that: + - cm_remove_l3out_dhcp_relay_label is changed + - cm_remove_l3out_dhcp_relay_label.proposed == {} + - nm_remove_l3out_dhcp_relay_label is changed + - nm_remove_l3out_dhcp_relay_label.previous != [] + - nm_remove_l3out_dhcp_relay_label.method == "DELETE" + - nm_remove_l3out_dhcp_relay_label_idempotency is not changed + - nm_remove_l3out_dhcp_relay_label_idempotency.previous == [] + + - name: Remove the ansible_tenant - cleanup before ending tests + cisco.aci.aci_tenant: + <<: *aci_tenant_present + state: absent + + - name: Remove the ansible_dom - cleanup before ending tests + cisco.aci.aci_domain: + <<: *aci_domain_present + state: absent diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_l3out_eigrp_interface_profile/aliases b/ansible_collections/cisco/aci/tests/integration/targets/aci_l3out_eigrp_interface_profile/aliases new file mode 100644 index 000000000..209b793f9 --- /dev/null +++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_l3out_eigrp_interface_profile/aliases @@ -0,0 +1,2 @@ +# No ACI simulator yet, so not enabled +# unsupported diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_l3out_eigrp_interface_profile/tasks/main.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_l3out_eigrp_interface_profile/tasks/main.yml new file mode 100644 index 000000000..8607897b1 --- /dev/null +++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_l3out_eigrp_interface_profile/tasks/main.yml @@ -0,0 +1,224 @@ +# Test code for the ACI modules +# Copyright: (c) 2023, Gaspard Micol (@gmicol) + +# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) + +- name: Test that we have an ACI APIC host, ACI username and ACI password + ansible.builtin.fail: + msg: 'Please define the following variables: aci_hostname, aci_username and aci_password.' + when: aci_hostname is not defined or aci_username is not defined or aci_password is not defined + +- name: Set vars + ansible.builtin.set_fact: + aci_info: &aci_info + host: "{{ aci_hostname }}" + username: "{{ aci_username }}" + password: "{{ aci_password }}" + validate_certs: '{{ aci_validate_certs | default(false) }}' + use_ssl: '{{ aci_use_ssl | default(true) }}' + use_proxy: '{{ aci_use_proxy | default(true) }}' + output_level: debug + +# CLEAN ENVIRONMENT +- name: Remove the ansible_tenant + cisco.aci.aci_tenant: &aci_tenant_absent + <<: *aci_info + tenant: ansible_tenant + state: absent + +- name: Verify Cloud and Non-Cloud Sites in use. + ansible.builtin.include_tasks: ../../../../../../integration/targets/aci_cloud_provider/tasks/main.yml + +- name: Execute tasks only for non-cloud sites + when: query_cloud.current == [] # This condition will execute only non-cloud sites + block: # block specifies execution of tasks within, based on conditions + - name: Add a new tenant + cisco.aci.aci_tenant: &aci_tenant_present + <<: *aci_info + tenant: ansible_tenant + description: Ansible tenant + state: present + + - name: Add new Domain + cisco.aci.aci_domain: &aci_domain_present + <<: *aci_info + domain: ansible_dom + domain_type: l3dom + state: present + + - name: Addd a new VRF + cisco.aci.aci_vrf: &aci_vrf_present + <<: *aci_tenant_present + vrf: ansible_vrf + description: Ansible VRF + + - name: Add a new L3Out + cisco.aci.aci_l3out: &aci_l3out_present + <<: *aci_vrf_present + l3out: ansible_l3out + domain: ansible_dom + route_control: export + l3protocol: eigrp + asn: 1 + description: Ansible L3Out + + - name: Add a new L3Out logical node profile + cisco.aci.aci_l3out_logical_node_profile: &aci_l3out_node_profile_present + <<: *aci_tenant_present + l3out: ansible_l3out + node_profile: ansible_l3out_node_profile + description: Ansible L3Out Logical Node Profile + + - name: Add a new L3Out logical interface profile + cisco.aci.aci_l3out_logical_interface_profile: &aci_l3out_interface_profile_present + <<: *aci_l3out_node_profile_present + interface_profile: ansible_l3out_interface_profile + description: First Ansible L3Out Logical Interface Profile + + - name: Add a new eigrp interface policy + cisco.aci.aci_interface_policy_eigrp: + <<: *aci_tenant_present + eigrp: ansible_eigrp_interface_policy + description: Ansible EIGRP Interface Policy + state: present + + - name: Add a new keychain policy + cisco.aci.aci_keychain_policy: + <<: *aci_tenant_present + keychain_policy: ansible_keychain_policy + description: Ansible Keychain Policy + state: present + + - name: Add eigrp policy to first interface profile (check mode) + cisco.aci.aci_l3out_eigrp_interface_profile: &aci_l3out_eigrp_interface_profile_present + <<: *aci_l3out_interface_profile_present + eigrp_policy: ansible_eigrp_interface_policy + eigrp_keychain_policy: ansible_keychain_policy + description: First Ansible EIGRP Interface Profile + check_mode: true + register: cm_add_l3out_eigrp_interface_profile + + - name: Add eigrp policy to first interface profile (normal mode) + cisco.aci.aci_l3out_eigrp_interface_profile: + <<: *aci_l3out_eigrp_interface_profile_present + register: nm_add_l3out_eigrp_interface_profile + + - name: Add eigrp interface profile again - testing idempotency + cisco.aci.aci_l3out_eigrp_interface_profile: + <<: *aci_l3out_eigrp_interface_profile_present + register: nm_add_l3out_eigrp_interface_profile_idempotency + + - name: Create a second L3Out logical interface profile + cisco.aci.aci_l3out_logical_interface_profile: &aci_l3out_interface_profile_present_2 + <<: *aci_l3out_node_profile_present + interface_profile: ansible_l3out_interface_profile_2 + description: Second Ansible L3Out Logical Interface Profile + + - name: Add eigrp policy to second interface profile (normal_mode) + cisco.aci.aci_l3out_eigrp_interface_profile: + <<: *aci_l3out_interface_profile_present_2 + eigrp_policy: ansible_eigrp_interface_policy + description: Second Ansible EIGRP Interface Profile + state: present + register: nm_add_l3out_eigrp_interface_profile_2 + + - name: Asserts for eigrp interface policies creation tasks + ansible.builtin.assert: + that: + - cm_add_l3out_eigrp_interface_profile is changed + - cm_add_l3out_eigrp_interface_profile.previous == [] + - cm_add_l3out_eigrp_interface_profile.current == [] + - nm_add_l3out_eigrp_interface_profile is changed + - nm_add_l3out_eigrp_interface_profile.current.0.eigrpIfP.children.0.eigrpAuthIfP.children.0.eigrpRsKeyChainPol.attributes.tnFvKeyChainPolName == "ansible_keychain_policy" + - nm_add_l3out_eigrp_interface_profile.current.0.eigrpIfP.children.1.eigrpRsIfPol.attributes.tnEigrpIfPolName == "ansible_eigrp_interface_policy" + - nm_add_l3out_eigrp_interface_profile_idempotency is not changed + - nm_add_l3out_eigrp_interface_profile_2 is changed + - nm_add_l3out_eigrp_interface_profile_2.previous == [] + - nm_add_l3out_eigrp_interface_profile_2.current.0.eigrpIfP.children.0.eigrpRsIfPol.attributes.tnEigrpIfPolName == "ansible_eigrp_interface_policy" + + - name: Query all eigrp interface profiles + cisco.aci.aci_l3out_eigrp_interface_profile: + <<: *aci_info + state: query + register: query_all_l3out_eigrp_interface_profile + + - name: Query first eigrp interface profile + cisco.aci.aci_l3out_eigrp_interface_profile: + <<: *aci_l3out_eigrp_interface_profile_present + state: query + register: query_ansible_l3out_eigrp_interface_profile_1 + + - name: Asserts query tasks + ansible.builtin.assert: + that: + - query_all_l3out_eigrp_interface_profile is not changed + - query_all_l3out_eigrp_interface_profile.current|length >= 2 + - query_ansible_l3out_eigrp_interface_profile_1 is not changed + - query_ansible_l3out_eigrp_interface_profile_1.current.0.eigrpIfP.children.0.eigrpAuthIfP.children.0.eigrpRsKeyChainPol.attributes.tDn == "uni/tn-ansible_tenant/keychainp-ansible_keychain_policy" + - query_ansible_l3out_eigrp_interface_profile_1.current.0.eigrpIfP.children.0.eigrpAuthIfP.children.0.eigrpRsKeyChainPol.attributes.state == "formed" + - query_ansible_l3out_eigrp_interface_profile_1.current.0.eigrpIfP.children.1.eigrpRsIfPol.attributes.tDn == "uni/tn-ansible_tenant/eigrpIfPol-ansible_eigrp_interface_policy" + - query_ansible_l3out_eigrp_interface_profile_1.current.0.eigrpIfP.children.1.eigrpRsIfPol.attributes.state == "formed" + + - name: Remove authentification from first eigrp interface profile (check mode) + cisco.aci.aci_l3out_eigrp_interface_profile: &aci_l3out_eigrp_interface_profile_remove_auth + <<: *aci_l3out_eigrp_interface_profile_present + eigrp_keychain_policy: "" + check_mode: true + register: cm_remove_auth_l3out_eigrp_interface_profile + + - name: Remove authentification from first eigrp interface profile (normal mode) + cisco.aci.aci_l3out_eigrp_interface_profile: + <<: *aci_l3out_eigrp_interface_profile_remove_auth + register: nm_remove_auth_l3out_eigrp_interface_profile + + - name: Remove authentification from first eigrp interface profile again - testing idempotency + cisco.aci.aci_l3out_eigrp_interface_profile: + <<: *aci_l3out_eigrp_interface_profile_remove_auth + register: nm_remove_auth_eigrp_interface_profile_idempotency + + - name: Asserts authentification removal tasks + ansible.builtin.assert: + that: + - cm_remove_auth_l3out_eigrp_interface_profile is changed + - cm_remove_auth_l3out_eigrp_interface_profile.current == cm_remove_auth_l3out_eigrp_interface_profile.previous + - nm_remove_auth_l3out_eigrp_interface_profile is changed + - nm_remove_auth_l3out_eigrp_interface_profile.current.0.eigrpIfP.children|length == 1 + - nm_remove_auth_eigrp_interface_profile_idempotency is not changed + + - name: Remove eigrp interface profile (check_mode) + cisco.aci.aci_l3out_eigrp_interface_profile: &l3out_eigrp_interface_profile_absent + <<: *aci_l3out_eigrp_interface_profile_present + state: absent + check_mode: true + register: cm_remove_l3out_eigrp_interface_profile + + - name: Remove eigrp interface profile (normal_mode) + cisco.aci.aci_l3out_eigrp_interface_profile: + <<: *l3out_eigrp_interface_profile_absent + register: nm_remove_l3out_eigrp_interface_profile + + - name: Remove eigrp interface profile - testing idempotency + cisco.aci.aci_l3out_eigrp_interface_profile: + <<: *l3out_eigrp_interface_profile_absent + register: nm_remove_l3out_eigrp_interface_profile_idempotency + + - name: Asserts deletion tasks + ansible.builtin.assert: + that: + - cm_remove_l3out_eigrp_interface_profile is changed + - cm_remove_l3out_eigrp_interface_profile.proposed == {} + - nm_remove_l3out_eigrp_interface_profile is changed + - nm_remove_l3out_eigrp_interface_profile.previous != [] + - nm_remove_l3out_eigrp_interface_profile.method == "DELETE" + - nm_remove_l3out_eigrp_interface_profile_idempotency is not changed + - nm_remove_l3out_eigrp_interface_profile_idempotency.previous == [] + + - name: Remove the ansible_tenant - cleanup before ending tests + cisco.aci.aci_tenant: + <<: *aci_tenant_present + state: absent + + - name: Remove the ansible_dom - cleanup before ending tests + cisco.aci.aci_domain: + <<: *aci_domain_present + state: absent diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_l3out_extepg/tasks/main.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_l3out_extepg/tasks/main.yml index d52fb5ef4..61291cb6a 100644 --- a/ansible_collections/cisco/aci/tests/integration/targets/aci_l3out_extepg/tasks/main.yml +++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_l3out_extepg/tasks/main.yml @@ -29,7 +29,7 @@ block: - name: Query system information - aci_system: + cisco.aci.aci_system: <<: *aci_info id: 1 state: query diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_l3out_extepg_to_contract/tasks/main.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_l3out_extepg_to_contract/tasks/main.yml index c49475d0a..d8437c522 100644 --- a/ansible_collections/cisco/aci/tests/integration/targets/aci_l3out_extepg_to_contract/tasks/main.yml +++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_l3out_extepg_to_contract/tasks/main.yml @@ -1,15 +1,16 @@ # Test code for the ACI modules # Copyright: (c) 2020, Shreyas Srish (@shrsr) +# Copyright: (c) 2023, Akini Ross (@akinross) # GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) -- name: Test that we have an ACI APIC host, ACI username and ACI password - fail: +- name: Test that we have an ACI APIC host, ACI username and ACI password + ansible.builtin.fail: msg: 'Please define the following variables: aci_hostname, aci_username and aci_password.' when: aci_hostname is not defined or aci_username is not defined or aci_password is not defined - name: Set vars - set_fact: + ansible.builtin.set_fact: aci_info: &aci_info host: "{{ aci_hostname }}" username: "{{ aci_username }}" @@ -21,28 +22,35 @@ # CLEAN ENVIRONMENT - name: Remove the ansible_tenant - aci_tenant: - <<: *aci_info - tenant: ansible_tenant + cisco.aci.aci_tenant: + <<: *aci_info + tenant: ansible_test state: absent +- name: Query system information + cisco.aci.aci_system: + <<: *aci_info + id: 1 + state: query + register: version + - name: Verify Cloud and Non-Cloud Sites in use. - include_tasks: ../../../../../../integration/targets/aci_cloud_provider/tasks/main.yml + ansible.builtin.include_tasks: ../../../../../../integration/targets/aci_cloud_provider/tasks/main.yml - name: Execute tasks only for non-cloud sites when: query_cloud.current == [] # This condition will execute only non-cloud sites block: # block specifies execution of tasks within, based on conditions - name: Add a new tenant - aci_tenant: + cisco.aci.aci_tenant: <<: *aci_info - tenant: ansible_tenant + tenant: ansible_test description: Ansible tenant state: present - name: Add a new l3out - aci_l3out: + cisco.aci.aci_l3out: <<: *aci_info - tenant: ansible_tenant + tenant: ansible_test name: ansible_l3out description: l3out for Ansible tenant domain: ansible_dom @@ -52,91 +60,202 @@ state: present - name: Add a new ExtEpg - aci_l3out_extepg: + cisco.aci.aci_l3out_extepg: <<: *aci_info - tenant: ansible_tenant + tenant: ansible_test 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: + + - name: Bind External End Point Groups to Contracts (check-mode) + cisco.aci.aci_l3out_extepg_to_contract: &aci_ext_epg_present <<: *aci_info - tenant: ansible_tenant + tenant: ansible_test l3out: ansible_l3out extepg: ansible_extEpg contract: ansible_contract contract_type: provider state: present - register: bind_extepg_provider_contract + register: cm_bind_extepg_provider_contract + check_mode: true + + - name: Bind External End Point Groups to Contracts + aci_l3out_extepg_to_contract: + <<: *aci_ext_epg_present + register: nm_bind_extepg_provider_contract + + - name: Bind External End Point Groups to Contracts again + aci_l3out_extepg_to_contract: + <<: *aci_ext_epg_present + register: nm_bind_extepg_provider_contract_again - name: Verify bind_extepg_provider_contract - assert: + ansible.builtin.assert: that: - - bind_extepg_provider_contract.current.0.fvRsProv.attributes.dn == "uni/tn-ansible_tenant/out-ansible_l3out/instP-ansible_extEpg/rsprov-ansible_contract" - - bind_extepg_provider_contract.current.0.fvRsProv.attributes.annotation == 'orchestrator:ansible' + - cm_bind_extepg_provider_contract is changed + - cm_bind_extepg_provider_contract.previous == [] + - cm_bind_extepg_provider_contract.proposed.fvRsProv.attributes.dn == "uni/tn-ansible_test/out-ansible_l3out/instP-ansible_extEpg/rsprov-ansible_contract" + - cm_bind_extepg_provider_contract.proposed.fvRsProv.attributes.annotation == "orchestrator:ansible" + - cm_bind_extepg_provider_contract.proposed.fvRsProv.attributes.tnVzBrCPName == "ansible_contract" + - nm_bind_extepg_provider_contract is changed + - nm_bind_extepg_provider_contract.previous == [] + - nm_bind_extepg_provider_contract.current.0.fvRsProv.attributes.dn == "uni/tn-ansible_test/out-ansible_l3out/instP-ansible_extEpg/rsprov-ansible_contract" + - nm_bind_extepg_provider_contract.current.0.fvRsProv.attributes.annotation == "orchestrator:ansible" + - nm_bind_extepg_provider_contract.current.0.fvRsProv.attributes.tnVzBrCPName == "ansible_contract" + - nm_bind_extepg_provider_contract_again is not changed + - nm_bind_extepg_provider_contract_again.previous.0.fvRsProv.attributes.dn == "uni/tn-ansible_test/out-ansible_l3out/instP-ansible_extEpg/rsprov-ansible_contract" + - nm_bind_extepg_provider_contract_again.previous.0.fvRsProv.attributes.annotation == "orchestrator:ansible" + - nm_bind_extepg_provider_contract_again.previous.0.fvRsProv.attributes.tnVzBrCPName == "ansible_contract" + - nm_bind_extepg_provider_contract_again.current.0.fvRsProv.attributes.dn == "uni/tn-ansible_test/out-ansible_l3out/instP-ansible_extEpg/rsprov-ansible_contract" + - nm_bind_extepg_provider_contract_again.current.0.fvRsProv.attributes.annotation == "orchestrator:ansible" + - nm_bind_extepg_provider_contract_again.current.0.fvRsProv.attributes.tnVzBrCPName == "ansible_contract" - - name: Bind second External End Point Groups to Contracts - aci_l3out_extepg_to_contract: + - name: Bind second External End Point Groups to Contracts with contract label and subject label + cisco.aci.aci_l3out_extepg_to_contract: <<: *aci_info - tenant: ansible_tenant + tenant: ansible_test l3out: ansible_l3out extepg: ansible_extEpg contract: ansible_contract2 contract_type: provider + contract_label: anstest_contract_label + subject_label: anstest_subject_label state: present register: bind_extepg_provider_contract_2 - name: Verify bind_extepg_provider_contract_2 - assert: + ansible.builtin.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" + - bind_extepg_provider_contract_2.current.0.fvRsProv.attributes.dn == "uni/tn-ansible_test/out-ansible_l3out/instP-ansible_extEpg/rsprov-ansible_contract2" + - bind_extepg_provider_contract_2.current.0.fvRsProv.attributes.tnVzBrCPName == "ansible_contract2" + - bind_extepg_provider_contract_2.current.0.fvRsProv.children.0.vzProvSubjLbl.attributes.name == "anstest_subject_label" + - bind_extepg_provider_contract_2.current.0.fvRsProv.children.1.vzProvLbl.attributes.name == "anstest_contract_label" + - bind_extepg_provider_contract_2.current.0.fvRsProv.children | length == 2 - - name: Query the External End Point Groups - aci_l3out_extepg_to_contract: - <<: *aci_info - tenant: ansible_tenant - l3out: ansible_l3out - extepg: ansible_extEpg + - name: Bind taboo contract to external epg + cisco.aci.aci_l3out_extepg_to_contract: + <<: *aci_ext_epg_present contract: ansible_contract - contract_type: provider - state: query - register: query_extepg + contract_type: taboo + register: taboo_present - - name: Verify query_extepg - assert: + - name: Bind interface contract to external epg + cisco.aci.aci_l3out_extepg_to_contract: + <<: *aci_ext_epg_present + contract: ansible_contract + contract_type: interface + register: interface_present + + - name: Bind intra epg contract to external epg + cisco.aci.aci_l3out_extepg_to_contract: &aci_ext_epg_intra_present + <<: *aci_ext_epg_present + contract: ansible_contract + contract_type: intra_epg + register: intra_epg_present + when: version.current.0.topSystem.attributes.version is version('5', '>=') # This condition will execute only for APIC version 5.x and above + + - name: Bind intra epg contract to external epg (error contract label) + cisco.aci.aci_l3out_extepg_to_contract: + <<: *aci_ext_epg_intra_present + contract_label: anstest_contract_label + ignore_errors: true + register: err_contract_label + + - name: Bind intra epg contract to external epg (error subject label) + cisco.aci.aci_l3out_extepg_to_contract: + <<: *aci_ext_epg_intra_present + subject_label: anstest_subject_label + ignore_errors: true + register: err_subject_label + + - name: Bind intra epg contract to external epg (error subject and contract label) + cisco.aci.aci_l3out_extepg_to_contract: + <<: *aci_ext_epg_intra_present + contract_label: anstest_contract_label + subject_label: anstest_subject_label + ignore_errors: true + register: err_subject_and_contract_label + + - name: Verify present assertions for taboo, interface and intra_epg contract types + ansible.builtin.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" + - taboo_present is changed + - taboo_present.previous == [] + - taboo_present.current.0.fvRsProtBy.attributes.tnVzTabooName == 'ansible_contract' + - interface_present is changed + - interface_present.previous == [] + - interface_present.current.0.fvRsConsIf.attributes.tnVzCPIfName == 'ansible_contract' + - err_contract_label is failed + - err_contract_label.msg == "the 'contract_label' and 'subject_label' are not configurable for intra_epg contracts" + - err_subject_label is failed + - err_subject_label.msg == "the 'contract_label' and 'subject_label' are not configurable for intra_epg contracts" + - err_subject_and_contract_label is failed + - err_subject_and_contract_label.msg == "the 'contract_label' and 'subject_label' are not configurable for intra_epg contracts" + + - name: Verify present assertions for taboo, interface and intra_epg contract types + ansible.builtin.assert: + that: + - intra_epg_present is changed + - intra_epg_present.previous == [] + - intra_epg_present.current.0.fvRsIntraEpg.attributes.tnVzBrCPName == 'ansible_contract' + when: version.current.0.topSystem.attributes.version is version('5', '>=') # This condition will execute only for APIC version 5.x and above + + - name: Query the External End Point Groups + cisco.aci.aci_l3out_extepg_to_contract: + <<: *aci_ext_epg_present + state: query + register: query_extepg - name: Query all the External End Point Groups - aci_l3out_extepg_to_contract: + cisco.aci.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 + - name: Verify query_extepg + ansible.builtin.assert: + that: + - query_extepg is not changed + - query_extepg.current | length == 1 + - query_extepg.current.0.fvRsProv.attributes.dn == "uni/tn-ansible_test/out-ansible_l3out/instP-ansible_extEpg/rsprov-ansible_contract" + - query_all is not changed + - query_all.current | length >= 1 + + - name: Remove existing contract to External End Point Groups (check-mode) + aci_l3out_extepg_to_contract: &aci_ext_epg_absent + <<: *aci_ext_epg_present state: absent - register: remove_contract_extepg + register: cm_remove_contract_extepg + check_mode: true + + - name: Remove existing contract to External End Point Groups + cisco.aci.aci_l3out_extepg_to_contract: + <<: *aci_ext_epg_absent + register: nm_remove_contract_extepg + + - name: Remove existing contract to External End Point Groups again + cisco.aci.aci_l3out_extepg_to_contract: + <<: *aci_ext_epg_absent + register: nm_remove_contract_extepg_again - name: Verify remove_contract_extepg - assert: + ansible.builtin.assert: that: - - remove_contract_extepg.previous.0.fvRsProv.attributes.dn == "uni/tn-ansible_tenant/out-ansible_l3out/instP-ansible_extEpg/rsprov-ansible_contract" + - cm_remove_contract_extepg is changed + - cm_remove_contract_extepg.previous.0.fvRsProv.attributes.dn == "uni/tn-ansible_test/out-ansible_l3out/instP-ansible_extEpg/rsprov-ansible_contract" + - nm_remove_contract_extepg is changed + - nm_remove_contract_extepg.previous.0.fvRsProv.attributes.dn == "uni/tn-ansible_test/out-ansible_l3out/instP-ansible_extEpg/rsprov-ansible_contract" + - nm_remove_contract_extepg.current == [] + - nm_remove_contract_extepg_again is not changed + - nm_remove_contract_extepg_again.previous == [] + - nm_remove_contract_extepg_again.current == [] - name: Bind External End Point Groups to Contracts - aci_l3out_extepg_to_contract: + cisco.aci.aci_l3out_extepg_to_contract: <<: *aci_info - tenant: ansible_tenant + tenant: ansible_test l3out: ansible_l3out extepg: ansible_extEpg contract: ansible_contract @@ -147,6 +266,13 @@ register: bind_extepg_consumer_contract - name: Verify bind_extepg_consumer_contract - assert: + ansible.builtin.assert: that: - - bind_extepg_consumer_contract.msg == "the 'provider_match' is only configurable for Provided Contracts" \ No newline at end of file + - bind_extepg_consumer_contract.msg == "the 'provider_match' is only configurable for Provided Contracts" + + # CLEAN ENVIRONMENT + - name: Remove the ansible_tenant + cisco.aci.aci_tenant: + <<: *aci_info + tenant: ansible_test + state: absent diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_l3out_extsubnet/tasks/main.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_l3out_extsubnet/tasks/main.yml index 4be8a65f7..be15031db 100644 --- a/ansible_collections/cisco/aci/tests/integration/targets/aci_l3out_extsubnet/tasks/main.yml +++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_l3out_extsubnet/tasks/main.yml @@ -4,12 +4,12 @@ # GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) - name: Test that we have an ACI APIC host, ACI username and ACI password - fail: + ansible.builtin.fail: msg: 'Please define the following variables: aci_hostname, aci_username and aci_password.' when: aci_hostname is not defined or aci_username is not defined or aci_password is not defined - name: Set vars - set_fact: + ansible.builtin.set_fact: aci_info: &aci_info host: "{{ aci_hostname }}" username: "{{ aci_username }}" @@ -21,26 +21,26 @@ # CLEAN ENVIRONMENT - name: Remove the ansible_tenant - aci_tenant: + cisco.aci.aci_tenant: <<: *aci_info tenant: ansible_tenant state: absent - name: Verify Cloud and Non-Cloud Sites in use. - include_tasks: ../../../../../../integration/targets/aci_cloud_provider/tasks/main.yml + ansible.builtin.include_tasks: ../../../../../../integration/targets/aci_cloud_provider/tasks/main.yml - name: Execute tasks only for non-cloud sites when: query_cloud.current == [] # This condition will execute only non-cloud sites block: # block specifies execution of tasks within, based on conditions - name: Add a new tenant - aci_tenant: + cisco.aci.aci_tenant: <<: *aci_info tenant: ansible_tenant description: Ansible tenant state: present - name: Add a new l3out - aci_l3out: + cisco.aci.aci_l3out: <<: *aci_info tenant: ansible_tenant name: ansible_l3out @@ -52,7 +52,7 @@ state: present - name: Add a new ExtEpg - aci_l3out_extepg: + cisco.aci.aci_l3out_extepg: <<: *aci_info tenant: ansible_tenant l3out: ansible_l3out @@ -84,7 +84,7 @@ register: nm_add_subnet - name: Verify cm_add_subnet and nm_add_subnet - assert: + ansible.builtin.assert: that: - cm_add_subnet is changed - nm_add_subnet is changed @@ -107,7 +107,7 @@ register: nm_add_subnet_again - name: Verify nm_add_subnet_again - assert: + ansible.builtin.assert: that: - nm_add_subnet_again is not changed @@ -139,7 +139,7 @@ register: nm_change_subnet - name: Verify cm_change_subnet and nm_change_subnet - assert: + ansible.builtin.assert: that: - cm_change_subnet is changed - nm_change_subnet is changed @@ -164,7 +164,7 @@ register: nm_add_another_subnet - name: Verify nm_add_another_subnet - assert: + ansible.builtin.assert: that: - nm_add_another_subnet is changed - nm_add_another_subnet.current.0.l3extSubnet.attributes.ip == "192.1.2.0/24" @@ -189,7 +189,7 @@ register: query_subnet - name: Verify query_all and query_subnet - assert: + ansible.builtin.assert: that: - query_all is not changed - query_subnet is not changed @@ -208,7 +208,7 @@ register: rm_subnet - name: Verify rm_subnet - assert: + ansible.builtin.assert: that: - rm_subnet is changed - rm_subnet.current == [] @@ -230,7 +230,7 @@ ignore_errors: true - name: asserts failed aggregate creation tasks - assert: + ansible.builtin.assert: that: - nm_aggregate_scope_none is failed - nm_aggregate_scope_none.msg.startswith("missing parameter(s) required by 'aggregate'") @@ -251,7 +251,7 @@ ignore_errors: true - name: asserts failed aggregate creation tasks - assert: + ansible.builtin.assert: that: - nm_aggregate_scope_mismatch is failed - nm_aggregate_scope_mismatch.msg == "All aggregate values ['export-rtctrl', 'import-rtctrl'] need to be defined in scope ['import-security']." @@ -286,7 +286,7 @@ register: nm_aggregate_scope_match - name: asserts success aggregate creation task - assert: + ansible.builtin.assert: that: - cm_aggregate_scope_match is changed - cm_aggregate_scope_match.proposed.l3extSubnet.attributes.ip == "0.0.0.0/0" @@ -313,6 +313,6 @@ register: nm_aggregate_scope_match - name: asserts success aggregate creation task reversed input order - assert: + ansible.builtin.assert: that: - nm_aggregate_scope_match is not changed \ No newline at end of file diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_l3out_floating_svi/aliases b/ansible_collections/cisco/aci/tests/integration/targets/aci_l3out_floating_svi/aliases new file mode 100644 index 000000000..209b793f9 --- /dev/null +++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_l3out_floating_svi/aliases @@ -0,0 +1,2 @@ +# No ACI simulator yet, so not enabled +# unsupported diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_l3out_floating_svi/tasks/main.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_l3out_floating_svi/tasks/main.yml new file mode 100644 index 000000000..5bc0cf78b --- /dev/null +++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_l3out_floating_svi/tasks/main.yml @@ -0,0 +1,220 @@ +# Author: Shreyas Srish (@shrsr) +# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) + +# SET VARS +- name: Set vars + ansible.builtin.set_fact: + aci_info: &aci_info + host: '{{ aci_hostname }}' + username: '{{ aci_username }}' + password: '{{ aci_password }}' + validate_certs: '{{ aci_validate_certs | default(false) }}' + use_ssl: '{{ aci_use_ssl | default(true) }}' + use_proxy: '{{ aci_use_proxy | default(true) }}' + output_level: '{{ aci_output_level | default("info") }}' + +# CLEAN ENVIRONMENT +- name: Remove test tenant before we kickoff + cisco.aci.aci_tenant: &tenant_absent + <<: *aci_info + tenant: ansible_test + state: absent + +- name: Verify Cloud and Non-Cloud Sites in use. + ansible.builtin.include_tasks: ../../../../../../integration/targets/aci_cloud_provider/tasks/main.yml + +- name: Execute tasks only for non-cloud sites + when: query_cloud.current == [] # This condition will execute only non-cloud sites + block: # block specifies execution of tasks within, based on conditions + # SETUP ENVIRONMENT + - name: Create domain + cisco.aci.aci_domain: &domain_present + <<: *aci_info + domain: l3outintftest + domain_type: l3dom + state: present + + - name: Create tenant + cisco.aci.aci_tenant: &tenant_present + <<: *tenant_absent + state: present + + - name: Configure VRF + cisco.aci.aci_vrf: &vrf_present + <<: *tenant_present + vrf: l3outintftest + + - name: Create L3Out + cisco.aci.aci_l3out: + <<: *vrf_present + l3out: l3outintftest + domain: l3outintftest + route_control: export + + - name: Create node profile + cisco.aci.aci_l3out_logical_node_profile: &np_present + <<: *tenant_present + l3out: l3outintftest + node_profile: nodes + + - name: Add interface profile + cisco.aci.aci_l3out_logical_interface_profile: &intf_present + <<: *np_present + interface_profile: Floating + + - name: Create a floating svi in check mode + cisco.aci.aci_l3out_floating_svi: &floating_svi + <<: *intf_present + pod_id: 1 + node_id: 201 + encap: vlan-1 + address: 23.45.67.90/24 + external_bridge_group_profile: bridge1 + state: present + check_mode: true + register: add_floating_cm + when: version.current.0.topSystem.attributes.version is version('5', '>=') + + - name: Create a floating svi in normal mode + cisco.aci.aci_l3out_floating_svi: + <<: *floating_svi + state: present + register: add_floating_nm + when: version.current.0.topSystem.attributes.version is version('5', '>=') + + - name: Create a floating svi again + cisco.aci.aci_l3out_floating_svi: + <<: *floating_svi + state: present + register: add_floating_again + when: version.current.0.topSystem.attributes.version is version('5', '>=') + + - name: Update floating svi + cisco.aci.aci_l3out_floating_svi: + <<: *floating_svi + external_bridge_group_profile: bridge2 + state: present + register: update_floating + when: version.current.0.topSystem.attributes.version is version('5', '>=') + + - name: Delete an external_bridge_group_profile + cisco.aci.aci_l3out_floating_svi: + <<: *floating_svi + external_bridge_group_profile: "" + state: present + register: remove_bridge + when: version.current.0.topSystem.attributes.version is version('5', '>=') + + - name: Create another floating svi + cisco.aci.aci_l3out_floating_svi: + <<: *intf_present + pod_id: 1 + node_id: 202 + encap: vlan-1 + address: 24.45.67.90/24 + external_bridge_group_profile: "" + state: present + register: add_floating2 + when: version.current.0.topSystem.attributes.version is version('5', '>=') + + - name: Create another floating svi with no external_bridge_group_profile + cisco.aci.aci_l3out_floating_svi: + <<: *intf_present + pod_id: 1 + node_id: 203 + encap: vlan-1 + address: 25.45.67.90/24 + state: present + register: add_floating3 + + - name: Change floating svi with an attempt to delete external_bridge_group_profile + cisco.aci.aci_l3out_floating_svi: + <<: *intf_present + pod_id: 1 + node_id: 203 + encap: vlan-1 + address: 25.45.67.90/24 + external_bridge_group_profile: "" + state: present + register: change_floating3 + when: version.current.0.topSystem.attributes.version is version('5', '>=') + + - name: Verify present ops + ansible.builtin.assert: + that: + - add_floating_cm is changed + - add_floating_nm is changed + - add_floating_again is not changed + - update_floating is changed + - remove_bridge is changed + - add_floating2 is changed + - add_floating3 is changed + - change_floating3 is not changed + - add_floating_cm.proposed.l3extVirtualLIfP.attributes.addr == "23.45.67.90/24" + - add_floating_cm.proposed.l3extVirtualLIfP.attributes.dn == "uni/tn-ansible_test/out-l3outintftest/lnodep-nodes/lifp-Floating/vlifp-[topology/pod-1/node-201]-[vlan-1]" + - add_floating_cm.proposed.l3extVirtualLIfP.attributes.encap == "vlan-1" + - add_floating_cm.proposed.l3extVirtualLIfP.children.0.l3extBdProfileCont.children.0.l3extRsBdProfile.attributes.tDn == "uni/tn-ansible_test/bdprofile-bridge1" + - add_floating_nm.current.0.l3extVirtualLIfP.attributes.addr == "23.45.67.90/24" + - add_floating_nm.current.0.l3extVirtualLIfP.attributes.dn == "uni/tn-ansible_test/out-l3outintftest/lnodep-nodes/lifp-Floating/vlifp-[topology/pod-1/node-201]-[vlan-1]" + - add_floating_nm.current.0.l3extVirtualLIfP.attributes.encap == "vlan-1" + - add_floating_nm.current.0.l3extVirtualLIfP.children.0.l3extBdProfileCont.children.0.l3extRsBdProfile.attributes.tDn == "uni/tn-ansible_test/bdprofile-bridge1" + - update_floating.current.0.l3extVirtualLIfP.children.0.l3extBdProfileCont.children.0.l3extRsBdProfile.attributes.tDn == "uni/tn-ansible_test/bdprofile-bridge2" + - remove_bridge.current.0.l3extVirtualLIfP.children is not defined + - add_floating2.current.0.l3extVirtualLIfP.attributes.addr == "24.45.67.90/24" + - add_floating2.current.0.l3extVirtualLIfP.attributes.dn == "uni/tn-ansible_test/out-l3outintftest/lnodep-nodes/lifp-Floating/vlifp-[topology/pod-1/node-202]-[vlan-1]" + - add_floating2.current.0.l3extVirtualLIfP.attributes.encap == "vlan-1" + when: version.current.0.topSystem.attributes.version is version('5', '>=') + + - name: Verify present ops for all versions + ansible.builtin.assert: + that: + - add_floating3 is changed + - add_floating3.current.0.l3extVirtualLIfP.attributes.addr == "25.45.67.90/24" + - add_floating3.current.0.l3extVirtualLIfP.attributes.dn == "uni/tn-ansible_test/out-l3outintftest/lnodep-nodes/lifp-Floating/vlifp-[topology/pod-1/node-203]-[vlan-1]" + - add_floating3.current.0.l3extVirtualLIfP.attributes.encap == "vlan-1" + - add_floating3.current.0.l3extVirtualLIfP.children is not defined + + - name: Query a floating svi + cisco.aci.aci_l3out_floating_svi: + <<: *floating_svi + state: query + register: query_floating + when: version.current.0.topSystem.attributes.version is version('5', '>=') + + - name: Query all floating svis + cisco.aci.aci_l3out_floating_svi: + <<: *intf_present + state: query + register: query_all_floating + when: version.current.0.topSystem.attributes.version is version('5', '>=') + + - name: Verify Query ops + ansible.builtin.assert: + that: + - query_floating is not changed + - query_all_floating is not changed + - query_floating.current.0.l3extVirtualLIfP.attributes.addr == "23.45.67.90/24" + - query_floating.current.0.l3extVirtualLIfP.attributes.dn == "uni/tn-ansible_test/out-l3outintftest/lnodep-nodes/lifp-Floating/vlifp-[topology/pod-1/node-201]-[vlan-1]" + - query_floating.current.0.l3extVirtualLIfP.attributes.encap == "vlan-1" + - query_all_floating.current.0.l3extLIfP.children | length == 3 + when: version.current.0.topSystem.attributes.version is version('5', '>=') + + - name: Remove a floating svi + cisco.aci.aci_l3out_floating_svi: + <<: *floating_svi + state: absent + register: remove_floating + when: version.current.0.topSystem.attributes.version is version('5', '>=') + + - name: Verify remove ops + ansible.builtin.assert: + that: + - remove_floating is changed + - remove_floating.current == [] + when: version.current.0.topSystem.attributes.version is version('5', '>=') + + - name: Clean up environment + cisco.aci.aci_tenant: + <<: *aci_info + tenant: ansible_test + state: absent diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_l3out_floating_svi_path/aliases b/ansible_collections/cisco/aci/tests/integration/targets/aci_l3out_floating_svi_path/aliases new file mode 100644 index 000000000..209b793f9 --- /dev/null +++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_l3out_floating_svi_path/aliases @@ -0,0 +1,2 @@ +# No ACI simulator yet, so not enabled +# unsupported diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_l3out_floating_svi_path/tasks/main.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_l3out_floating_svi_path/tasks/main.yml new file mode 100644 index 000000000..3ecc01a2e --- /dev/null +++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_l3out_floating_svi_path/tasks/main.yml @@ -0,0 +1,365 @@ +# Author: Shreyas Srish (@shrsr) +# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) + +# SET VARS +- name: Set vars + ansible.builtin.set_fact: + aci_info: &aci_info + host: '{{ aci_hostname }}' + username: '{{ aci_username }}' + password: '{{ aci_password }}' + validate_certs: '{{ aci_validate_certs | default(false) }}' + use_ssl: '{{ aci_use_ssl | default(true) }}' + use_proxy: '{{ aci_use_proxy | default(true) }}' + output_level: '{{ aci_output_level | default("info") }}' + +# CLEAN ENVIRONMENT +- name: Remove test tenant before we kickoff + cisco.aci.aci_tenant: &tenant_absent + <<: *aci_info + tenant: ansible_test + state: absent + +- name: Verify Cloud and Non-Cloud Sites in use. + ansible.builtin.include_tasks: ../../../../../../integration/targets/aci_cloud_provider/tasks/main.yml + +- name: Execute tasks only for non-cloud sites + when: query_cloud.current == [] # This condition will execute only non-cloud sites + block: # block specifies execution of tasks within, based on conditions + # SETUP ENVIRONMENT + - name: Create domain + cisco.aci.aci_domain: &domain_present + <<: *aci_info + domain: l3outintftest + domain_type: l3dom + state: present + + - name: Create tenant + cisco.aci.aci_tenant: &tenant_present + <<: *tenant_absent + state: present + + - name: Configure VRF + cisco.aci.aci_vrf: &vrf_present + <<: *tenant_present + vrf: l3outintftest + + - name: Create L3Out + cisco.aci.aci_l3out: + <<: *vrf_present + l3out: l3outintftest + domain: l3outintftest + route_control: export + + - name: Create node profile + cisco.aci.aci_l3out_logical_node_profile: &np_present + <<: *tenant_present + l3out: l3outintftest + node_profile: nodes + + - name: Add interface profile + cisco.aci.aci_l3out_logical_interface_profile: &intf_present + <<: *np_present + interface_profile: Floating + + - name: Create a floating svi + cisco.aci.aci_l3out_floating_svi: + <<: *intf_present + pod_id: 1 + node_id: 201 + encap: vlan-1 + address: 23.45.67.90/24 + state: present + + - name: Create a floating svi + cisco.aci.aci_l3out_floating_svi: + <<: *intf_present + pod_id: 1 + node_id: 202 + encap: vlan-1 + address: 26.45.67.90/24 + state: present + + - name: Add VMM domain + cisco.aci.aci_domain: + <<: *aci_info + domain: vmm_dom + domain_type: vmm + vm_provider: vmware + state: present + + - name: Add a vSwitch policy to vmware domain + cisco.aci.aci_vmm_vswitch_policy: + <<: *aci_info + domain: vmm_dom + vm_provider: vmware + enhanced_lag: + - name: enhanced + - name: enhanced2 + state: present + + - name: Create a floating svi path of type physical in check_mode + cisco.aci.aci_l3out_floating_svi_path: + <<: *intf_present + pod_id: 1 + node_id: 201 + encap: vlan-1 + domain_type: physical + domain: physical_dom + floating_ip: 25.45.67.90/24 + access_encap: vlan-1 + state: present + check_mode: true + register: add_floating_path_cm + when: version.current.0.topSystem.attributes.version is version('5', '>=') + + - name: Create a floating svi path of type physical in normal mode + cisco.aci.aci_l3out_floating_svi_path: + <<: *intf_present + pod_id: 1 + node_id: 201 + encap: vlan-1 + domain_type: physical + domain: physical_dom + floating_ip: 25.45.67.90/24 + access_encap: vlan-1 + state: present + register: add_floating_path_nm + when: version.current.0.topSystem.attributes.version is version('5', '>=') + + - name: Create a floating svi path of type physical in normal mode again + cisco.aci.aci_l3out_floating_svi_path: + <<: *intf_present + pod_id: 1 + node_id: 201 + encap: vlan-1 + domain_type: physical + domain: physical_dom + floating_ip: 25.45.67.90/24 + access_encap: vlan-1 + state: present + register: add_floating_path_again + when: version.current.0.topSystem.attributes.version is version('5', '>=') + + - name: Update a floating svi path of type physical + cisco.aci.aci_l3out_floating_svi_path: + <<: *intf_present + pod_id: 1 + node_id: 201 + encap: vlan-1 + domain_type: physical + domain: physical_dom + floating_ip: 25.45.67.90/24 + access_encap: vlan-2 + state: present + register: update_floating_path + when: version.current.0.topSystem.attributes.version is version('5', '>=') + + - name: Create another floating svi path of type physical + cisco.aci.aci_l3out_floating_svi_path: + <<: *intf_present + pod_id: 1 + node_id: 201 + encap: vlan-1 + domain_type: physical + domain: physical_dom2 + floating_ip: 25.45.67.90/24 + access_encap: vlan-1 + state: present + register: add_another_floating_path + when: version.current.0.topSystem.attributes.version is version('5', '>=') + + - name: Create a floating svi path of type virtual + cisco.aci.aci_l3out_floating_svi_path: + <<: *intf_present + pod_id: 1 + node_id: 202 + encap: vlan-1 + domain_type: vmware + domain: vmm_dom + floating_ip: 27.45.67.90/24 + forged_transmit: enabled + mac_change: enabled + promiscuous_mode: enabled + enhanced_lag_policy: enhanced + state: present + register: add_enhanced + when: version.current.0.topSystem.attributes.version is version('5', '>=') + + - name: Create a floating svi path of type virtual (change enhanced_lag_policy) + cisco.aci.aci_l3out_floating_svi_path: + <<: *intf_present + pod_id: 1 + node_id: 202 + encap: vlan-1 + domain_type: vmware + domain: vmm_dom + floating_ip: 27.45.67.90/24 + forged_transmit: enabled + mac_change: enabled + promiscuous_mode: enabled + enhanced_lag_policy: enhanced2 + state: present + register: change_enhanced + when: version.current.0.topSystem.attributes.version is version('5', '>=') + + - name: Create a floating svi path of type virtual (delete enhanced_lag_policy) + cisco.aci.aci_l3out_floating_svi_path: + <<: *intf_present + pod_id: 1 + node_id: 202 + encap: vlan-1 + domain_type: vmware + domain: vmm_dom + floating_ip: 27.45.67.90/24 + forged_transmit: enabled + mac_change: enabled + promiscuous_mode: enabled + enhanced_lag_policy: "" + state: present + register: del_enhanced + when: version.current.0.topSystem.attributes.version is version('5', '>=') + + - name: Verify present ops + ansible.builtin.assert: + that: + - add_floating_path_cm is changed + - add_floating_path_nm is changed + - add_floating_path_again is not changed + - update_floating_path is changed + - add_another_floating_path is changed + - add_enhanced is changed + - change_enhanced is changed + - del_enhanced is changed + - add_floating_path_nm.current.0.l3extRsDynPathAtt.attributes.dn == "uni/tn-ansible_test/out-l3outintftest/lnodep-nodes/lifp-Floating/vlifp-[topology/pod-1/node-201]-[vlan-1]/rsdynPathAtt-[uni/phys-physical_dom]" + - add_floating_path_nm.current.0.l3extRsDynPathAtt.attributes.encap == "vlan-1" + - add_floating_path_nm.current.0.l3extRsDynPathAtt.attributes.floatingAddr == "25.45.67.90/24" + - update_floating_path.current.0.l3extRsDynPathAtt.attributes.encap == "vlan-2" + - add_enhanced.current.0.l3extRsDynPathAtt.attributes.dn == "uni/tn-ansible_test/out-l3outintftest/lnodep-nodes/lifp-Floating/vlifp-[topology/pod-1/node-202]-[vlan-1]/rsdynPathAtt-[uni/vmmp-VMware/dom-vmm_dom]" + - add_enhanced.current.0.l3extRsDynPathAtt.attributes.floatingAddr == "27.45.67.90/24" + - add_enhanced.current.0.l3extRsDynPathAtt.attributes.forgedTransmit == "Enabled" + - add_enhanced.current.0.l3extRsDynPathAtt.attributes.macChange == "Enabled" + - add_enhanced.current.0.l3extRsDynPathAtt.attributes.promMode == "Enabled" + - add_enhanced.current.0.l3extRsDynPathAtt.children.0.l3extVirtualLIfPLagPolAtt.children.0.l3extRsVSwitchEnhancedLagPol.attributes.tDn == "uni/vmmp-VMware/dom-vmm_dom/vswitchpolcont/enlacplagp-enhanced" + - change_enhanced.current.0.l3extRsDynPathAtt.children.0.l3extVirtualLIfPLagPolAtt.children.0.l3extRsVSwitchEnhancedLagPol.attributes.tDn == "uni/vmmp-VMware/dom-vmm_dom/vswitchpolcont/enlacplagp-enhanced2" + - add_enhanced.sent.l3extRsDynPathAtt.children.0.l3extVirtualLIfPLagPolAtt.children.0.l3extRsVSwitchEnhancedLagPol.attributes.tDn == "uni/vmmp-VMware/dom-vmm_dom/vswitchpolcont/enlacplagp-enhanced" + - change_enhanced.sent.l3extRsDynPathAtt.children.0.l3extVirtualLIfPLagPolAtt.children.0.l3extRsVSwitchEnhancedLagPol.attributes.tDn == "uni/vmmp-VMware/dom-vmm_dom/vswitchpolcont/enlacplagp-enhanced2" + - del_enhanced.current.0.l3extRsDynPathAtt.children is not defined + when: version.current.0.topSystem.attributes.version is version('5', '>=') + +# Special Case + - name: Create a floating svi path of type virtual with enhanced2 of type l3extRsVSwitchEnhancedLagPol + cisco.aci.aci_l3out_floating_svi_path: + <<: *intf_present + pod_id: 1 + node_id: 202 + encap: vlan-1 + domain_type: vmware + domain: vmm_dom + floating_ip: 27.45.67.90/24 + enhanced_lag_policy: enhanced2 + state: present + register: check_v_four + + - name: Delete enhanced2 of type l3extRsVSwitchEnhancedLagPol + cisco.aci.aci_rest: + <<: *aci_info + path: api/node/mo/uni/tn-ansible_test/out-l3outintftest/lnodep-nodes/lifp-Floating/vlifp-[topology/pod-1/node-202]-[vlan-1]/rsdynPathAtt-[uni/vmmp-VMware/dom-vmm_dom]/vlifplagpolatt/rsvSwitchEnhancedLagPol-[uni/vmmp-VMware/dom-vmm_dom/vswitchpolcont/enlacplagp-enhanced2].json + method: post + content: | + {"l3extRsVSwitchEnhancedLagPol":{"attributes":{"dn":"uni/tn-ansible_test/out-l3outintftest/lnodep-nodes/lifp-Floating/vlifp-[topology/pod-1/node-202]-[vlan-1]/rsdynPathAtt-[uni/vmmp-VMware/dom-vmm_dom]/vlifplagpolatt/rsvSwitchEnhancedLagPol-[uni/vmmp-VMware/dom-vmm_dom/vswitchpolcont/enlacplagp-enhanced2]","status":"deleted"}}} + + - name: Create a floating svi path of type virtual with enhanced2 of type l3extRsVSwitchEnhancedLagPol + cisco.aci.aci_l3out_floating_svi_path: + <<: *intf_present + pod_id: 1 + node_id: 202 + encap: vlan-1 + domain_type: vmware + domain: vmm_dom + floating_ip: 27.45.67.90/24 + enhanced_lag_policy: enhanced2 + state: present + register: check_enhanced + + - name: Verify special case + ansible.builtin.assert: + that: + - check_v_four is changed + - check_enhanced is changed + - check_v_four.current.0.l3extRsDynPathAtt.attributes.floatingAddr == "27.45.67.90/24" + - check_enhanced.current.0.l3extRsDynPathAtt.children.0.l3extVirtualLIfPLagPolAtt.children.0.l3extRsVSwitchEnhancedLagPol.attributes.tDn == "uni/vmmp-VMware/dom-vmm_dom/vswitchpolcont/enlacplagp-enhanced2" + + - name: Query a floating svi path + cisco.aci.aci_l3out_floating_svi_path: + <<: *intf_present + pod_id: 1 + node_id: 201 + encap: vlan-1 + domain_type: physical + domain: physical_dom + state: query + register: query_floating + when: version.current.0.topSystem.attributes.version is version('5', '>=') + + - name: Query all floating svi paths + cisco.aci.aci_l3out_floating_svi_path: + <<: *intf_present + pod_id: 1 + node_id: 201 + encap: vlan-1 + state: query + register: query_all_floating + when: version.current.0.topSystem.attributes.version is version('5', '>=') + + - name: Verify query ops + ansible.builtin.assert: + that: + - query_floating is not changed + - query_all_floating is not changed + - query_floating.current.0.l3extRsDynPathAtt.attributes.dn == "uni/tn-ansible_test/out-l3outintftest/lnodep-nodes/lifp-Floating/vlifp-[topology/pod-1/node-201]-[vlan-1]/rsdynPathAtt-[uni/phys-physical_dom]" + - query_floating.current.0.l3extRsDynPathAtt.attributes.floatingAddr == "25.45.67.90/24" + - query_floating.current.0.l3extRsDynPathAtt.attributes.encap == "vlan-2" + - query_all_floating.current.0.l3extVirtualLIfP.children | length == 2 + when: version.current.0.topSystem.attributes.version is version('5', '>=') + + - name: Remove a floating svi path + cisco.aci.aci_l3out_floating_svi_path: + <<: *intf_present + pod_id: 1 + node_id: 201 + encap: vlan-1 + domain_type: physical + domain: physical_dom + state: absent + register: remove_floating_path + when: version.current.0.topSystem.attributes.version is version('5', '>=') + + - name: Verify absent ops + ansible.builtin.assert: + that: + - remove_floating_path is changed + - remove_floating_path.current == [] + when: version.current.0.topSystem.attributes.version is version('5', '>=') + + # Clean up Environment + - name: Remove vSwitch Policy + cisco.aci.aci_vmm_vswitch_policy: + <<: *aci_info + domain: vmm_dom + vm_provider: vmware + state: absent + + - name: Remove VMM domain + cisco.aci.aci_domain: + <<: *aci_info + domain: vmm_dom + domain_type: vmm + vm_provider: vmware + state: absent + + - name: Remove test tenant + cisco.aci.aci_tenant: + <<: *aci_info + tenant: ansible_test + state: absent diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_l3out_floating_svi_path_secondary_ip/aliases b/ansible_collections/cisco/aci/tests/integration/targets/aci_l3out_floating_svi_path_secondary_ip/aliases new file mode 100644 index 000000000..209b793f9 --- /dev/null +++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_l3out_floating_svi_path_secondary_ip/aliases @@ -0,0 +1,2 @@ +# No ACI simulator yet, so not enabled +# unsupported diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_l3out_floating_svi_path_secondary_ip/tasks/main.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_l3out_floating_svi_path_secondary_ip/tasks/main.yml new file mode 100644 index 000000000..a1aedf96c --- /dev/null +++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_l3out_floating_svi_path_secondary_ip/tasks/main.yml @@ -0,0 +1,226 @@ +# Author: Shreyas Srish (@shrsr) +# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) + +# SET VARS +- name: Set vars + ansible.builtin.set_fact: + aci_info: &aci_info + host: '{{ aci_hostname }}' + username: '{{ aci_username }}' + password: '{{ aci_password }}' + validate_certs: '{{ aci_validate_certs | default(false) }}' + use_ssl: '{{ aci_use_ssl | default(true) }}' + use_proxy: '{{ aci_use_proxy | default(true) }}' + output_level: '{{ aci_output_level | default("debug") }}' + +# CLEAN ENVIRONMENT +- name: Remove test tenant before we kickoff + cisco.aci.aci_tenant: &tenant_absent + <<: *aci_info + tenant: ansible_test + state: absent + +- name: Verify Cloud and Non-Cloud Sites in use. + ansible.builtin.include_tasks: ../../../../../../integration/targets/aci_cloud_provider/tasks/main.yml + +- name: Execute tasks only for non-cloud sites + when: + - version.current.0.topSystem.attributes.version is version('5', '>=') + - query_cloud.current == [] # This condition will execute only non-cloud sites + block: # block specifies execution of tasks within, based on conditions + # SETUP ENVIRONMENT + - name: Create domain + cisco.aci.aci_domain: &domain_present + <<: *aci_info + domain: l3outintftest + domain_type: l3dom + state: present + + - name: Create tenant + cisco.aci.aci_tenant: &tenant_present + <<: *tenant_absent + state: present + + - name: Configure VRF + cisco.aci.aci_vrf: &vrf_present + <<: *tenant_present + vrf: l3outintftest + + - name: Create L3Out + cisco.aci.aci_l3out: + <<: *vrf_present + l3out: l3outintftest + domain: l3outintftest + route_control: export + + - name: Create node profile + cisco.aci.aci_l3out_logical_node_profile: &np_present + <<: *tenant_present + l3out: l3outintftest + node_profile: NODES + + - name: Add interface profile + cisco.aci.aci_l3out_logical_interface_profile: &intf_present + <<: *np_present + interface_profile: Floating + + - name: Create a floating svi + cisco.aci.aci_l3out_floating_svi: + <<: *intf_present + pod_id: 1 + node_id: 201 + encap: vlan-1 + address: 23.45.67.90/24 + state: present + + - name: Create a floating svi path of type physical + cisco.aci.aci_l3out_floating_svi_path: + <<: *intf_present + pod_id: 1 + node_id: 201 + encap: vlan-1 + domain_type: physical + domain: physical_dom + floating_ip: 25.45.67.90/24 + state: present + + - name: Create a floating svi path of type virtual + cisco.aci.aci_l3out_floating_svi_path: + <<: *intf_present + pod_id: 1 + node_id: 201 + encap: vlan-1 + domain_type: vmware + domain: virtual + floating_ip: 25.45.67.90/24 + state: present + + - name: Create a floating svi path secondary_ip (virtual) + cisco.aci.aci_l3out_floating_svi_path_secondary_ip: + <<: *intf_present + pod_id: 1 + node_id: 201 + encap: vlan-1 + domain_type: vmware + domain: virtual + secondary_ip: 30.45.67.90/24 + state: present + register: add_ip_virtual + + - name: Create a floating svi path secondary_ip in check mode + cisco.aci.aci_l3out_floating_svi_path_secondary_ip: + <<: *intf_present + pod_id: 1 + node_id: 201 + encap: vlan-1 + domain_type: physical + domain: physical_dom + secondary_ip: 27.45.67.90/24 + state: present + check_mode: true + register: add_ip_cm + + - name: Create a floating svi path secondary_ip in normal mode + cisco.aci.aci_l3out_floating_svi_path_secondary_ip: + <<: *intf_present + pod_id: 1 + node_id: 201 + encap: vlan-1 + domain_type: physical + domain: physical_dom + secondary_ip: 27.45.67.90/24 + state: present + register: add_ip_nm + + - name: Create a floating svi path secondary_ip again + cisco.aci.aci_l3out_floating_svi_path_secondary_ip: + <<: *intf_present + pod_id: 1 + node_id: 201 + encap: vlan-1 + domain_type: physical + domain: physical_dom + secondary_ip: 27.45.67.90/24 + state: present + register: add_ip_again + + - name: Create another floating svi path secondary_ip + cisco.aci.aci_l3out_floating_svi_path_secondary_ip: + <<: *intf_present + pod_id: 1 + node_id: 201 + encap: vlan-1 + domain_type: physical + domain: physical_dom + secondary_ip: 28.45.67.90/24 + state: present + register: add_another_ip + + - name: Verify present ops + ansible.builtin.assert: + that: + - add_ip_cm is changed + - add_ip_nm is changed + - add_ip_again is not changed + - add_another_ip is changed + - add_ip_virtual.current.0.l3extIp.attributes.addr == "30.45.67.90/24" + - add_ip_cm.proposed.l3extIp.attributes.addr == "27.45.67.90/24" + - add_ip_nm.current.0.l3extIp.attributes.addr == "27.45.67.90/24" + - add_another_ip.current.0.l3extIp.attributes.addr == "28.45.67.90/24" + + - name: Query a floating svi path secondary_ip + cisco.aci.aci_l3out_floating_svi_path_secondary_ip: + <<: *intf_present + pod_id: 1 + node_id: 201 + encap: vlan-1 + domain_type: physical + domain: physical_dom + secondary_ip: 27.45.67.90/24 + state: query + register: query_ip + + - name: Query all ips + cisco.aci.aci_l3out_floating_svi_path_secondary_ip: + <<: *intf_present + pod_id: 1 + node_id: 201 + encap: vlan-1 + domain_type: physical + domain: physical_dom + state: query + register: query_all + + - name: Verify query ops + ansible.builtin.assert: + that: + - query_ip is not changed + - query_all is not changed + - query_ip.current.0.l3extIp.attributes.addr == "27.45.67.90/24" + - query_all.current.0.l3extRsDynPathAtt.children | length == 2 + + - name: Delete a floating svi path secondary_ip + cisco.aci.aci_l3out_floating_svi_path_secondary_ip: + <<: *intf_present + pod_id: 1 + node_id: 201 + encap: vlan-1 + domain_type: physical + domain: physical_dom + secondary_ip: 27.45.67.90/24 + state: absent + register: delete_ip + + - name: Verify delete ops + ansible.builtin.assert: + that: + - delete_ip is changed + - delete_ip.current == [] + +# Clean up environment + - name: Remove test tenant + cisco.aci.aci_tenant: + <<: *aci_info + tenant: ansible_test + state: absent + \ No newline at end of file diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_l3out_floating_svi_secondary_ip/aliases b/ansible_collections/cisco/aci/tests/integration/targets/aci_l3out_floating_svi_secondary_ip/aliases new file mode 100644 index 000000000..209b793f9 --- /dev/null +++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_l3out_floating_svi_secondary_ip/aliases @@ -0,0 +1,2 @@ +# No ACI simulator yet, so not enabled +# unsupported diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_l3out_floating_svi_secondary_ip/tasks/main.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_l3out_floating_svi_secondary_ip/tasks/main.yml new file mode 100644 index 000000000..f0d2040c6 --- /dev/null +++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_l3out_floating_svi_secondary_ip/tasks/main.yml @@ -0,0 +1,159 @@ +# Author: Shreyas Srish (@shrsr) +# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) + +# SET VARS +- name: Set vars + ansible.builtin.set_fact: + aci_info: &aci_info + host: '{{ aci_hostname }}' + username: '{{ aci_username }}' + password: '{{ aci_password }}' + validate_certs: '{{ aci_validate_certs | default(false) }}' + use_ssl: '{{ aci_use_ssl | default(true) }}' + use_proxy: '{{ aci_use_proxy | default(true) }}' + output_level: '{{ aci_output_level | default("info") }}' + +# CLEAN ENVIRONMENT +- name: Remove test tenant before we kickoff + cisco.aci.aci_tenant: &tenant_absent + <<: *aci_info + tenant: ansible_test + state: absent + +- name: Verify Cloud and Non-Cloud Sites in use. + ansible.builtin.include_tasks: ../../../../../../integration/targets/aci_cloud_provider/tasks/main.yml + +- name: Execute tasks only for non-cloud sites + when: query_cloud.current == [] # This condition will execute only non-cloud sites + block: # block specifies execution of tasks within, based on conditions + # SETUP ENVIRONMENT + - name: Create domain + cisco.aci.aci_domain: &domain_present + <<: *aci_info + domain: l3outintftest + domain_type: l3dom + state: present + + - name: Create tenant + cisco.aci.aci_tenant: &tenant_present + <<: *tenant_absent + state: present + + - name: Configure VRF + cisco.aci.aci_vrf: &vrf_present + <<: *tenant_present + vrf: l3outintftest + + - name: Create L3Out + cisco.aci.aci_l3out: + <<: *vrf_present + l3out: l3outintftest + domain: l3outintftest + route_control: export + + - name: Create node profile + cisco.aci.aci_l3out_logical_node_profile: &np_present + <<: *tenant_present + l3out: l3outintftest + node_profile: NODES + + - name: Add interface profile + cisco.aci.aci_l3out_logical_interface_profile: &intf_present + <<: *np_present + interface_profile: Floating + + - name: Create a floating svi + cisco.aci.aci_l3out_floating_svi: + <<: *intf_present + pod_id: 1 + node_id: 201 + encap: vlan-1 + address: 23.45.67.90/24 + external_bridge_group_profile: bridge1 + state: present + register: add_floating_cm + + - name: Create a floating svi secondary_ip in check mode + cisco.aci.aci_l3out_floating_svi_secondary_ip: &floating_svi + <<: *intf_present + pod_id: 1 + node_id: 201 + encap: vlan-1 + secondary_ip: 25.45.67.90/24 + state: present + check_mode: true + register: add_ip_cm + + - name: Create a floating svi secondary_ip in normal mode + cisco.aci.aci_l3out_floating_svi_secondary_ip: + <<: *floating_svi + state: present + register: add_ip_nm + + - name: Create a floating svi secondary_ip again + cisco.aci.aci_l3out_floating_svi_secondary_ip: + <<: *floating_svi + state: present + register: add_ip_again + + - name: Create another floating svi secondary_ip + cisco.aci.aci_l3out_floating_svi_secondary_ip: + <<: *intf_present + pod_id: 1 + node_id: 201 + encap: vlan-1 + secondary_ip: 26.45.67.90/24 + state: present + register: add_another_ip + + - name: Verify present ops + ansible.builtin.assert: + that: + - add_ip_cm is changed + - add_ip_nm is changed + - add_ip_again is not changed + - add_another_ip is changed + - add_ip_nm.current.0.l3extIp.attributes.addr == "25.45.67.90/24" + - add_another_ip.current.0.l3extIp.attributes.addr == "26.45.67.90/24" + + - name: Query a floating svi secondary_ip + cisco.aci.aci_l3out_floating_svi_secondary_ip: + <<: *floating_svi + state: query + register: query_ip + + - name: Query all ips + cisco.aci.aci_l3out_floating_svi_secondary_ip: + <<: *intf_present + pod_id: 1 + node_id: 201 + encap: vlan-1 + state: query + register: query_all + + - name: Verify query ops + ansible.builtin.assert: + that: + - query_ip is not changed + - query_all is not changed + - query_ip.current.0.l3extIp.attributes.addr == "25.45.67.90/24" + - query_all.current.0.l3extVirtualLIfP.children | length == 2 + + - name: Delete a floating svi secondary_ip + cisco.aci.aci_l3out_floating_svi_secondary_ip: + <<: *floating_svi + state: absent + register: delete_ip + + - name: Verify delete ops + ansible.builtin.assert: + that: + - delete_ip is changed + - delete_ip.current == [] + +# Clean up environment + - name: Remove test tenant + cisco.aci.aci_tenant: + <<: *aci_info + tenant: ansible_test + state: absent \ No newline at end of file diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_l3out_hsrp_group/aliases b/ansible_collections/cisco/aci/tests/integration/targets/aci_l3out_hsrp_group/aliases new file mode 100644 index 000000000..209b793f9 --- /dev/null +++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_l3out_hsrp_group/aliases @@ -0,0 +1,2 @@ +# No ACI simulator yet, so not enabled +# unsupported diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_l3out_hsrp_group/tasks/main.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_l3out_hsrp_group/tasks/main.yml new file mode 100644 index 000000000..d1a4ef501 --- /dev/null +++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_l3out_hsrp_group/tasks/main.yml @@ -0,0 +1,195 @@ +# Test code for the ACI modules +# Copyright: (c) 2023, Shreyas Srish (@shrsr) +# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) + +# SET VARS +- name: Set vars + ansible.builtin.set_fact: + aci_info: &aci_info + host: '{{ aci_hostname }}' + username: '{{ aci_username }}' + password: '{{ aci_password }}' + validate_certs: '{{ aci_validate_certs | default(false) }}' + use_ssl: '{{ aci_use_ssl | default(true) }}' + use_proxy: '{{ aci_use_proxy | default(true) }}' + output_level: '{{ aci_output_level | default("debug") }}' + +# CLEAN ENVIRONMENT +- name: Remove test tenant before we kickoff + cisco.aci.aci_tenant: &tenant_absent + <<: *aci_info + tenant: ansible_test + state: absent + +- name: Verify Cloud and Non-Cloud Sites in use. + ansible.builtin.include_tasks: ../../../../../../integration/targets/aci_cloud_provider/tasks/main.yml + +- name: Execute tasks only for non-cloud sites + when: query_cloud.current == [] # This condition will execute only non-cloud sites + block: # block specifies execution of tasks within, based on conditions + # SETUP ENVIRONMENT + - name: Create domain + cisco.aci.aci_domain: + <<: *aci_info + domain: l3outintftest + domain_type: l3dom + state: present + + - name: Create tenant + cisco.aci.aci_tenant: &tenant_present + <<: *tenant_absent + state: present + + - name: Configure VRF + cisco.aci.aci_vrf: &vrf_present + <<: *tenant_present + vrf: l3outintftest + + - name: Create L3Out + cisco.aci.aci_l3out: + <<: *vrf_present + l3out: l3outintftest + domain: l3outintftest + route_control: export + + - name: Create node profile + cisco.aci.aci_l3out_logical_node_profile: &np_present + <<: *tenant_present + l3out: l3outintftest + node_profile: node1 + + - name: Create interface profile + cisco.aci.aci_l3out_logical_interface_profile: &intf_present + <<: *np_present + interface_profile: intf1 + + - name: Add a hsrp interface profile + cisco.aci.aci_l3out_hsrp_interface_profile: + <<: *intf_present + hsrp_policy: default + version: v1 + state: present + + - name: Add a hsrp group (check mode) + cisco.aci.aci_l3out_hsrp_group: &group_present + <<: *intf_present + hsrp_interface_group: group1 + group_id: 1 + ip: 12.34.56.32 + mac: 00:00:00:00:00:FF + group_name: one + group_type: ipv4 + ip_obtain_mode: admin + group_policy: default + state: present + check_mode: true + register: cm_add_group + + - name: Add a hsrp group (normal mode) + cisco.aci.aci_l3out_hsrp_group: + <<: *group_present + register: nm_add_group + + - name: Add hsrp group again + cisco.aci.aci_l3out_hsrp_group: + <<: *group_present + register: add_group_again + + - name: Change hsrp group + cisco.aci.aci_l3out_hsrp_group: &group_update + <<: *group_present + group_id: 3 + register: update_group + + - name: Add another hsrp group + cisco.aci.aci_l3out_hsrp_group: + <<: *intf_present + hsrp_interface_group: group2 + group_name: two + ip_obtain_mode: learn + state: present + register: nm_add_group2 + + - name: Verify add hsrp groups + ansible.builtin.assert: + that: + - cm_add_group is changed + - nm_add_group is changed + - add_group_again is not changed + - cm_add_group.proposed.hsrpGroupP.attributes.groupAf == "ipv4" + - cm_add_group.proposed.hsrpGroupP.attributes.groupId == "1" + - cm_add_group.proposed.hsrpGroupP.attributes.groupName == "one" + - cm_add_group.proposed.hsrpGroupP.attributes.ip == "12.34.56.32" + - cm_add_group.proposed.hsrpGroupP.attributes.ipObtainMode == "admin" + - cm_add_group.proposed.hsrpGroupP.attributes.mac == "00:00:00:00:00:FF" + - cm_add_group.proposed.hsrpGroupP.children.0.hsrpRsGroupPol.attributes.tnHsrpGroupPolName == "default" + - nm_add_group.current.0.hsrpGroupP.attributes.dn == "uni/tn-ansible_test/out-l3outintftest/lnodep-node1/lifp-intf1/hsrpIfP/hsrpGroupP-group1" + - nm_add_group.current.0.hsrpGroupP.attributes.groupAf == "ipv4" + - nm_add_group.current.0.hsrpGroupP.attributes.groupId == "1" + - cm_add_group.previous == nm_add_group.previous == [] + - update_group.current.0.hsrpGroupP.attributes.groupId == "3" + - nm_add_group.current.0.hsrpGroupP.attributes.name == "group1" + - nm_add_group.current.0.hsrpGroupP.attributes.groupName == "one" + - nm_add_group.current.0.hsrpGroupP.attributes.ip == "12.34.56.32" + - nm_add_group.current.0.hsrpGroupP.attributes.ipObtainMode == "admin" + - nm_add_group.current.0.hsrpGroupP.attributes.mac == "00:00:00:00:00:FF" + - nm_add_group.current.0.hsrpGroupP.children.0.hsrpRsGroupPol.attributes.tnHsrpGroupPolName == "default" + - nm_add_group2.current.0.hsrpGroupP.attributes.name == "group2" + - nm_add_group2.current.0.hsrpGroupP.attributes.groupName == "two" + - nm_add_group2.current.0.hsrpGroupP.attributes.ipObtainMode == "learn" + + - name: Query a hsrp group + cisco.aci.aci_l3out_hsrp_group: + <<: *group_update + state: query + register: query_group + + - name: Query all hsrp groups + cisco.aci.aci_l3out_hsrp_group: + <<: *intf_present + state: query + register: query_all + + - name: Verify query + ansible.builtin.assert: + that: + - query_group is not changed + - query_all is not changed + - query_group.current.0.hsrpGroupP.attributes.dn == "uni/tn-ansible_test/out-l3outintftest/lnodep-node1/lifp-intf1/hsrpIfP/hsrpGroupP-group1" + - query_group.current.0.hsrpGroupP.attributes.groupAf == "ipv4" + - query_group.current.0.hsrpGroupP.attributes.groupId == "3" + - query_group.current.0.hsrpGroupP.attributes.name == "group1" + - query_group.current.0.hsrpGroupP.attributes.groupName == "one" + - query_group.current.0.hsrpGroupP.attributes.ip == "12.34.56.32" + - query_group.current.0.hsrpGroupP.attributes.ipObtainMode == "admin" + - query_group.current.0.hsrpGroupP.attributes.mac == "00:00:00:00:00:FF" + - query_group.current.0.hsrpGroupP.children.0.hsrpRsGroupPol.attributes.tnHsrpGroupPolName == "default" + - query_all.current.0.hsrpIfP.children | length == 2 + + - name: Remove a hsrp group in check mode + cisco.aci.aci_l3out_hsrp_group: + <<: *group_update + state: absent + check_mode: true + register: cm_absent_group + + - name: Remove a hsrp group + cisco.aci.aci_l3out_hsrp_group: + <<: *group_update + state: absent + register: absent_group + + - name: Remove hsrp group again + cisco.aci.aci_l3out_hsrp_group: + <<: *group_update + state: absent + register: absent_group_again + + - name: Verify remove + ansible.builtin.assert: + that: + - cm_absent_group is changed + - cm_absent_group.proposed == {} + - absent_group is changed + - absent_group.current == [] + - absent_group_again is not changed diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_l3out_hsrp_interface_profile/aliases b/ansible_collections/cisco/aci/tests/integration/targets/aci_l3out_hsrp_interface_profile/aliases new file mode 100644 index 000000000..209b793f9 --- /dev/null +++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_l3out_hsrp_interface_profile/aliases @@ -0,0 +1,2 @@ +# No ACI simulator yet, so not enabled +# unsupported diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_l3out_hsrp_interface_profile/tasks/main.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_l3out_hsrp_interface_profile/tasks/main.yml new file mode 100644 index 000000000..162e1ce04 --- /dev/null +++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_l3out_hsrp_interface_profile/tasks/main.yml @@ -0,0 +1,152 @@ +# Test code for the ACI modules +# Copyright: (c) 2023, Shreyas Srish (@shrsr) +# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) + +# SET VARS +- name: Set vars + ansible.builtin.set_fact: + aci_info: &aci_info + host: '{{ aci_hostname }}' + username: '{{ aci_username }}' + password: '{{ aci_password }}' + validate_certs: '{{ aci_validate_certs | default(false) }}' + use_ssl: '{{ aci_use_ssl | default(true) }}' + use_proxy: '{{ aci_use_proxy | default(true) }}' + output_level: '{{ aci_output_level | default("debug") }}' + +# CLEAN ENVIRONMENT +- name: Remove test tenant before we kickoff + cisco.aci.aci_tenant: &tenant_absent + <<: *aci_info + tenant: ansible_test + state: absent + +- name: Verify Cloud and Non-Cloud Sites in use. + ansible.builtin.include_tasks: ../../../../../../integration/targets/aci_cloud_provider/tasks/main.yml + +- name: Execute tasks only for non-cloud sites + when: query_cloud.current == [] # This condition will execute only non-cloud sites + block: # block specifies execution of tasks within, based on conditions + # SETUP ENVIRONMENT + - name: Create domain + cisco.aci.aci_domain: + <<: *aci_info + domain: l3outintftest + domain_type: l3dom + state: present + + - name: Create tenant + cisco.aci.aci_tenant: &tenant_present + <<: *tenant_absent + state: present + + - name: Configure VRF + cisco.aci.aci_vrf: &vrf_present + <<: *tenant_present + vrf: l3outintftest + + - name: Create L3Out + cisco.aci.aci_l3out: + <<: *vrf_present + l3out: l3outintftest + domain: l3outintftest + route_control: export + + - name: Create node profile + cisco.aci.aci_l3out_logical_node_profile: &np_present + <<: *tenant_present + l3out: l3outintftest + node_profile: node1 + + - name: Create interface profile + cisco.aci.aci_l3out_logical_interface_profile: &intf_present + <<: *np_present + interface_profile: intf1 + + - name: Add a new hsrp interface profile (check mode) + cisco.aci.aci_l3out_hsrp_interface_profile: &hsrp_present + <<: *intf_present + version: v1 + state: present + check_mode: true + register: cm_add_hsrp + + - name: Add a new hsrp interface profile (normal mode) + cisco.aci.aci_l3out_hsrp_interface_profile: *hsrp_present + register: nm_add_hsrp + + - name: Verify add hsrp + ansible.builtin.assert: + that: + - cm_add_hsrp is changed + - nm_add_hsrp is changed + - cm_add_hsrp.proposed.hsrpIfP.attributes.version == "v1" + - cm_add_hsrp.previous == nm_add_hsrp.previous == [] + - nm_add_hsrp.current.0.hsrpIfP.attributes.dn == "uni/tn-ansible_test/out-l3outintftest/lnodep-node1/lifp-intf1/hsrpIfP" + - nm_add_hsrp.current.0.hsrpIfP.attributes.version == "v1" + + - name: Add the hsrp interface profile again to check idempotency + cisco.aci.aci_l3out_hsrp_interface_profile: *hsrp_present + register: nm_add_hsrp_again + + - name: Verify idempotency + ansible.builtin.assert: + that: + - nm_add_hsrp_again is not changed + + - name: Update the hsrp interface_profile + cisco.aci.aci_l3out_hsrp_interface_profile: &hsrp_update + <<: *hsrp_present + hsrp_policy: default + version: v2 + register: nm_hsrp_update + + - name: Verify update hsrp + ansible.builtin.assert: + that: + - nm_hsrp_update is changed + - nm_hsrp_update.current.0.hsrpIfP.attributes.dn == "uni/tn-ansible_test/out-l3outintftest/lnodep-node1/lifp-intf1/hsrpIfP" + - nm_hsrp_update.current.0.hsrpIfP.attributes.version == "v2" + - nm_hsrp_update.current.0.hsrpIfP.children.0.hsrpRsIfPol.attributes.tnHsrpIfPolName == "default" + + - name: Query the hsrp interface profile + cisco.aci.aci_l3out_hsrp_interface_profile: + <<: *hsrp_update + state: query + register: query_hsrp + + - name: Verify query hsrp + ansible.builtin.assert: + that: + - query_hsrp is not changed + - query_hsrp.current.0.hsrpIfP.attributes.dn == "uni/tn-ansible_test/out-l3outintftest/lnodep-node1/lifp-intf1/hsrpIfP" + - query_hsrp.current.0.hsrpIfP.attributes.version == "v2" + - query_hsrp.current.0.hsrpIfP.children.0.hsrpRsIfPol.attributes.tnHsrpIfPolName == "default" + + - name: Remove the hsrp interface profile + cisco.aci.aci_l3out_hsrp_interface_profile: + <<: *hsrp_update + state: absent + register: cm_remove_hsrp + check_mode: true + + - name: Remove the hsrp interface profile + cisco.aci.aci_l3out_hsrp_interface_profile: + <<: *hsrp_update + state: absent + register: remove_hsrp + + - name: Remove the hsrp interface profile again + cisco.aci.aci_l3out_hsrp_interface_profile: + <<: *hsrp_update + state: absent + register: remove_hsrp_again + + - name: Verify remove_hsrp + ansible.builtin.assert: + that: + - cm_remove_hsrp is changed + - cm_remove_hsrp.proposed == {} + - remove_hsrp is changed + - remove_hsrp.current == [] + - remove_hsrp_again is not changed diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_l3out_hsrp_secondary_vip/aliases b/ansible_collections/cisco/aci/tests/integration/targets/aci_l3out_hsrp_secondary_vip/aliases new file mode 100644 index 000000000..209b793f9 --- /dev/null +++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_l3out_hsrp_secondary_vip/aliases @@ -0,0 +1,2 @@ +# No ACI simulator yet, so not enabled +# unsupported diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_l3out_hsrp_secondary_vip/tasks/main.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_l3out_hsrp_secondary_vip/tasks/main.yml new file mode 100644 index 000000000..d267f2d3d --- /dev/null +++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_l3out_hsrp_secondary_vip/tasks/main.yml @@ -0,0 +1,173 @@ +# Test code for the ACI modules +# Copyright: (c) 2023, Shreyas Srish (@shrsr) +# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) + +# SET VARS +- name: Set vars + ansible.builtin.set_fact: + aci_info: &aci_info + host: '{{ aci_hostname }}' + username: '{{ aci_username }}' + password: '{{ aci_password }}' + validate_certs: '{{ aci_validate_certs | default(false) }}' + use_ssl: '{{ aci_use_ssl | default(true) }}' + use_proxy: '{{ aci_use_proxy | default(true) }}' + output_level: '{{ aci_output_level | default("debug") }}' + +# CLEAN ENVIRONMENT +- name: Remove test tenant before we kickoff + cisco.aci.aci_tenant: &tenant_absent + <<: *aci_info + tenant: ansible_test + state: absent + +- name: Verify Cloud and Non-Cloud Sites in use. + ansible.builtin.include_tasks: ../../../../../../integration/targets/aci_cloud_provider/tasks/main.yml + +- name: Execute tasks only for non-cloud sites + when: query_cloud.current == [] # This condition will execute only non-cloud sites + block: # block specifies execution of tasks within, based on conditions + # SETUP ENVIRONMENT + - name: Create domain + cisco.aci.aci_domain: + <<: *aci_info + domain: l3outintftest + domain_type: l3dom + state: present + + - name: Create tenant + cisco.aci.aci_tenant: &tenant_present + <<: *tenant_absent + state: present + + - name: Configure VRF + cisco.aci.aci_vrf: &vrf_present + <<: *tenant_present + vrf: l3outintftest + + - name: Create L3Out + cisco.aci.aci_l3out: + <<: *vrf_present + l3out: l3outintftest + domain: l3outintftest + route_control: export + + - name: Create node profile + cisco.aci.aci_l3out_logical_node_profile: &np_present + <<: *tenant_present + l3out: l3outintftest + node_profile: node1 + + - name: Create interface profile + cisco.aci.aci_l3out_logical_interface_profile: &intf_present + <<: *np_present + interface_profile: intf1 + + - name: Add a hsrp interface profile + cisco.aci.aci_l3out_hsrp_interface_profile: + <<: *intf_present + hsrp_policy: default + version: v1 + state: present + + - name: Add a hsrp group + cisco.aci.aci_l3out_hsrp_group: + <<: *intf_present + hsrp_interface_group: group1 + group_id: 1 + ip: 12.34.56.32 + mac: 00:00:00:00:00:FF + group_name: one + group_type: ipv4 + ip_obtain_mode: admin + group_policy: default + state: present + + - name: Add a hsrp group secondary vip (check mode) + cisco.aci.aci_l3out_hsrp_secondary_vip: &vip + <<: *intf_present + hsrp_interface_group: group1 + secondary_virtual_ip: 191.1.1.1 + check_mode: true + register: cm_vip + + - name: Add a hsrp group secondary vip (normal mode) + cisco.aci.aci_l3out_hsrp_secondary_vip: + <<: *vip + register: nm_vip + + - name: Add a hsrp group secondary vip again + cisco.aci.aci_l3out_hsrp_secondary_vip: + <<: *vip + register: add_vip_again + + - name: Add another vip + cisco.aci.aci_l3out_hsrp_secondary_vip: + <<: *vip + secondary_virtual_ip: 191.1.1.2 + register: add_vip2 + + - name: Verify add hsrp vips + ansible.builtin.assert: + that: + - cm_vip is changed + - nm_vip is changed + - add_vip_again is not changed + - add_vip2 is changed + - cm_vip.previous == nm_vip.previous == [] + - cm_vip.proposed.hsrpSecVip.attributes.ip == "191.1.1.1" + - nm_vip.current.0.hsrpSecVip.attributes.dn == "uni/tn-ansible_test/out-l3outintftest/lnodep-node1/lifp-intf1/hsrpIfP/hsrpGroupP-group1/hsrpSecVip-[191.1.1.1]" + - nm_vip.current.0.hsrpSecVip.attributes.ip == "191.1.1.1" + - add_vip2.current.0.hsrpSecVip.attributes.dn == "uni/tn-ansible_test/out-l3outintftest/lnodep-node1/lifp-intf1/hsrpIfP/hsrpGroupP-group1/hsrpSecVip-[191.1.1.2]" + - add_vip2.current.0.hsrpSecVip.attributes.ip == "191.1.1.2" + + + - name: Query a vip + cisco.aci.aci_l3out_hsrp_secondary_vip: + <<: *vip + state: query + register: query_vip + + - name: Query all vips + cisco.aci.aci_l3out_hsrp_secondary_vip: + <<: *intf_present + hsrp_interface_group: group1 + state: query + register: query_all + + - name: Verify query + ansible.builtin.assert: + that: + - query_vip is not changed + - query_all is not changed + - query_vip.current.0.hsrpSecVip.attributes.dn == "uni/tn-ansible_test/out-l3outintftest/lnodep-node1/lifp-intf1/hsrpIfP/hsrpGroupP-group1/hsrpSecVip-[191.1.1.1]" + - query_vip.current.0.hsrpSecVip.attributes.ip == "191.1.1.1" + - query_all.current.0.hsrpGroupP.children | length == 2 + + - name: Remove a hsrp group vip in check mode + cisco.aci.aci_l3out_hsrp_secondary_vip: + <<: *vip + state: absent + check_mode: true + register: cm_absent_vip + + - name: Remove a hsrp group vip + cisco.aci.aci_l3out_hsrp_secondary_vip: + <<: *vip + state: absent + register: absent_vip + + - name: Remove hsrp group again + cisco.aci.aci_l3out_hsrp_secondary_vip: + <<: *vip + state: absent + register: absent_vip_again + + - name: Verify remove + ansible.builtin.assert: + that: + - cm_absent_vip is changed + - cm_absent_vip.proposed == {} + - absent_vip is changed + - absent_vip.current == [] + - absent_vip_again is not changed diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_l3out_interface/tasks/main.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_l3out_interface/tasks/main.yml index 5b2a247d8..38e4321e3 100644 --- a/ansible_collections/cisco/aci/tests/integration/targets/aci_l3out_interface/tasks/main.yml +++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_l3out_interface/tasks/main.yml @@ -1,16 +1,17 @@ # Test code for the ACI modules # Copyright: (c) 2021, Tim Cragg (@timcragg) +# Copyright: (c) 2023, Akini Ross (@akinross) # GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) - name: Test that we have an ACI APIC host, ACI username and ACI password - fail: + ansible.builtin.fail: msg: 'Please define the following variables: aci_hostname, aci_username and aci_password.' when: aci_hostname is not defined or aci_username is not defined or aci_password is not defined # GET Credentials from the inventory - name: Set vars - set_fact: + ansible.builtin.set_fact: aci_info: &aci_info host: "{{ aci_hostname }}" username: "{{ aci_username }}" @@ -22,40 +23,40 @@ # CLEAN ENVIRONMENT - name: Remove ansible_tenant if it already exists - aci_tenant: + cisco.aci.aci_tenant: <<: *aci_info tenant: ansible_tenant state: absent - name: Verify Cloud and Non-Cloud Sites in use. - include_tasks: ../../../../../../integration/targets/aci_cloud_provider/tasks/main.yml + ansible.builtin.include_tasks: ../../../../../../integration/targets/aci_cloud_provider/tasks/main.yml - name: Execute tasks only for non-cloud sites when: query_cloud.current == [] # This condition will execute only non-cloud sites block: # block specifies execution of tasks within, based on conditions - name: Remove ansible_l3ext_domain if it already exists - aci_domain: + cisco.aci.aci_domain: <<: *aci_info domain: ansible_l3ext_domain domain_type: l3dom state: absent - name: Remove ansible_port_channel_ipg if it already exists - aci_interface_policy_leaf_policy_group: + cisco.aci.aci_interface_policy_leaf_policy_group: <<: *aci_info lag_type: link policy_group: ansible_port_channel_ipg state: absent - name: Remove ansible_vpc_ipg if it already exists - aci_interface_policy_leaf_policy_group: + cisco.aci.aci_interface_policy_leaf_policy_group: <<: *aci_info lag_type: node policy_group: ansible_vpc_ipg state: absent - name: Add a new tenant required for l3out - aci_tenant: + cisco.aci.aci_tenant: <<: *aci_info tenant: ansible_tenant description: Ansible tenant @@ -63,7 +64,7 @@ # ADD domain - name: Add domain for l3out - aci_domain: + cisco.aci.aci_domain: <<: *aci_info domain: ansible_l3ext_domain domain_type: l3dom @@ -71,7 +72,7 @@ # ADD VRF - name: Add VRF for l3out - aci_vrf: + cisco.aci.aci_vrf: <<: *aci_info tenant: ansible_tenant vrf: ansible_vrf @@ -79,7 +80,7 @@ # ADD PC IPG - name: Add port-channel IPG - aci_interface_policy_leaf_policy_group: + cisco.aci.aci_interface_policy_leaf_policy_group: <<: *aci_info lag_type: link policy_group: ansible_port_channel_ipg @@ -87,7 +88,7 @@ # ADD vPC IPG - name: Add vPC IPG - aci_interface_policy_leaf_policy_group: + cisco.aci.aci_interface_policy_leaf_policy_group: <<: *aci_info lag_type: node policy_group: ansible_vpc_ipg @@ -95,7 +96,7 @@ # ADD l3out - name: Add l3out - aci_l3out: + cisco.aci.aci_l3out: <<: *aci_info tenant: ansible_tenant name: ansible_l3out @@ -106,7 +107,7 @@ # ADD l3out logical node profile - name: l3out logical node profile - aci_l3out_logical_node_profile: + cisco.aci.aci_l3out_logical_node_profile: <<: *aci_info tenant: ansible_tenant l3out: ansible_l3out @@ -115,7 +116,7 @@ # ADD l3out logical interface profile - name: l3out logical interface profile - aci_l3out_logical_interface_profile: + cisco.aci.aci_l3out_logical_interface_profile: <<: *aci_info tenant: ansible_tenant l3out: ansible_l3out @@ -125,7 +126,7 @@ # ADD l3out interface - name: Add routed interface - aci_l3out_interface: + cisco.aci.aci_l3out_interface: <<: *aci_info tenant: ansible_tenant l3out: ansible_l3out @@ -144,7 +145,7 @@ register: add_l3out_interface - name: Verify l3out has been created with the correct attributes - assert: + ansible.builtin.assert: that: - add_l3out_interface.current.0.l3extRsPathL3OutAtt.attributes.dn == "uni/tn-ansible_tenant/out-ansible_l3out/lnodep-ansible_node_profile/lifp-ansible_interface_profile/rspathL3OutAtt-[topology/pod-1/paths-201/pathep-[eth1/15]]" - add_l3out_interface.current.0.l3extRsPathL3OutAtt.attributes.addr == "192.168.50.1/27" @@ -157,7 +158,7 @@ # ADD l3out interface again to check idempotency - name: Add routed interface again - aci_l3out_interface: + cisco.aci.aci_l3out_interface: <<: *aci_info tenant: ansible_tenant l3out: ansible_l3out @@ -176,13 +177,13 @@ register: add_l3out_interface_again - name: Verify l3out has not changed - assert: + ansible.builtin.assert: that: - add_l3out_interface_again is not changed # MODIFY l3out attributes - name: Update routed interface - aci_l3out_interface: + cisco.aci.aci_l3out_interface: <<: *aci_info tenant: ansible_tenant l3out: ansible_l3out @@ -199,7 +200,7 @@ register: update_l3out_interface - name: Verify routed interface has correct attributes - assert: + ansible.builtin.assert: that: - update_l3out_interface.current.0.l3extRsPathL3OutAtt.attributes.dn == "uni/tn-ansible_tenant/out-ansible_l3out/lnodep-ansible_node_profile/lifp-ansible_interface_profile/rspathL3OutAtt-[topology/pod-1/paths-201/pathep-[eth1/15]]" - update_l3out_interface.current.0.l3extRsPathL3OutAtt.attributes.addr == "192.168.60.1/27" @@ -209,7 +210,7 @@ # QUERY l3out interface - name: Query routed interface - aci_l3out_interface: + cisco.aci.aci_l3out_interface: <<: *aci_info tenant: ansible_tenant l3out: ansible_l3out @@ -222,7 +223,7 @@ register: query_l3out_interface - name: Verify query_l3out_interface - assert: + ansible.builtin.assert: that: - query_l3out_interface is not changed - query_l3out_interface.current.0.l3extRsPathL3OutAtt.attributes.dn == "uni/tn-ansible_tenant/out-ansible_l3out/lnodep-ansible_node_profile/lifp-ansible_interface_profile/rspathL3OutAtt-[topology/pod-1/paths-201/pathep-[eth1/15]]" @@ -232,7 +233,7 @@ - query_l3out_interface.current.0.l3extRsPathL3OutAtt.attributes.mode == "regular" - name: Query all interfaces - aci_l3out_interface: + cisco.aci.aci_l3out_interface: <<: *aci_info tenant: ansible_tenant l3out: ansible_l3out @@ -242,7 +243,7 @@ register: query_l3out_interfaces - name: Verify query_l3out_interfaces - assert: + ansible.builtin.assert: that: - query_l3out_interfaces is not changed - query_l3out_interfaces.current.0.l3extLIfP.children.0.l3extRsPathL3OutAtt.attributes.rn == "rspathL3OutAtt-[topology/pod-1/paths-201/pathep-[eth1/15]]" @@ -253,7 +254,7 @@ # DELETE l3out interface - name: Remove routed sub-interface - aci_l3out_interface: + cisco.aci.aci_l3out_interface: <<: *aci_info tenant: ansible_tenant l3out: ansible_l3out @@ -266,14 +267,14 @@ register: delete_l3out_interface - name: Verify interface has been deleted - assert: + ansible.builtin.assert: that: - delete_l3out_interface.current == [] - delete_l3out_interface.previous.0.l3extRsPathL3OutAtt.attributes.dn == "uni/tn-ansible_tenant/out-ansible_l3out/lnodep-ansible_node_profile/lifp-ansible_interface_profile/rspathL3OutAtt-[topology/pod-1/paths-201/pathep-[eth1/15]]" # ADD l3out port-channel - name: Add routed interface port-channel - aci_l3out_interface: + cisco.aci.aci_l3out_interface: <<: *aci_info tenant: ansible_tenant l3out: ansible_l3out @@ -289,7 +290,7 @@ register: add_l3out_pc_interface - name: Verify l3out port-channel has been created with the correct attributes - assert: + ansible.builtin.assert: that: - add_l3out_pc_interface.current.0.l3extRsPathL3OutAtt.attributes.dn == "uni/tn-ansible_tenant/out-ansible_l3out/lnodep-ansible_node_profile/lifp-ansible_interface_profile/rspathL3OutAtt-[topology/pod-1/paths-201/pathep-[ansible_port_channel_ipg]]" - add_l3out_pc_interface.current.0.l3extRsPathL3OutAtt.attributes.addr == "192.168.70.1/27" @@ -298,7 +299,7 @@ # ADD l3out port-channel again to check idempotency - name: Add routed interface port-channel again - aci_l3out_interface: + cisco.aci.aci_l3out_interface: <<: *aci_info tenant: ansible_tenant l3out: ansible_l3out @@ -314,13 +315,13 @@ register: add_l3out_pc_interface_again - name: Verify interface has not changed - assert: + ansible.builtin.assert: that: - add_l3out_pc_interface_again is not changed # MODIFY l3out port-channel attributes - name: Update routed port-channel interface - aci_l3out_interface: + cisco.aci.aci_l3out_interface: <<: *aci_info tenant: ansible_tenant l3out: ansible_l3out @@ -336,7 +337,7 @@ register: update_l3out_pc_interface - name: Verify l3out port-channel has been updated with the correct attributes - assert: + ansible.builtin.assert: that: - update_l3out_pc_interface is changed - update_l3out_pc_interface.current.0.l3extRsPathL3OutAtt.attributes.dn == "uni/tn-ansible_tenant/out-ansible_l3out/lnodep-ansible_node_profile/lifp-ansible_interface_profile/rspathL3OutAtt-[topology/pod-1/paths-201/pathep-[ansible_port_channel_ipg]]" @@ -346,7 +347,7 @@ # QUERY l3out port-channel interface - name: Query l3out port-channel - aci_l3out_interface: + cisco.aci.aci_l3out_interface: <<: *aci_info tenant: ansible_tenant l3out: ansible_l3out @@ -359,7 +360,7 @@ register: query_l3out_pc_interface - name: Verify query_l3out_pc_interface - assert: + ansible.builtin.assert: that: - query_l3out_pc_interface is not changed - query_l3out_pc_interface.current.0.l3extRsPathL3OutAtt.attributes.dn == "uni/tn-ansible_tenant/out-ansible_l3out/lnodep-ansible_node_profile/lifp-ansible_interface_profile/rspathL3OutAtt-[topology/pod-1/paths-201/pathep-[ansible_port_channel_ipg]]" @@ -369,7 +370,7 @@ # DELETE l3out port-channel interface - name: Remove port-channel - aci_l3out_interface: + cisco.aci.aci_l3out_interface: <<: *aci_info tenant: ansible_tenant l3out: ansible_l3out @@ -382,14 +383,14 @@ register: delete_l3out_pc_interface - name: Verify interface has been deleted - assert: + ansible.builtin.assert: that: - delete_l3out_pc_interface.current == [] - delete_l3out_pc_interface.previous.0.l3extRsPathL3OutAtt.attributes.dn == "uni/tn-ansible_tenant/out-ansible_l3out/lnodep-ansible_node_profile/lifp-ansible_interface_profile/rspathL3OutAtt-[topology/pod-1/paths-201/pathep-[ansible_port_channel_ipg]]" # ADD l3out vPC - name: Add interface vPC - aci_l3out_interface: + cisco.aci.aci_l3out_interface: &ext_svi_interface <<: *aci_info tenant: ansible_tenant l3out: ansible_l3out @@ -402,43 +403,45 @@ mode: native addr: 192.168.90.1/27 encap: vlan-913 + mac: "00:22:BD:F8:19:FE" + description: "anisble test description" state: present register: add_l3out_vpc_interface - name: Verify l3out vPC has been created with the correct attributes - assert: + ansible.builtin.assert: that: - add_l3out_vpc_interface.current.0.l3extRsPathL3OutAtt.attributes.dn == "uni/tn-ansible_tenant/out-ansible_l3out/lnodep-ansible_node_profile/lifp-ansible_interface_profile/rspathL3OutAtt-[topology/pod-1/protpaths-201-202/pathep-[ansible_vpc_ipg]]" - add_l3out_vpc_interface.current.0.l3extRsPathL3OutAtt.attributes.addr == "192.168.90.1/27" - add_l3out_vpc_interface.current.0.l3extRsPathL3OutAtt.attributes.ifInstT == "ext-svi" - add_l3out_vpc_interface.current.0.l3extRsPathL3OutAtt.attributes.encap == "vlan-913" + - add_l3out_vpc_interface.current.0.l3extRsPathL3OutAtt.attributes.encapScope == "local" - add_l3out_vpc_interface.current.0.l3extRsPathL3OutAtt.attributes.mode == "native" + - add_l3out_vpc_interface.current.0.l3extRsPathL3OutAtt.attributes.mac == "00:22:BD:F8:19:FE" + - add_l3out_vpc_interface.current.0.l3extRsPathL3OutAtt.attributes.descr == "anisble test description" - name: Add interface vPC again - aci_l3out_interface: - <<: *aci_info - tenant: ansible_tenant - l3out: ansible_l3out - node_profile: ansible_node_profile - interface_profile: ansible_interface_profile - pod_id: 1 - node_id: 201-202 - path_ep: ansible_vpc_ipg - interface_type: ext-svi - mode: native - addr: 192.168.90.1/27 - encap: vlan-913 - state: present + cisco.aci.aci_l3out_interface: + <<: *ext_svi_interface register: add_l3out_vpc_interface_again + - name: Change encap_scope on interface vPC + cisco.aci.aci_l3out_interface: + <<: *ext_svi_interface + encap_scope: vrf + state: present + register: change_l3out_vpc_interface_encap_scope + - name: Verify vPC interface is not changed - assert: + ansible.builtin.assert: that: - add_l3out_vpc_interface_again is not changed + - change_l3out_vpc_interface_encap_scope.previous.0.l3extRsPathL3OutAtt.attributes.encapScope == "local" + - change_l3out_vpc_interface_encap_scope.current.0.l3extRsPathL3OutAtt.attributes.encapScope == "ctx" # MODIFY vPC interface - name: Update interface vPC - aci_l3out_interface: + cisco.aci.aci_l3out_interface: <<: *aci_info tenant: ansible_tenant l3out: ansible_l3out @@ -455,7 +458,7 @@ register: modify_l3out_vpc_interface - name: Verify l3out vPC has been updated with the correct attributes - assert: + ansible.builtin.assert: that: - modify_l3out_vpc_interface is changed - modify_l3out_vpc_interface.current.0.l3extRsPathL3OutAtt.attributes.dn == "uni/tn-ansible_tenant/out-ansible_l3out/lnodep-ansible_node_profile/lifp-ansible_interface_profile/rspathL3OutAtt-[topology/pod-1/protpaths-201-202/pathep-[ansible_vpc_ipg]]" @@ -466,7 +469,7 @@ # QUERY vPC interface - name: Query vPC interface - aci_l3out_interface: + cisco.aci.aci_l3out_interface: <<: *aci_info tenant: ansible_tenant l3out: ansible_l3out @@ -479,7 +482,7 @@ register: query_l3out_vpc_interface - name: Verify l3out vPC query - assert: + ansible.builtin.assert: that: - query_l3out_vpc_interface is not changed - query_l3out_vpc_interface.current.0.l3extRsPathL3OutAtt.attributes.dn == "uni/tn-ansible_tenant/out-ansible_l3out/lnodep-ansible_node_profile/lifp-ansible_interface_profile/rspathL3OutAtt-[topology/pod-1/protpaths-201-202/pathep-[ansible_vpc_ipg]]" @@ -489,7 +492,7 @@ - query_l3out_vpc_interface.current.0.l3extRsPathL3OutAtt.attributes.mode == "regular" - name: Delete vPC interface - aci_l3out_interface: + cisco.aci.aci_l3out_interface: <<: *aci_info tenant: ansible_tenant l3out: ansible_l3out @@ -502,33 +505,264 @@ register: delete_l3out_vpc_interface - name: Verify vPC interface is deleted - assert: + ansible.builtin.assert: that: - delete_l3out_vpc_interface.current == [] + - name: Execute tasks only for APIC version 5.x and above + when: + - version.current.0.topSystem.attributes.version is version('5', '>=') # This condition will execute only for APIC version 5.x and above + block: + + - name: Ensure infra SR-MPLS l3out does not exist + cisco.aci.aci_l3out: &aci_infra_sr_mpls_l3out_absent + <<: *aci_info + tenant: infra + name: ansible_infra_sr_mpls_l3out + domain: ansible_dom + vrf: overlay-1 + mpls: "yes" + l3protocol: bgp + state: absent + + - name: Add a infra SR-MPLS l3out + cisco.aci.aci_l3out: + <<: *aci_infra_sr_mpls_l3out_absent + state: present + + - name: Add a node profile in the infra SR-MPLS l3out + cisco.aci.aci_l3out_logical_node_profile: &aci_infra_node_profile + <<: *aci_info + tenant: infra + l3out: ansible_infra_sr_mpls_l3out + node_profile: ansible_infra_sr_mpls_l3out_node_profile + + - name: Add interface profile in the infra SR-MPLS l3out node profile + cisco.aci.aci_l3out_logical_interface_profile: &aci_infra_interface_profile + <<: *aci_infra_node_profile + interface_profile: ansible_infra_sr_mpls_l3out_interface_profile + + - name: Add direct port channel interface in the infra SR-MPLS l3out interface profile (check_mode) + aci_l3out_interface: &aci_infra_pc_interface + <<: *aci_infra_interface_profile + pod_id: 1 + node_id: 101 + path_ep: pc_ansible_test + interface_type: l3-port + addr: 192.168.90.1/24 + state: present + register: cm_add_infra_sr_mpls_l3out_port_channel_interface + check_mode: true + + - name: Add direct port channel interface in the infra SR-MPLS l3out interface profile + aci_l3out_interface: + <<: *aci_infra_pc_interface + register: nm_add_infra_sr_mpls_l3out_port_channel_interface + + - name: Add direct port channel interface in the infra SR-MPLS l3out interface profile again + aci_l3out_interface: + <<: *aci_infra_pc_interface + register: nm_add_infra_sr_mpls_l3out_port_channel_interface_again + + - name: Add interface in the infra SR-MPLS l3out interface profile + aci_l3out_interface: &aci_infra_interface + <<: *aci_infra_interface_profile + pod_id: 1 + node_id: 101 + path_ep: eth1/17 + interface_type: l3-port + addr: 192.168.91.1/24 + state: present + register: nm_add_infra_sr_mpls_l3out_interface + + - name: Add sub interface in the infra SR-MPLS l3out interface profile + aci_l3out_interface: &aci_infra_sub_interface + <<: *aci_infra_interface_profile + pod_id: 1 + node_id: 101 + path_ep: eth1/18 + interface_type: sub-interface + addr: 192.168.92.1/24 + state: present + register: nm_add_infra_sr_mpls_l3out_sub_interface + + - name: Verify interfaces in the infra SR-MPLS l3out interface profile + assert: + that: + - cm_add_infra_sr_mpls_l3out_port_channel_interface is changed + - cm_add_infra_sr_mpls_l3out_port_channel_interface.previous == [] + - cm_add_infra_sr_mpls_l3out_port_channel_interface.proposed.l3extRsPathL3OutAtt.attributes.annotation == "orchestrator:ansible" + - cm_add_infra_sr_mpls_l3out_port_channel_interface.proposed.l3extRsPathL3OutAtt.attributes.addr == "192.168.90.1/24" + - cm_add_infra_sr_mpls_l3out_port_channel_interface.proposed.l3extRsPathL3OutAtt.attributes.ifInstT == "l3-port" + - cm_add_infra_sr_mpls_l3out_port_channel_interface.proposed.l3extRsPathL3OutAtt.attributes.tDn == "topology/pod-1/paths-101/pathep-[pc_ansible_test]" + - nm_add_infra_sr_mpls_l3out_port_channel_interface is changed + - nm_add_infra_sr_mpls_l3out_port_channel_interface.previous == [] + - nm_add_infra_sr_mpls_l3out_port_channel_interface.current.0.l3extRsPathL3OutAtt.attributes.annotation == "orchestrator:ansible" + - nm_add_infra_sr_mpls_l3out_port_channel_interface.current.0.l3extRsPathL3OutAtt.attributes.addr == "192.168.90.1/24" + - nm_add_infra_sr_mpls_l3out_port_channel_interface.current.0.l3extRsPathL3OutAtt.attributes.ifInstT == "l3-port" + - nm_add_infra_sr_mpls_l3out_port_channel_interface.current.0.l3extRsPathL3OutAtt.attributes.tDn == "topology/pod-1/paths-101/pathep-[pc_ansible_test]" + - nm_add_infra_sr_mpls_l3out_port_channel_interface_again is not changed + - nm_add_infra_sr_mpls_l3out_port_channel_interface_again.previous.0.l3extRsPathL3OutAtt.attributes.annotation == "orchestrator:ansible" + - nm_add_infra_sr_mpls_l3out_port_channel_interface_again.previous.0.l3extRsPathL3OutAtt.attributes.addr == "192.168.90.1/24" + - nm_add_infra_sr_mpls_l3out_port_channel_interface_again.previous.0.l3extRsPathL3OutAtt.attributes.ifInstT == "l3-port" + - nm_add_infra_sr_mpls_l3out_port_channel_interface_again.previous.0.l3extRsPathL3OutAtt.attributes.tDn == "topology/pod-1/paths-101/pathep-[pc_ansible_test]" + - nm_add_infra_sr_mpls_l3out_port_channel_interface_again.current.0.l3extRsPathL3OutAtt.attributes.annotation == "orchestrator:ansible" + - nm_add_infra_sr_mpls_l3out_port_channel_interface_again.current.0.l3extRsPathL3OutAtt.attributes.addr == "192.168.90.1/24" + - nm_add_infra_sr_mpls_l3out_port_channel_interface_again.current.0.l3extRsPathL3OutAtt.attributes.ifInstT == "l3-port" + - nm_add_infra_sr_mpls_l3out_port_channel_interface_again.current.0.l3extRsPathL3OutAtt.attributes.tDn == "topology/pod-1/paths-101/pathep-[pc_ansible_test]" + - nm_add_infra_sr_mpls_l3out_interface is changed + - nm_add_infra_sr_mpls_l3out_interface.previous == [] + - nm_add_infra_sr_mpls_l3out_interface.current.0.l3extRsPathL3OutAtt.attributes.annotation == "orchestrator:ansible" + - nm_add_infra_sr_mpls_l3out_interface.current.0.l3extRsPathL3OutAtt.attributes.addr == "192.168.91.1/24" + - nm_add_infra_sr_mpls_l3out_interface.current.0.l3extRsPathL3OutAtt.attributes.ifInstT == "l3-port" + - nm_add_infra_sr_mpls_l3out_interface.current.0.l3extRsPathL3OutAtt.attributes.tDn == "topology/pod-1/paths-101/pathep-[eth1/17]" + - nm_add_infra_sr_mpls_l3out_sub_interface is changed + - nm_add_infra_sr_mpls_l3out_sub_interface.previous == [] + - nm_add_infra_sr_mpls_l3out_sub_interface.current.0.l3extRsPathL3OutAtt.attributes.annotation == "orchestrator:ansible" + - nm_add_infra_sr_mpls_l3out_sub_interface.current.0.l3extRsPathL3OutAtt.attributes.addr == "192.168.92.1/24" + - nm_add_infra_sr_mpls_l3out_sub_interface.current.0.l3extRsPathL3OutAtt.attributes.ifInstT == "sub-interface" + - nm_add_infra_sr_mpls_l3out_sub_interface.current.0.l3extRsPathL3OutAtt.attributes.tDn == "topology/pod-1/paths-101/pathep-[eth1/18]" + + - name: Enable micro BFD on direct port channel interface in the infra SR-MPLS l3out interface profile without destination (error) + aci_l3out_interface: + <<: *aci_infra_pc_interface + micro_bfd: true + register: err_micro_bfd_not_provided_destination + ignore_errors: true + + - name: Enable micro BFD on direct port channel interface in the infra SR-MPLS l3out interface profile timer without micro BFD (error) + aci_l3out_interface: + <<: *aci_infra_pc_interface + micro_bfd_timer: 75 + register: err_micro_bfd_timer_not_provided_micro_bfd + ignore_errors: true + + - name: Enable micro BFD on direct port channel interface in the infra SR-MPLS l3out interface profile destination without micro BFD (error) + aci_l3out_interface: + <<: *aci_infra_pc_interface + micro_bfd_destination: true + register: err_micro_bfd_destination_not_provided_micro_bfd + ignore_errors: true + + - name: Verify micro BFD errors + assert: + that: + - err_micro_bfd_not_provided_destination is failed + - err_micro_bfd_not_provided_destination.msg == "micro_bfd is True but all of the following are missing{{":"}} micro_bfd_destination" + - err_micro_bfd_timer_not_provided_micro_bfd is failed + - err_micro_bfd_timer_not_provided_micro_bfd.msg == "missing parameter(s) required by 'micro_bfd_timer'{{":"}} micro_bfd" + - err_micro_bfd_destination_not_provided_micro_bfd is failed + - err_micro_bfd_destination_not_provided_micro_bfd.msg == "missing parameter(s) required by 'micro_bfd_destination'{{":"}} micro_bfd" + + - name: Enable micro BFD on direct port channel interface in the infra SR-MPLS l3out interface (check_mode) + aci_l3out_interface: &enable_bfd + <<: *aci_infra_pc_interface + micro_bfd: true + micro_bfd_destination: 192.168.90.2 + register: cm_enable_micro_bfd + check_mode: true + + - name: Enable micro BFD on direct port channel interface in the infra SR-MPLS l3out interface + aci_l3out_interface: + <<: *enable_bfd + register: nm_enable_micro_bfd + + - name: Change timer for micro on direct port channel interface in the infra SR-MPLS l3out interface + aci_l3out_interface: + <<: *enable_bfd + micro_bfd_timer: 75 + register: nm_change_micro_bfd_timer + + - name: Diable micro BFD on direct port channel interface in the infra SR-MPLS l3out interface + aci_l3out_interface: + <<: *enable_bfd + micro_bfd: false + register: nm_disable_micro_bfd + + - name: Verify micro BFD configuration on direct port channel interface in the infra SR-MPLS l3out interface + assert: + that: + - cm_enable_micro_bfd is changed + - cm_enable_micro_bfd.previous.0.l3extRsPathL3OutAtt.children is undefined + - cm_enable_micro_bfd.proposed.l3extRsPathL3OutAtt.children.0.bfdMicroBfdP.attributes.adminState == "yes" + - cm_enable_micro_bfd.proposed.l3extRsPathL3OutAtt.children.0.bfdMicroBfdP.attributes.dst == "192.168.90.2" + - nm_enable_micro_bfd is changed + - nm_enable_micro_bfd.previous.0.l3extRsPathL3OutAtt.children is undefined + - nm_enable_micro_bfd.current.0.l3extRsPathL3OutAtt.children.0.bfdMicroBfdP.attributes.adminState == "yes" + - nm_enable_micro_bfd.current.0.l3extRsPathL3OutAtt.children.0.bfdMicroBfdP.attributes.dst == "192.168.90.2" + - nm_enable_micro_bfd.current.0.l3extRsPathL3OutAtt.children.0.bfdMicroBfdP.attributes.stTm == "0" + - nm_change_micro_bfd_timer is changed + - nm_change_micro_bfd_timer.previous.0.l3extRsPathL3OutAtt.children.0.bfdMicroBfdP.attributes.adminState == "yes" + - nm_change_micro_bfd_timer.previous.0.l3extRsPathL3OutAtt.children.0.bfdMicroBfdP.attributes.dst == "192.168.90.2" + - nm_change_micro_bfd_timer.previous.0.l3extRsPathL3OutAtt.children.0.bfdMicroBfdP.attributes.stTm == "0" + - nm_change_micro_bfd_timer.current.0.l3extRsPathL3OutAtt.children.0.bfdMicroBfdP.attributes.adminState == "yes" + - nm_change_micro_bfd_timer.current.0.l3extRsPathL3OutAtt.children.0.bfdMicroBfdP.attributes.dst == "192.168.90.2" + - nm_change_micro_bfd_timer.current.0.l3extRsPathL3OutAtt.children.0.bfdMicroBfdP.attributes.stTm == "75" + - nm_disable_micro_bfd is changed + - nm_disable_micro_bfd.previous.0.l3extRsPathL3OutAtt.children.0.bfdMicroBfdP.attributes.adminState == "yes" + - nm_disable_micro_bfd.previous.0.l3extRsPathL3OutAtt.children.0.bfdMicroBfdP.attributes.dst == "192.168.90.2" + - nm_disable_micro_bfd.previous.0.l3extRsPathL3OutAtt.children.0.bfdMicroBfdP.attributes.stTm == "75" + - nm_disable_micro_bfd.current.0.l3extRsPathL3OutAtt.children.0.bfdMicroBfdP.attributes.adminState == "no" + - nm_disable_micro_bfd.current.0.l3extRsPathL3OutAtt.children.0.bfdMicroBfdP.attributes.dst == "192.168.90.2" + - nm_disable_micro_bfd.current.0.l3extRsPathL3OutAtt.children.0.bfdMicroBfdP.attributes.stTm == "75" + + - name: Delete direct port channel interface in the infra SR-MPLS l3out interface profile again (check_mode) + aci_l3out_interface: &aci_infra_pc_interface_absent + <<: *aci_infra_pc_interface + state: absent + register: cm_delete_infra_sr_mpls_l3out_port_channel_interface + check_mode: true + + - name: Delete direct port channel interface in the infra SR-MPLS l3out interface profile + aci_l3out_interface: + <<: *aci_infra_pc_interface_absent + register: nm_delete_infra_sr_mpls_l3out_port_channel_interface + + - name: Delete direct port channel interface in the infra SR-MPLS l3out interface profile again + aci_l3out_interface: + <<: *aci_infra_pc_interface_absent + register: nm_delete_infra_sr_mpls_l3out_port_channel_interface_again + + - name: Verify deletion of port channel interfaces in the infra SR-MPLS l3out interface profile + assert: + that: + - cm_delete_infra_sr_mpls_l3out_port_channel_interface is changed + - cm_delete_infra_sr_mpls_l3out_port_channel_interface.previous != [] + - cm_delete_infra_sr_mpls_l3out_port_channel_interface.proposed == {} + - nm_delete_infra_sr_mpls_l3out_port_channel_interface is changed + - nm_delete_infra_sr_mpls_l3out_port_channel_interface.previous != [] + - nm_delete_infra_sr_mpls_l3out_port_channel_interface.current == [] + - nm_delete_infra_sr_mpls_l3out_port_channel_interface_again is not changed + - nm_delete_infra_sr_mpls_l3out_port_channel_interface_again.previous == [] + - nm_delete_infra_sr_mpls_l3out_port_channel_interface_again.current == [] + + - name: Remove a infra SR-MPLS l3out + cisco.aci.aci_l3out: + <<: *aci_infra_sr_mpls_l3out_absent + # CLEAN UP - name: Remove ansible_tenant - aci_tenant: + cisco.aci.aci_tenant: <<: *aci_info tenant: ansible_tenant state: absent - name: Remove ansible_l3ext_domain - aci_domain: + cisco.aci.aci_domain: <<: *aci_info domain: ansible_l3ext_domain domain_type: l3dom state: absent - name: Remove ansible_port_channel_ipg - aci_interface_policy_leaf_policy_group: + cisco.aci.aci_interface_policy_leaf_policy_group: <<: *aci_info lag_type: link policy_group: ansible_port_channel_ipg state: absent - name: Remove ansible_vpc_ipg - aci_interface_policy_leaf_policy_group: + cisco.aci.aci_interface_policy_leaf_policy_group: <<: *aci_info lag_type: node policy_group: ansible_vpc_ipg diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_l3out_interface_secondary_ip/tasks/main.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_l3out_interface_secondary_ip/tasks/main.yml index 775d40ee8..df49658be 100644 --- a/ansible_collections/cisco/aci/tests/integration/targets/aci_l3out_interface_secondary_ip/tasks/main.yml +++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_l3out_interface_secondary_ip/tasks/main.yml @@ -4,13 +4,13 @@ # GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) - name: Test that we have an ACI APIC host, ACI username and ACI password - fail: + ansible.builtin.fail: msg: 'Please define the following variables: aci_hostname, aci_username and aci_password.' when: aci_hostname is not defined or aci_username is not defined or aci_password is not defined # GET Credentials from the inventory - name: Set vars - set_fact: + ansible.builtin.set_fact: aci_info: &aci_info host: "{{ aci_hostname }}" username: "{{ aci_username }}" @@ -22,26 +22,26 @@ # CLEAN ENVIRONMENT - name: Remove test tenant if it already exists - aci_tenant: + cisco.aci.aci_tenant: <<: *aci_info tenant: ansible_test state: absent - name: Verify Cloud and Non-Cloud Sites in use. - include_tasks: ../../../../../../integration/targets/aci_cloud_provider/tasks/main.yml + ansible.builtin.include_tasks: ../../../../../../integration/targets/aci_cloud_provider/tasks/main.yml - name: Execute tasks only for non-cloud sites when: query_cloud.current == [] # This condition will execute only non-cloud sites block: # block specifies execution of tasks within, based on conditions - name: Remove port-channel IPG - aci_interface_policy_leaf_policy_group: + cisco.aci.aci_interface_policy_leaf_policy_group: <<: *aci_info lag_type: link policy_group: ansible_port_channel_ipg state: absent - name: Remove vPC IPG - aci_interface_policy_leaf_policy_group: + cisco.aci.aci_interface_policy_leaf_policy_group: <<: *aci_info lag_type: node policy_group: ansible_vpc_ipg @@ -49,7 +49,7 @@ # ADD PC IPG - name: Add port-channel IPG - aci_interface_policy_leaf_policy_group: + cisco.aci.aci_interface_policy_leaf_policy_group: <<: *aci_info lag_type: link policy_group: ansible_port_channel_ipg @@ -57,7 +57,7 @@ # ADD vPC IPG - name: Add vPC IPG - aci_interface_policy_leaf_policy_group: + cisco.aci.aci_interface_policy_leaf_policy_group: <<: *aci_info lag_type: node policy_group: ansible_vpc_ipg @@ -65,7 +65,7 @@ # ADD domain - name: Add domain for l3out - aci_domain: + cisco.aci.aci_domain: <<: *aci_info domain: ansible_l3ext_domain domain_type: l3dom @@ -73,7 +73,7 @@ # ADD tenant - name: Add a new tenant required for l3out - aci_tenant: + cisco.aci.aci_tenant: <<: *aci_info tenant: ansible_test description: Ansible tenant @@ -81,7 +81,7 @@ # ADD VRF - name: Add VRF for l3out - aci_vrf: + cisco.aci.aci_vrf: <<: *aci_info tenant: ansible_test vrf: ansible_vrf @@ -89,7 +89,7 @@ # ADD l3out - name: Add l3out - aci_l3out: + cisco.aci.aci_l3out: <<: *aci_info tenant: ansible_test name: ansible_l3out @@ -100,7 +100,7 @@ # ADD l3out logical node profile - name: l3out logical node profile - aci_l3out_logical_node_profile: + cisco.aci.aci_l3out_logical_node_profile: <<: *aci_info tenant: ansible_test l3out: ansible_l3out @@ -109,7 +109,7 @@ # ADD l3out logical interface profile - name: l3out logical interface profile - aci_l3out_logical_interface_profile: + cisco.aci.aci_l3out_logical_interface_profile: <<: *aci_info tenant: ansible_test l3out: ansible_l3out @@ -119,7 +119,7 @@ # ADD l3out routed interface - name: Add routed interface - aci_l3out_interface: + cisco.aci.aci_l3out_interface: <<: *aci_info tenant: ansible_test l3out: ansible_l3out @@ -135,7 +135,7 @@ # ADD l3out routed interface po - name: Add routed interface port-channel - aci_l3out_interface: + cisco.aci.aci_l3out_interface: <<: *aci_info tenant: ansible_test l3out: ansible_l3out @@ -151,7 +151,7 @@ # ADD l3out routed interface vPC - name: Add routed interface vPC - aci_l3out_interface: + cisco.aci.aci_l3out_interface: <<: *aci_info tenant: ansible_test l3out: ansible_l3out @@ -167,7 +167,7 @@ # ADD l3out routed interface vPC member - name: Add routed interface vPC member - aci_l3out_logical_interface_vpc_member: + cisco.aci.aci_l3out_logical_interface_vpc_member: <<: *aci_info tenant: ansible_test l3out: ansible_l3out @@ -182,7 +182,7 @@ # ADD secondary IPs to the interfaces - name: Add secondary IP to routed interface - aci_l3out_interface_secondary_ip: + cisco.aci.aci_l3out_interface_secondary_ip: <<: *aci_info tenant: ansible_test l3out: ansible_l3out @@ -197,7 +197,7 @@ register: secondary_intf - name: Add secondary to IP routed interface port-channel - aci_l3out_interface_secondary_ip: + cisco.aci.aci_l3out_interface_secondary_ip: <<: *aci_info tenant: ansible_test l3out: ansible_l3out @@ -212,7 +212,7 @@ register: secondary_po - name: Add secondary IP to routed interface vPC - aci_l3out_interface_secondary_ip: + cisco.aci.aci_l3out_interface_secondary_ip: <<: *aci_info tenant: ansible_test l3out: ansible_l3out @@ -228,7 +228,7 @@ register: secondary_vpc - name: Verify secondaries have been created with the correct attributes - assert: + ansible.builtin.assert: that: - secondary_intf.current.0.l3extIp.attributes.dn == "uni/tn-ansible_test/out-ansible_l3out/lnodep-ansible_node_profile/lifp-ansible_interface_profile/rspathL3OutAtt-[topology/pod-1/paths-201/pathep-[eth1/15]]/addr-[192.168.50.2/27]" - secondary_intf.current.0.l3extIp.attributes.ipv6Dad == "disabled" @@ -240,7 +240,7 @@ # CHECK idempotency - name: Add secondary IP to routed interface with no changes - aci_l3out_interface_secondary_ip: + cisco.aci.aci_l3out_interface_secondary_ip: <<: *aci_info tenant: ansible_test l3out: ansible_l3out @@ -255,7 +255,7 @@ register: secondary_intf_again - name: Add secondary to IP routed interface port-channel with no changes - aci_l3out_interface_secondary_ip: + cisco.aci.aci_l3out_interface_secondary_ip: <<: *aci_info tenant: ansible_test l3out: ansible_l3out @@ -270,7 +270,7 @@ register: secondary_po_again - name: Add secondary IP to routed interface vPC with no changes - aci_l3out_interface_secondary_ip: + cisco.aci.aci_l3out_interface_secondary_ip: <<: *aci_info tenant: ansible_test l3out: ansible_l3out @@ -286,7 +286,7 @@ register: secondary_vpc_again - name: Verify MOs have not changed - assert: + ansible.builtin.assert: that: - secondary_intf_again is not changed - secondary_po_again is not changed @@ -294,7 +294,7 @@ # CHECK updates/modifications - name: Modify routed interface - aci_l3out_interface_secondary_ip: + cisco.aci.aci_l3out_interface_secondary_ip: <<: *aci_info tenant: ansible_test l3out: ansible_l3out @@ -309,7 +309,7 @@ register: secondary_intf_update - name: Modify routed port-channel - aci_l3out_interface_secondary_ip: + cisco.aci.aci_l3out_interface_secondary_ip: <<: *aci_info tenant: ansible_test l3out: ansible_l3out @@ -324,7 +324,7 @@ register: secondary_po_update - name: Modify routed vPC - aci_l3out_interface_secondary_ip: + cisco.aci.aci_l3out_interface_secondary_ip: <<: *aci_info tenant: ansible_test l3out: ansible_l3out @@ -340,7 +340,7 @@ register: secondary_vpc_update - name: Verify updates have been applied - assert: + ansible.builtin.assert: that: - secondary_intf_update is changed - secondary_po_update is changed @@ -351,7 +351,7 @@ # QUERIES - name: Query secondary for interface - aci_l3out_interface_secondary_ip: + cisco.aci.aci_l3out_interface_secondary_ip: <<: *aci_info tenant: ansible_test l3out: ansible_l3out @@ -366,7 +366,7 @@ register: secondary_intf_query - name: Query secondary for po - aci_l3out_interface_secondary_ip: + cisco.aci.aci_l3out_interface_secondary_ip: <<: *aci_info tenant: ansible_test l3out: ansible_l3out @@ -381,7 +381,7 @@ register: secondary_po_query - name: Query secondary for vpc - aci_l3out_interface_secondary_ip: + cisco.aci.aci_l3out_interface_secondary_ip: <<: *aci_info tenant: ansible_test l3out: ansible_l3out @@ -397,13 +397,13 @@ register: secondary_vpc_query - name: Query all secondary IPs - aci_l3out_interface_secondary_ip: + cisco.aci.aci_l3out_interface_secondary_ip: <<: *aci_info state: query register: secondary_all_query - name: Verify queries - assert: + ansible.builtin.assert: that: - secondary_intf_query is not changed - secondary_po_query is not changed @@ -418,7 +418,7 @@ # DELETE secondary IPs - name: Delete secondary for interface - aci_l3out_interface_secondary_ip: + cisco.aci.aci_l3out_interface_secondary_ip: <<: *aci_info tenant: ansible_test l3out: ansible_l3out @@ -433,7 +433,7 @@ register: secondary_intf_remove - name: Delete secondary for po - aci_l3out_interface_secondary_ip: + cisco.aci.aci_l3out_interface_secondary_ip: <<: *aci_info tenant: ansible_test l3out: ansible_l3out @@ -448,7 +448,7 @@ register: secondary_po_remove - name: Delete secondary for vpc - aci_l3out_interface_secondary_ip: + cisco.aci.aci_l3out_interface_secondary_ip: <<: *aci_info tenant: ansible_test l3out: ansible_l3out @@ -464,7 +464,7 @@ register: secondary_vpc_remove - name: Verify objects have been deleted - assert: + ansible.builtin.assert: that: - secondary_intf_remove.current == [] - secondary_po_remove.current == [] @@ -475,27 +475,27 @@ # CLEAN UP - name: Remove tenant - aci_tenant: + cisco.aci.aci_tenant: <<: *aci_info tenant: ansible_test state: absent - name: Remove ext domain - aci_domain: + cisco.aci.aci_domain: <<: *aci_info domain: ansible_l3ext_domain domain_type: l3dom state: absent - name: Remove port-channel - aci_interface_policy_leaf_policy_group: + cisco.aci.aci_interface_policy_leaf_policy_group: <<: *aci_info lag_type: link policy_group: ansible_port_channel_ipg state: absent - name: Remove vpc - aci_interface_policy_leaf_policy_group: + cisco.aci.aci_interface_policy_leaf_policy_group: <<: *aci_info lag_type: node policy_group: ansible_vpc_ipg diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_l3out_logical_interface_profile/tasks/main.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_l3out_logical_interface_profile/tasks/main.yml index b3ad827f1..506690c70 100644 --- a/ansible_collections/cisco/aci/tests/integration/targets/aci_l3out_logical_interface_profile/tasks/main.yml +++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_l3out_logical_interface_profile/tasks/main.yml @@ -1,9 +1,12 @@ +# Test code for the ACI modules # Author: Marcel Zehnder (@maercu) +# Copyright: (c) 2024, Gaspard Micol (@gmicol) + # GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) # SET VARS - name: Set vars - set_fact: + ansible.builtin.set_fact: aci_info: &aci_info host: '{{ aci_hostname }}' username: '{{ aci_username }}' @@ -15,164 +18,287 @@ # CLEAN ENVIRONMENT - name: Remove test tenant before we kickoff - cisco.aci.aci_tenant: &tenant_absent + cisco.aci.aci_tenant: &aci_tenant_absent <<: *aci_info - tenant: ansible_test + tenant: ansible_tenant state: absent - name: Verify Cloud and Non-Cloud Sites in use. - include_tasks: ../../../../../../integration/targets/aci_cloud_provider/tasks/main.yml + ansible.builtin.include_tasks: ../../../../../../integration/targets/aci_cloud_provider/tasks/main.yml - name: Execute tasks only for non-cloud sites when: query_cloud.current == [] # This condition will execute only non-cloud sites block: # block specifies execution of tasks within, based on conditions # SETUP ENVIRONMENT - name: Create domain - cisco.aci.aci_domain: &domain_present + cisco.aci.aci_domain: &aci_domain_present <<: *aci_info - domain: l3outintftest + domain: ansible_dom domain_type: l3dom state: present - name: Create tenant - cisco.aci.aci_tenant: &tenant_present - <<: *tenant_absent + cisco.aci.aci_tenant: &aci_tenant_present + <<: *aci_tenant_absent state: present - name: Configure VRF - cisco.aci.aci_vrf: &vrf_present - <<: *tenant_present - vrf: l3outintftest + cisco.aci.aci_vrf: &aci_vrf_present + <<: *aci_tenant_present + vrf: ansible_vrf + state: present - name: Create L3Out cisco.aci.aci_l3out: - <<: *vrf_present - l3out: l3outintftest - domain: l3outintftest - route_control: export + <<: *aci_vrf_present + l3out: ansible_l3out + domain: ansible_dom + state: present - name: Crete node profile - cisco.aci.aci_l3out_logical_node_profile: &np_present - <<: *tenant_present - l3out: l3outintftest - node_profile: NODES - - # BEGIN WITH TESTS (ADD PROFILE) - - name: Add interface profile (check_mode) - cisco.aci.aci_l3out_logical_interface_profile: &intf_present - <<: *np_present - interface_profile: INTFS - description: test + cisco.aci.aci_l3out_logical_node_profile: &aci_np_present + <<: *aci_tenant_present + l3out: ansible_l3out + node_profile: ansible_node_profile + state: present + +# CREATE Logical Interface Profile + - name: Add a Logical Interface Profile (check_mode) + cisco.aci.aci_l3out_logical_interface_profile: &aci_l3out_logical_interface_profile_present + <<: *aci_np_present + interface_profile: ansible_interface_profile_1 + description: Logical Interface Profile 1 for ansible_node_profile + nd_policy: default + egress_dpp_policy: default + ingress_dpp_policy: default + qos_priority: level1 + qos_custom_policy: default + pim_v4_interface_profile: + tenant: common + pim: default + pim_v6_interface_profile: + tenant: common + pim: default + igmp_interface_profile: + tenant: common + igmp: default + state: present check_mode: true - register: cm_add_intf + register: cm_add_interface_profile - - name: Add interface profile (normal_mode) + - name: Add a Logical Interface Profile (normal_mode) cisco.aci.aci_l3out_logical_interface_profile: - <<: *intf_present - register: nm_add_intf + <<: *aci_l3out_logical_interface_profile_present + register: nm_add_interface_profile - - name: Verify nm_add_intf - assert: - that: - - cm_add_intf is changed - - nm_add_intf is changed - - cm_add_intf.previous == nm_add_intf.previous == [] - - cm_add_intf.sent.l3extLIfP.attributes.name == nm_add_intf.sent.l3extLIfP.attributes.name == 'INTFS' - - cm_add_intf.sent.l3extLIfP.attributes.descr == nm_add_intf.sent.l3extLIfP.attributes.descr == 'test' - - nm_add_intf.current.0.l3extLIfP.attributes.annotation == 'orchestrator:ansible' - - - name: Add profile again, check if idempotency works + - name: Add the first Logical Interface Profile again - testing idempotency cisco.aci.aci_l3out_logical_interface_profile: - <<: *intf_present - register: add_intf_again + <<: *aci_l3out_logical_interface_profile_present + register: nm_add_interface_profile_idempotency - - name: Verify add_intf_again - assert: - that: - - add_intf_again is not changed - - # UPDATE INTERFACE PROFILE - - name: Update profile - cisco.aci.aci_l3out_logical_interface_profile: &intf_update - <<: *intf_present - nd_policy: NDTEST - description: new test - register: update_intf - - - name: Verify update_intf - assert: + - name: Add a second Logical Interface Profile (normal_mode) + cisco.aci.aci_l3out_logical_interface_profile: &aci_l3out_logical_interface_profile_2_present + <<: *aci_np_present + interface_profile: ansible_interface_profile_2 + description: Logical Interface Profile 2 for ansible_node_profile + state: present + register: nm_add_interface_profile_2 + + - name: Asserts for Logical Interface Profile creation tasks + ansible.builtin.assert: that: - - update_intf.sent.l3extLIfP.attributes.descr == 'new test' - - update_intf is changed - - update_intf.previous != [] + - cm_add_interface_profile is changed + - cm_add_interface_profile.previous == [] + - cm_add_interface_profile.current == [] + - cm_add_interface_profile.proposed.l3extLIfP.attributes.name == "ansible_interface_profile_1" + - cm_add_interface_profile.proposed.l3extLIfP.attributes.prio == "level1" + - nm_add_interface_profile.proposed.l3extLIfP.children.0.l3extRsNdIfPol.attributes.tnNdIfPolName == "default" + - nm_add_interface_profile.proposed.l3extLIfP.children.1.l3extRsIngressQosDppPol.attributes.tnQosDppPolName == "default" + - nm_add_interface_profile.proposed.l3extLIfP.children.2.l3extRsEgressQosDppPol.attributes.tnQosDppPolName == "default" + - nm_add_interface_profile.proposed.l3extLIfP.children.3.l3extRsLIfPCustQosPol.attributes.tnQosCustomPolName == "default" + - nm_add_interface_profile.proposed.l3extLIfP.children.4.pimIPV6IfP.children.0.pimRsV6IfPol.attributes.tDn == "uni/tn-common/pimifpol-default" + - nm_add_interface_profile.proposed.l3extLIfP.children.5.pimIfP.children.0.pimRsIfPol.attributes.tDn == "uni/tn-common/pimifpol-default" + - nm_add_interface_profile.proposed.l3extLIfP.children.6.igmpIfP.children.0.igmpRsIfPol.attributes.tDn == "uni/tn-common/igmpIfPol-default" + - nm_add_interface_profile is changed + - nm_add_interface_profile.previous == [] + - nm_add_interface_profile.current.0.l3extLIfP.attributes.name == "ansible_interface_profile_1" + - nm_add_interface_profile.current.0.l3extLIfP.attributes.prio == "level1" + - nm_add_interface_profile.current.0.l3extLIfP.children.0.l3extRsLIfPCustQosPol.attributes.tnQosCustomPolName == "default" + - nm_add_interface_profile.current.0.l3extLIfP.children.1.igmpIfP.children.0.igmpRsIfPol.attributes.tDn == "uni/tn-common/igmpIfPol-default" + - nm_add_interface_profile.current.0.l3extLIfP.children.2.pimIfP.children.0.pimRsIfPol.attributes.tDn == "uni/tn-common/pimifpol-default" + - nm_add_interface_profile.current.0.l3extLIfP.children.3.pimIPV6IfP.children.0.pimRsV6IfPol.attributes.tDn == "uni/tn-common/pimifpol-default" + - nm_add_interface_profile.current.0.l3extLIfP.children.4.l3extRsEgressQosDppPol.attributes.tnQosDppPolName == "default" + - nm_add_interface_profile.current.0.l3extLIfP.children.5.l3extRsIngressQosDppPol.attributes.tnQosDppPolName == "default" + - nm_add_interface_profile.current.0.l3extLIfP.children.6.l3extRsNdIfPol.attributes.tnNdIfPolName == "default" + - nm_add_interface_profile_idempotency is not changed + - nm_add_interface_profile_idempotency.current.0.l3extLIfP.attributes.name == "ansible_interface_profile_1" + - nm_add_interface_profile_idempotency.current.0.l3extLIfP.attributes.prio == "level1" + - nm_add_interface_profile_idempotency.current.0.l3extLIfP.children.0.l3extRsLIfPCustQosPol.attributes.tnQosCustomPolName == "default" + - nm_add_interface_profile_idempotency.current.0.l3extLIfP.children.1.igmpIfP.children.0.igmpRsIfPol.attributes.tDn == "uni/tn-common/igmpIfPol-default" + - nm_add_interface_profile_idempotency.current.0.l3extLIfP.children.2.pimIfP.children.0.pimRsIfPol.attributes.tDn == "uni/tn-common/pimifpol-default" + - nm_add_interface_profile_idempotency.current.0.l3extLIfP.children.3.pimIPV6IfP.children.0.pimRsV6IfPol.attributes.tDn == "uni/tn-common/pimifpol-default" + - nm_add_interface_profile_idempotency.current.0.l3extLIfP.children.4.l3extRsEgressQosDppPol.attributes.tnQosDppPolName == "default" + - nm_add_interface_profile_idempotency.current.0.l3extLIfP.children.5.l3extRsIngressQosDppPol.attributes.tnQosDppPolName == "default" + - nm_add_interface_profile_idempotency.current.0.l3extLIfP.children.6.l3extRsNdIfPol.attributes.tnNdIfPolName == "default" + - nm_add_interface_profile_2 is changed + - nm_add_interface_profile_2.previous == [] + - nm_add_interface_profile_2.current.0.l3extLIfP.attributes.name == "ansible_interface_profile_2" + - nm_add_interface_profile_2.current.0.l3extLIfP.attributes.prio == "unspecified" - # ADD ANOTHER PROFILE - - name: Add another profile + # QUERY Logical Interface Profile + - name: Query all Logical Interface Profiles cisco.aci.aci_l3out_logical_interface_profile: - <<: *intf_present - interface_profile: INTF2 + <<: *aci_info + state: query + register: query_all_interface_profile - # QUERY ALL PROFILES - - name: Query all profiles + - name: Query ansible_interface_profile_1 cisco.aci.aci_l3out_logical_interface_profile: - <<: *aci_info + <<: *aci_l3out_logical_interface_profile_present state: query - register: query_all_profiles + register: query_ansible_interface_profile_1 - - name: Verify query_all_profiles - assert: + - name: Asserts query tasks + ansible.builtin.assert: that: - - query_all_profiles is not changed - - query_all_profiles.current|length >= 1 + - query_all_interface_profile is not changed + - query_all_interface_profile.current|length >= 2 + - query_ansible_interface_profile_1 is not changed + - query_ansible_interface_profile_1.current|length == 1 + - query_ansible_interface_profile_1.current.0.l3extLIfP.attributes.name == "ansible_interface_profile_1" + - query_ansible_interface_profile_1.current.0.l3extLIfP.attributes.prio == "level1" + - query_ansible_interface_profile_1.current.0.l3extLIfP.children.0.l3extRsLIfPCustQosPol.attributes.tDn == "uni/tn-common/qoscustom-default" + - query_ansible_interface_profile_1.current.0.l3extLIfP.children.1.igmpIfP.children.0.igmpRsIfPol.attributes.tDn == "uni/tn-common/igmpIfPol-default" + - query_ansible_interface_profile_1.current.0.l3extLIfP.children.2.pimIfP.children.0.pimRsIfPol.attributes.tDn == "uni/tn-common/pimifpol-default" + - query_ansible_interface_profile_1.current.0.l3extLIfP.children.3.pimIPV6IfP.children.0.pimRsV6IfPol.attributes.tDn == "uni/tn-common/pimifpol-default" + - query_ansible_interface_profile_1.current.0.l3extLIfP.children.4.l3extRsEgressQosDppPol.attributes.tDn == "uni/tn-common/qosdpppol-default" + - query_ansible_interface_profile_1.current.0.l3extLIfP.children.5.l3extRsIngressQosDppPol.attributes.tDn == "uni/tn-common/qosdpppol-default" + - query_ansible_interface_profile_1.current.0.l3extLIfP.children.6.l3extRsNdIfPol.attributes.tDn == "uni/tn-common/ndifpol-default" + + #REMOVE ASSOCIATED EPG/EXTERNAL EPG FROM NETFLOW EXPORTER POLICIES + - name: Remove all child classes from first Logical Interface Profile (check_mode) + cisco.aci.aci_l3out_logical_interface_profile: &aci_l3out_logical_interface_profile_remove_child_classes + <<: *aci_l3out_logical_interface_profile_present + nd_policy: "" + egress_dpp_policy: "" + ingress_dpp_policy: "" + qos_custom_policy: "" + pim_v4_interface_profile: {} + pim_v6_interface_profile: {} + igmp_interface_profile: {} + check_mode: true + register: cm_remove_child_classes_interface_profile - # QUERY A SPECIFIC PROFILE - - name: Query a specific profile + - name: Remove all child classes from first Logical Interface Profile (normal_mode) cisco.aci.aci_l3out_logical_interface_profile: - <<: *intf_update - state: query - register: query_spec_profile + <<: *aci_l3out_logical_interface_profile_remove_child_classes + register: nm_remove_child_classes_interface_profile + + - name: Remove all child classes from first Logical Interface Profile again - testing idempotency + cisco.aci.aci_l3out_logical_interface_profile: + <<: *aci_l3out_logical_interface_profile_remove_child_classes + register: nm_remove_child_classes_interface_profile_idempotency - - name: Verify query_spec_profile - assert: + - name: Asserts for child classes removal tasks + ansible.builtin.assert: that: - - query_spec_profile is not changed - - query_spec_profile.current|length == 1 + - cm_remove_child_classes_interface_profile is changed + - cm_remove_child_classes_interface_profile.current == cm_remove_child_classes_interface_profile.previous + - cm_remove_child_classes_interface_profile.proposed.l3extLIfP.children.0.l3extRsNdIfPol.attributes.tnNdIfPolName == "" + - cm_remove_child_classes_interface_profile.proposed.l3extLIfP.children.1.l3extRsIngressQosDppPol.attributes.tnQosDppPolName == "" + - cm_remove_child_classes_interface_profile.proposed.l3extLIfP.children.2.l3extRsEgressQosDppPol.attributes.tnQosDppPolName == "" + - cm_remove_child_classes_interface_profile.proposed.l3extLIfP.children.3.l3extRsLIfPCustQosPol.attributes.tnQosCustomPolName == "" + - cm_remove_child_classes_interface_profile.proposed.l3extLIfP.children.4.pimIPV6IfP.attributes.status == "deleted" + - cm_remove_child_classes_interface_profile.proposed.l3extLIfP.children.5.pimIfP.attributes.status == "deleted" + - cm_remove_child_classes_interface_profile.proposed.l3extLIfP.children.6.igmpIfP.attributes.status == "deleted" + - nm_remove_child_classes_interface_profile is changed + - nm_remove_child_classes_interface_profile.current.0.l3extLIfP.children.0.l3extRsLIfPCustQosPol.attributes.tnQosCustomPolName == "" + - nm_remove_child_classes_interface_profile.current.0.l3extLIfP.children.1.l3extRsEgressQosDppPol.attributes.tnQosDppPolName == "" + - nm_remove_child_classes_interface_profile.current.0.l3extLIfP.children.2.l3extRsIngressQosDppPol.attributes.tnQosDppPolName == "" + - nm_remove_child_classes_interface_profile.current.0.l3extLIfP.children.3.l3extRsNdIfPol.attributes.tnNdIfPolName == "" + - nm_remove_child_classes_interface_profile.proposed.l3extLIfP.children.4.pimIPV6IfP.attributes.status == "deleted" + - nm_remove_child_classes_interface_profile.proposed.l3extLIfP.children.5.pimIfP.attributes.status == "deleted" + - nm_remove_child_classes_interface_profile.proposed.l3extLIfP.children.6.igmpIfP.attributes.status == "deleted" + - nm_remove_child_classes_interface_profile.current.0.l3extLIfP.children|length == 4 + - nm_remove_child_classes_interface_profile_idempotency is not changed + - nm_remove_child_classes_interface_profile_idempotency.current.0.l3extLIfP.children.0.l3extRsLIfPCustQosPol.attributes.tnQosCustomPolName == "" + - nm_remove_child_classes_interface_profile_idempotency.current.0.l3extLIfP.children.1.l3extRsEgressQosDppPol.attributes.tnQosDppPolName == "" + - nm_remove_child_classes_interface_profile_idempotency.current.0.l3extLIfP.children.2.l3extRsIngressQosDppPol.attributes.tnQosDppPolName == "" + - nm_remove_child_classes_interface_profile_idempotency.current.0.l3extLIfP.children.3.l3extRsNdIfPol.attributes.tnNdIfPolName == "" + - nm_remove_child_classes_interface_profile_idempotency.current.0.l3extLIfP.children|length == 4 + + #UPDATE Logical Interface Profile + - name: Update first Logical Interface Profile (check_mode) + cisco.aci.aci_l3out_logical_interface_profile: &aci_l3out_logical_interface_profile_update + <<: *aci_l3out_logical_interface_profile_remove_child_classes + prio: level2 + description: Updated description for first ansible Logical Interface Profile + check_mode: true + register: cm_update_interface_profile - # QUERY A NON EXISTING PROFILE - - name: Query a nonexisting profile + - name: Update first Logical Interface Profile (normal_mode) cisco.aci.aci_l3out_logical_interface_profile: - <<: *np_present - interface_profile: nonexist - state: query - register: query_nonexist_profile + <<: *aci_l3out_logical_interface_profile_update + register: nm_update_interface_profile + + - name: Update first Logical Interface Profile again - testing idempotency + cisco.aci.aci_l3out_logical_interface_profile: + <<: *aci_l3out_logical_interface_profile_update + register: nm_udpate_interface_profile_idempotency - - name: Verify query_nonexist_profile - assert: + - name: Asserts for Logical Interface Profile update tasks + ansible.builtin.assert: that: - - query_nonexist_profile is not changed - - query_nonexist_profile.current == [] + - cm_update_interface_profile is changed + - cm_update_interface_profile.previous == cm_update_interface_profile.current + - cm_update_interface_profile.proposed.l3extLIfP.attributes.prio == "level2" + - cm_update_interface_profile.proposed.l3extLIfP.attributes.descr == "Updated description for first ansible Logical Interface Profile" + - nm_update_interface_profile is changed + - nm_update_interface_profile.current.0.l3extLIfP.attributes.prio == "level2" + - nm_update_interface_profile.current.0.l3extLIfP.attributes.descr == "Updated description for first ansible Logical Interface Profile" + - nm_udpate_interface_profile_idempotency is not changed + - nm_udpate_interface_profile_idempotency.current.0.l3extLIfP.attributes.prio == "level2" + - nm_udpate_interface_profile_idempotency.current.0.l3extLIfP.attributes.descr == "Updated description for first ansible Logical Interface Profile" - # REMOVE PROFILE - - name: Remove interface profile - cisco.aci.aci_l3out_logical_interface_profile: &intf_absent - <<: *intf_update + # DELETE Logical Interface Profile + - name: Remove Logical Interface Profile (check_mode) + cisco.aci.aci_l3out_logical_interface_profile: &interface_profile_absent + <<: *aci_l3out_logical_interface_profile_update state: absent - register: remove_profile + check_mode: true + register: cm_remove_interface_profile - - name: Verify remove_profile - assert: - that: - - remove_profile is changed - - remove_profile.current == [] + - name: Remove Logical Interface Profile (normal_mode) + cisco.aci.aci_l3out_logical_interface_profile: + <<: *interface_profile_absent + register: nm_remove_interface_profile - # REMOVE NONEXISTING PROFILE - - name: Remove interface profile again (nonexisting) + - name: Remove Logical Interface Profile - testing idempotency cisco.aci.aci_l3out_logical_interface_profile: - <<: *intf_absent - register: remove_nonexist_profile + <<: *interface_profile_absent + register: nm_remove_interface_profile_idempotency - - name: Verify remove_nonexist_profile - assert: + - name: Asserts deletion tasks + ansible.builtin.assert: that: - - remove_nonexist_profile is not changed - - remove_nonexist_profile.current == [] + - cm_remove_interface_profile is changed + - cm_remove_interface_profile.current == cm_remove_interface_profile.previous + - cm_remove_interface_profile.proposed == {} + - nm_remove_interface_profile is changed + - nm_remove_interface_profile.previous != [] + - nm_remove_interface_profile.proposed == {} + - nm_remove_interface_profile.current == [] + - nm_remove_interface_profile_idempotency is not changed + - nm_remove_interface_profile_idempotency.previous == [] + - nm_remove_interface_profile_idempotency.current == [] + + # CLEAN ENVIRONMENT BEFORE ENDING TESTS + - name: Remove the ansible_tenant - cleanup before ending tests + cisco.aci.aci_tenant: + <<: *aci_tenant_present + state: absent + + - name: Remove the ansible_dom - cleanup before ending tests + cisco.aci.aci_domain: + <<: *aci_domain_present + state: absent diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_l3out_logical_interface_profile_ospf_policy/tasks/main.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_l3out_logical_interface_profile_ospf_policy/tasks/main.yml index d10a88a7f..e98864604 100644 --- a/ansible_collections/cisco/aci/tests/integration/targets/aci_l3out_logical_interface_profile_ospf_policy/tasks/main.yml +++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_l3out_logical_interface_profile_ospf_policy/tasks/main.yml @@ -3,7 +3,7 @@ # SET VARS - name: Set vars - set_fact: + ansible.builtin.set_fact: aci_info: &aci_info host: '{{ aci_hostname }}' username: '{{ aci_username }}' @@ -21,7 +21,7 @@ state: absent - name: Verify Cloud and Non-Cloud Sites in use. - include_tasks: ../../../../../../integration/targets/aci_cloud_provider/tasks/main.yml + ansible.builtin.include_tasks: ../../../../../../integration/targets/aci_cloud_provider/tasks/main.yml - name: Execute tasks only for non-cloud sites when: query_cloud.current == [] # This condition will execute only non-cloud sites @@ -75,7 +75,7 @@ register: nm_add_ospfIfP - name: Verify add_ospfIfP - assert: + ansible.builtin.assert: that: - cm_add_ospfIfP is changed - nm_add_ospfIfP is changed @@ -88,7 +88,7 @@ register: nm_add_ospfIfP_again - name: Verify add_ospfIfP_again - assert: + ansible.builtin.assert: that: - nm_add_ospfIfP_again is not changed @@ -101,7 +101,7 @@ register: update_ospfIfP - name: Verify update_ospfIfP - assert: + ansible.builtin.assert: that: - update_ospfIfP is changed - update_ospfIfP.previous != [] @@ -116,7 +116,7 @@ register: query_ospfIfP_profile - name: Verify query_ospfIfP_profile - assert: + ansible.builtin.assert: that: - query_ospfIfP_profile is not changed - query_ospfIfP_profile.current|length == 1 @@ -137,7 +137,7 @@ register: remove_profile_again - name: Verify remove_profile and remove_profile_again - assert: + ansible.builtin.assert: that: - remove_profile.previous|length == 1 - remove_profile.previous[0].ospfIfP.children[0].ospfRsIfPol.attributes.tnOspfIfPolName == 'default' @@ -154,7 +154,7 @@ register: query_nonexist_policy - name: Verify query_nonexist_policy - assert: + ansible.builtin.assert: that: - query_nonexist_policy is not changed - query_nonexist_policy.current == [] @@ -166,7 +166,7 @@ register: remove_nonexist_policy - name: Verify remove_nonexist_policy - assert: + ansible.builtin.assert: that: - remove_nonexist_policy is not changed - remove_nonexist_policy.current == [] diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_l3out_logical_interface_vpc_member/tasks/main.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_l3out_logical_interface_vpc_member/tasks/main.yml index 749d2137f..755e93bea 100644 --- a/ansible_collections/cisco/aci/tests/integration/targets/aci_l3out_logical_interface_vpc_member/tasks/main.yml +++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_l3out_logical_interface_vpc_member/tasks/main.yml @@ -4,12 +4,12 @@ # GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) - name: Test that we have an ACI APIC host, ACI username and ACI password - fail: + ansible.builtin.fail: msg: 'Please define the following variables: aci_hostname, aci_username and aci_password.' when: aci_hostname is not defined or aci_username is not defined or aci_password is not defined - name: Set vars - set_fact: + ansible.builtin.set_fact: aci_info: &aci_info host: "{{ aci_hostname }}" username: "{{ aci_username }}" @@ -21,26 +21,26 @@ # CLEAN ENVIRONMENT - name: Remove the ansible_tenant - aci_tenant: + cisco.aci.aci_tenant: <<: *aci_info tenant: ansible_tenant state: absent - name: Verify Cloud and Non-Cloud Sites in use. - include_tasks: ../../../../../../integration/targets/aci_cloud_provider/tasks/main.yml + ansible.builtin.include_tasks: ../../../../../../integration/targets/aci_cloud_provider/tasks/main.yml - name: Execute tasks only for non-cloud sites when: query_cloud.current == [] # This condition will execute only non-cloud sites block: # block specifies execution of tasks within, based on conditions - name: Add a new tenant - aci_tenant: + cisco.aci.aci_tenant: <<: *aci_info tenant: ansible_tenant description: Ansible tenant state: present - name: Add a new L3Out - aci_l3out: + cisco.aci.aci_l3out: <<: *aci_info tenant: ansible_tenant name: ansible_l3out @@ -69,7 +69,7 @@ state: present - name: Add two vPC-interfaces - aci_l3out_interface: + cisco.aci.aci_l3out_interface: <<: *aci_info tenant: ansible_tenant l3out: ansible_l3out @@ -85,7 +85,7 @@ - policy_group_two - name: Add a VPC member based on path_dn - aci_l3out_logical_interface_vpc_member: + cisco.aci.aci_l3out_logical_interface_vpc_member: <<: *aci_info tenant: ansible_tenant l3out: ansible_l3out @@ -97,13 +97,13 @@ register: l3out_logical_interface_vpc_member_present - name: Assertions check for add a VPC member based on path_dn - assert: + ansible.builtin.assert: that: - l3out_logical_interface_vpc_member_present is changed - l3out_logical_interface_vpc_member_present.current.0.l3extMember.attributes.annotation == 'orchestrator:ansible' - name: Add a VPC member based on pod_id, node_id, path_ep - aci_l3out_logical_interface_vpc_member: + cisco.aci.aci_l3out_logical_interface_vpc_member: <<: *aci_info tenant: ansible_tenant l3out: ansible_l3out @@ -118,7 +118,7 @@ state: present - name: Query a specific VPC member under ansible_l3out - aci_l3out_logical_interface_vpc_member: + cisco.aci.aci_l3out_logical_interface_vpc_member: <<: *aci_info tenant: ansible_tenant l3out: ansible_l3out @@ -130,7 +130,7 @@ register: query_result - name: Query all relationships - aci_l3out_logical_interface_vpc_member: + cisco.aci.aci_l3out_logical_interface_vpc_member: <<: *aci_info tenant: ansible_tenant state: query @@ -138,7 +138,7 @@ register: query_result - name: Remove a VPC member - aci_l3out_logical_interface_vpc_member: + cisco.aci.aci_l3out_logical_interface_vpc_member: <<: *aci_info tenant: ansible_tenant l3out: ansible_l3out diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_l3out_logical_node/tasks/main.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_l3out_logical_node/tasks/main.yml index 1d61ee3e3..52ae8d7d9 100644 --- a/ansible_collections/cisco/aci/tests/integration/targets/aci_l3out_logical_node/tasks/main.yml +++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_l3out_logical_node/tasks/main.yml @@ -1,14 +1,16 @@ -# Author: Marcel Zehnder (@maercu) +# Test code for the ACI modules +# Copyright: (c) 2021, Marcel Zehnder (@maercu) +# Copyright: (c) 2023, Akini Ross (@akinross) # GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) - name: Test that we have an ACI APIC host, ACI username and ACI password - fail: + ansible.builtin.fail: msg: 'Please define the following variables: aci_hostname, aci_username and aci_password.' when: aci_hostname is not defined or aci_username is not defined or aci_password is not defined # SET VARS - name: Set vars - set_fact: + ansible.builtin.set_fact: aci_info: &aci_info host: '{{ aci_hostname }}' username: '{{ aci_username }}' @@ -18,6 +20,13 @@ use_proxy: '{{ aci_use_proxy | default(true) }}' output_level: '{{ aci_output_level | default("info") }}' +- name: Query system information + cisco.aci.aci_system: + <<: *aci_info + id: 1 + state: query + register: version + # CLEAN ENVIRONMENT - name: Remove test tenant before we kickoff cisco.aci.aci_tenant: &tenant_absent @@ -26,7 +35,7 @@ state: absent - name: Verify Cloud and Non-Cloud Sites in use. - include_tasks: ../../../../../../integration/targets/aci_cloud_provider/tasks/main.yml + ansible.builtin.include_tasks: ../../../../../../integration/targets/aci_cloud_provider/tasks/main.yml - name: Execute tasks only for non-cloud sites when: query_cloud.current == [] # This condition will execute only non-cloud sites @@ -79,7 +88,7 @@ register: nm_add_node - name: Verify nm_add_node - assert: + ansible.builtin.assert: that: - cm_add_node is changed - nm_add_node is changed @@ -95,7 +104,7 @@ register: add_node_again - name: Verify add_node_again - assert: + ansible.builtin.assert: that: - add_node_again is not changed @@ -119,7 +128,7 @@ register: remove_loopback_ip - name: Verify update_node - assert: + ansible.builtin.assert: that: - update_node is changed - update_node.previous != [] @@ -138,6 +147,138 @@ router_id: 12.12.12.12 loopback_address: 12.12.12.13 + - name: Execute tasks only for APIC version 5.x and above + when: + - version.current.0.topSystem.attributes.version is version('5', '>=') # This condition will execute only for APIC version 5.x and above + block: + + - name: Ensure infra SR-MPLS l3out does not exist + cisco.aci.aci_l3out: &aci_infra_sr_mpls_l3out_absent + <<: *aci_info + tenant: infra + name: ansible_infra_sr_mpls_l3out + domain: ansible_dom + vrf: overlay-1 + mpls: "yes" + l3protocol: bgp + state: absent + + - name: Add a infra SR-MPLS l3out + cisco.aci.aci_l3out: + <<: *aci_infra_sr_mpls_l3out_absent + state: present + + - name: Add a node profile in the infra SR-MPLS l3out + cisco.aci.aci_l3out_logical_node_profile: &aci_infra_node_profile + <<: *aci_info + tenant: infra + l3out: ansible_infra_sr_mpls_l3out + node_profile: ansible_infra_sr_mpls_l3out_node_profile + + - name: Add a node in the infra SR-MPLS l3out node profile (check_mode) + cisco.aci.aci_l3out_logical_node: &aci_infra_node_profile_node + <<: *aci_infra_node_profile + tenant: infra + l3out: ansible_infra_sr_mpls_l3out + node_profile: ansible_infra_sr_mpls_l3out_node_profile + pod_id: 1 + node_id: 113 + router_id_as_loopback: no + loopback_address: 50.0.0.1 + mpls_transport_loopback_address: 51.0.0.1 + sid: 500 + check_mode: true + register: cm_add_infra_node_profile_node + + - name: Add a node in the infra SR-MPLS l3out node profile without loopback (error) + cisco.aci.aci_l3out_logical_node: + <<: *aci_infra_node_profile_node + loopback_address: "{{ fake_var | default(omit) }}" + ignore_errors: true + register: err_add_infra_node_profile_node_without_loopback + + - name: Add a node in the infra SR-MPLS l3out node profile without sid (error) + cisco.aci.aci_l3out_logical_node: + <<: *aci_infra_node_profile_node + sid: "{{ fake_var | default(omit) }}" + ignore_errors: true + register: err_add_infra_node_profile_node_without_sid + + - name: Add a node in the infra SR-MPLS l3out node profile without mpls transport loopback addressid (error) + cisco.aci.aci_l3out_logical_node: + <<: *aci_infra_node_profile_node + mpls_transport_loopback_address: "{{ fake_var | default(omit) }}" + ignore_errors: true + register: err_add_infra_node_profile_node_without_mpls_transport_loopback_address + + - name: Add a node in the infra SR-MPLS l3out node profile (normal mode) + cisco.aci.aci_l3out_logical_node: + <<: *aci_infra_node_profile_node + register: nm_add_infra_node_profile_node + + - name: Add a node in the infra SR-MPLS l3out node profile again + cisco.aci.aci_l3out_logical_node: + <<: *aci_infra_node_profile_node + register: nm_add_infra_node_profile_node_again + + - name: Change the node in the infra SR-MPLS l3out node profile + cisco.aci.aci_l3out_logical_node: + <<: *aci_infra_node_profile_node + loopback_address: 50.0.0.2 + mpls_transport_loopback_address: 51.0.0.2 + sid: 501 + register: nm_change_infra_node_profile_node + + - name: Verify mpls custom qos policy configuration on node profile + assert: + that: + - cm_add_infra_node_profile_node is changed + - cm_add_infra_node_profile_node.previous == [] + - cm_add_infra_node_profile_node.proposed.l3extRsNodeL3OutAtt.attributes.rtrIdLoopBack == "no" + - cm_add_infra_node_profile_node.proposed.l3extRsNodeL3OutAtt.attributes.tDn == "topology/pod-1/node-113" + - cm_add_infra_node_profile_node.proposed.l3extRsNodeL3OutAtt.children.0.l3extLoopBackIfP.attributes.addr == "50.0.0.1" + - cm_add_infra_node_profile_node.proposed.l3extRsNodeL3OutAtt.children.0.l3extLoopBackIfP.children.0.mplsNodeSidP.attributes.loopbackAddr == "51.0.0.1" + - cm_add_infra_node_profile_node.proposed.l3extRsNodeL3OutAtt.children.0.l3extLoopBackIfP.children.0.mplsNodeSidP.attributes.sidoffset == "500" + - err_add_infra_node_profile_node_without_loopback is failed + - err_add_infra_node_profile_node_without_loopback.msg == "missing parameter(s) required by 'mpls_transport_loopback_address'{{":"}} loopback_address" + - err_add_infra_node_profile_node_without_sid is failed + - err_add_infra_node_profile_node_without_sid.msg == "parameters are required together{{":"}} mpls_transport_loopback_address, sid" + - err_add_infra_node_profile_node_without_mpls_transport_loopback_address is failed + - err_add_infra_node_profile_node_without_mpls_transport_loopback_address.msg == "parameters are required together{{":"}} mpls_transport_loopback_address, sid" + - nm_add_infra_node_profile_node is changed + - nm_add_infra_node_profile_node.previous == [] + - nm_add_infra_node_profile_node.current.0.l3extRsNodeL3OutAtt.attributes.rtrIdLoopBack == "no" + - nm_add_infra_node_profile_node.current.0.l3extRsNodeL3OutAtt.attributes.tDn == "topology/pod-1/node-113" + - nm_add_infra_node_profile_node.current.0.l3extRsNodeL3OutAtt.children.0.l3extLoopBackIfP.attributes.addr == "50.0.0.1" + - nm_add_infra_node_profile_node.current.0.l3extRsNodeL3OutAtt.children.0.l3extLoopBackIfP.children.0.mplsNodeSidP.attributes.loopbackAddr == "51.0.0.1" + - nm_add_infra_node_profile_node.current.0.l3extRsNodeL3OutAtt.children.0.l3extLoopBackIfP.children.0.mplsNodeSidP.attributes.sidoffset == "500" + - nm_add_infra_node_profile_node_again is not changed + - nm_add_infra_node_profile_node_again.previous.0.l3extRsNodeL3OutAtt.attributes.rtrIdLoopBack == "no" + - nm_add_infra_node_profile_node_again.previous.0.l3extRsNodeL3OutAtt.attributes.tDn == "topology/pod-1/node-113" + - nm_add_infra_node_profile_node_again.previous.0.l3extRsNodeL3OutAtt.children.0.l3extLoopBackIfP.attributes.addr == "50.0.0.1" + - nm_add_infra_node_profile_node_again.previous.0.l3extRsNodeL3OutAtt.children.0.l3extLoopBackIfP.children.0.mplsNodeSidP.attributes.loopbackAddr == "51.0.0.1" + - nm_add_infra_node_profile_node_again.previous.0.l3extRsNodeL3OutAtt.children.0.l3extLoopBackIfP.children.0.mplsNodeSidP.attributes.sidoffset == "500" + - nm_add_infra_node_profile_node_again.current.0.l3extRsNodeL3OutAtt.attributes.rtrIdLoopBack == "no" + - nm_add_infra_node_profile_node_again.current.0.l3extRsNodeL3OutAtt.attributes.tDn == "topology/pod-1/node-113" + - nm_add_infra_node_profile_node_again.current.0.l3extRsNodeL3OutAtt.children.0.l3extLoopBackIfP.attributes.addr == "50.0.0.1" + - nm_add_infra_node_profile_node_again.current.0.l3extRsNodeL3OutAtt.children.0.l3extLoopBackIfP.children.0.mplsNodeSidP.attributes.loopbackAddr == "51.0.0.1" + - nm_add_infra_node_profile_node_again.current.0.l3extRsNodeL3OutAtt.children.0.l3extLoopBackIfP.children.0.mplsNodeSidP.attributes.sidoffset == "500" + - nm_change_infra_node_profile_node is changed + - nm_change_infra_node_profile_node.previous.0.l3extRsNodeL3OutAtt.attributes.rtrIdLoopBack == "no" + - nm_change_infra_node_profile_node.previous.0.l3extRsNodeL3OutAtt.attributes.tDn == "topology/pod-1/node-113" + - nm_change_infra_node_profile_node.previous.0.l3extRsNodeL3OutAtt.children.0.l3extLoopBackIfP.attributes.addr == "50.0.0.1" + - nm_change_infra_node_profile_node.previous.0.l3extRsNodeL3OutAtt.children.0.l3extLoopBackIfP.children.0.mplsNodeSidP.attributes.loopbackAddr == "51.0.0.1" + - nm_change_infra_node_profile_node.previous.0.l3extRsNodeL3OutAtt.children.0.l3extLoopBackIfP.children.0.mplsNodeSidP.attributes.sidoffset == "500" + - nm_change_infra_node_profile_node.current.0.l3extRsNodeL3OutAtt.attributes.rtrIdLoopBack == "no" + - nm_change_infra_node_profile_node.current.0.l3extRsNodeL3OutAtt.attributes.tDn == "topology/pod-1/node-113" + - nm_change_infra_node_profile_node.current.0.l3extRsNodeL3OutAtt.children.0.l3extLoopBackIfP.attributes.addr == "50.0.0.2" + - nm_change_infra_node_profile_node.current.0.l3extRsNodeL3OutAtt.children.0.l3extLoopBackIfP.children.0.mplsNodeSidP.attributes.loopbackAddr == "51.0.0.2" + - nm_change_infra_node_profile_node.current.0.l3extRsNodeL3OutAtt.children.0.l3extLoopBackIfP.children.0.mplsNodeSidP.attributes.sidoffset == "501" + + - name: Remove a infra SR-MPLS l3out + cisco.aci.aci_l3out: + <<: *aci_infra_sr_mpls_l3out_absent + # QUERY ALL NODES - name: Query all nodes cisco.aci.aci_l3out_logical_node: @@ -146,7 +287,7 @@ register: query_all_nodes - name: Verify query_all_nodes - assert: + ansible.builtin.assert: that: - query_all_nodes is not changed - query_all_nodes.current|length >= 1 @@ -159,7 +300,7 @@ register: query_spec_node - name: Verify query_spec_node - assert: + ansible.builtin.assert: that: - query_spec_node is not changed - query_spec_node.current|length == 1 @@ -174,7 +315,7 @@ register: remove_node - name: Verify remove_node - assert: + ansible.builtin.assert: that: - remove_node is changed - remove_node.current == [] diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_l3out_logical_node_profile/tasks/main.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_l3out_logical_node_profile/tasks/main.yml index cbd3fa1a9..a744027d9 100644 --- a/ansible_collections/cisco/aci/tests/integration/targets/aci_l3out_logical_node_profile/tasks/main.yml +++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_l3out_logical_node_profile/tasks/main.yml @@ -1,15 +1,16 @@ # Test code for the ACI modules # Copyright: (c) 2021, Jason Juenger (@jasonjuenger) +# Copyright: (c) 2023, Akini Ross (@akinross) # GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) - name: Test that we have an ACI APIC host, ACI username and ACI password - fail: + ansible.builtin.fail: msg: 'Please define the following variables: aci_hostname, aci_username and aci_password.' when: aci_hostname is not defined or aci_username is not defined or aci_password is not defined - name: Set vars - set_fact: + ansible.builtin.set_fact: aci_info: &aci_info host: "{{ aci_hostname }}" username: "{{ aci_username }}" @@ -19,6 +20,13 @@ use_proxy: '{{ aci_use_proxy | default(true) }}' output_level: info +- name: Query system information + cisco.aci.aci_system: + <<: *aci_info + id: 1 + state: query + register: version + # CLEAN ENVIRONMENT - name: Remove the ansible_tenant cisco.aci.aci_tenant: @@ -27,7 +35,7 @@ state: absent - name: Verify Cloud and Non-Cloud Sites in use. - include_tasks: ../../../../../../integration/targets/aci_cloud_provider/tasks/main.yml + ansible.builtin.include_tasks: ../../../../../../integration/targets/aci_cloud_provider/tasks/main.yml - name: Execute tasks only for non-cloud sites when: query_cloud.current == [] # This condition will execute only non-cloud sites @@ -79,7 +87,7 @@ register: nm_add_second_node_profile - name: Verify add_node_profile - assert: + ansible.builtin.assert: that: - cm_add_node_profile is changed - nm_add_node_profile is changed @@ -111,7 +119,7 @@ register: nm_mod_node_profile - name: Verify mod_node_profile - assert: + ansible.builtin.assert: that: - cm_mod_node_profile is changed - nm_mod_node_profile is changed @@ -120,6 +128,73 @@ - nm_mod_node_profile.current.0.l3extLNodeP.attributes.dn == 'uni/tn-ansible_tenant/out-ansible_l3out/lnodep-ansible_node_profile' - nm_mod_node_profile.current.0.l3extLNodeP.attributes.name == 'ansible_node_profile' + - name: Execute tasks only for APIC version 5.x and above + when: + - version.current.0.topSystem.attributes.version is version('5', '>=') # This condition will execute only for APIC version 5.x and above + block: + + - name: Ensure infra SR-MPLS l3out does not exist + cisco.aci.aci_l3out: &aci_infra_sr_mpls_l3out_absent + <<: *aci_info + tenant: infra + name: ansible_infra_sr_mpls_l3out + domain: ansible_dom + vrf: overlay-1 + mpls: "yes" + l3protocol: bgp + state: absent + + - name: Add a infra SR-MPLS l3out + cisco.aci.aci_l3out: + <<: *aci_infra_sr_mpls_l3out_absent + state: present + + - name: Add a node profile with MPLS custom QoS policy + cisco.aci.aci_l3out_logical_node_profile: &aci_infra_node_profile_qos + <<: *aci_info + tenant: infra + l3out: ansible_infra_sr_mpls_l3out + node_profile: ansible_infra_sr_mpls_l3out_node_profile + mpls_custom_qos_policy: ansible_test_mpls_custom_qos_policy + register: nm_add_node_profile_qos + + - name: Modify MPLS custom QoS policy to node profile + cisco.aci.aci_l3out_logical_node_profile: &aci_infra_node_profile_qos_changed + <<: *aci_infra_node_profile_qos + mpls_custom_qos_policy: ansible_test_mpls_custom_qos_policy_changed + register: nm_mod_node_profile_qos_changed + + - name: Modify MPLS custom QoS policy to node profile again + cisco.aci.aci_l3out_logical_node_profile: + <<: *aci_infra_node_profile_qos_changed + register: nm_mod_node_profile_qos_again + + - name: Remove MPLS custom QoS policy from node profile again + cisco.aci.aci_l3out_logical_node_profile: + <<: *aci_infra_node_profile_qos_changed + mpls_custom_qos_policy: "" + register: nm_del_node_profile_qos + + - name: Verify MPLS custom QoS policy configuration on node profile + assert: + that: + - nm_add_node_profile_qos is changed + - nm_add_node_profile_qos.previous == [] + - nm_add_node_profile_qos.current.0.l3extLNodeP.children.0.l3extRsLNodePMplsCustQosPol.attributes.tDn == "uni/tn-infra/qosmplscustom-ansible_test_mpls_custom_qos_policy" + - nm_mod_node_profile_qos_changed is changed + - nm_mod_node_profile_qos_changed.previous.0.l3extLNodeP.children.0.l3extRsLNodePMplsCustQosPol.attributes.tDn == "uni/tn-infra/qosmplscustom-ansible_test_mpls_custom_qos_policy" + - nm_mod_node_profile_qos_changed.current.0.l3extLNodeP.children.0.l3extRsLNodePMplsCustQosPol.attributes.tDn == "uni/tn-infra/qosmplscustom-ansible_test_mpls_custom_qos_policy_changed" + - nm_mod_node_profile_qos_again is not changed + - nm_mod_node_profile_qos_again.previous.0.l3extLNodeP.children.0.l3extRsLNodePMplsCustQosPol.attributes.tDn == "uni/tn-infra/qosmplscustom-ansible_test_mpls_custom_qos_policy_changed" + - nm_mod_node_profile_qos_again.current.0.l3extLNodeP.children.0.l3extRsLNodePMplsCustQosPol.attributes.tDn == "uni/tn-infra/qosmplscustom-ansible_test_mpls_custom_qos_policy_changed" + - nm_del_node_profile_qos is changed + - nm_del_node_profile_qos.previous.0.l3extLNodeP.children.0.l3extRsLNodePMplsCustQosPol.attributes.tDn == "uni/tn-infra/qosmplscustom-ansible_test_mpls_custom_qos_policy_changed" + - nm_del_node_profile_qos.current.0.l3extLNodeP.children is undefined + + - name: Remove a infra SR-MPLS l3out + cisco.aci.aci_l3out: + <<: *aci_infra_sr_mpls_l3out_absent + - name: Query existing node profile (check mode) cisco.aci.aci_l3out_logical_node_profile: &query_existing_node_profile <<: *aci_info @@ -153,7 +228,7 @@ register: nm_query_all_node_profiles - name: Verify query_node_profile - assert: + ansible.builtin.assert: that: - cm_query_node_profile is not changed - nm_query_node_profile is not changed @@ -198,7 +273,7 @@ register: nm_remove_second_node_profile - name: Verify remove_node_profile - assert: + ansible.builtin.assert: that: - cm_remove_node_profile is changed - cm_remove_second_node_profile is changed diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_l3out_route_tag_policy/tasks/main.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_l3out_route_tag_policy/tasks/main.yml index d7ad61c6d..69b19c53f 100644 --- a/ansible_collections/cisco/aci/tests/integration/targets/aci_l3out_route_tag_policy/tasks/main.yml +++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_l3out_route_tag_policy/tasks/main.yml @@ -4,12 +4,12 @@ # GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) - name: Test that we have an ACI APIC host, ACI username and ACI password - fail: + ansible.builtin.fail: msg: 'Please define the following variables: aci_hostname, aci_username and aci_password.' when: aci_hostname is not defined or aci_username is not defined or aci_password is not defined - name: Set vars - set_fact: + ansible.builtin.set_fact: aci_info: &aci_info host: "{{ aci_hostname }}" username: "{{ aci_username }}" @@ -27,7 +27,7 @@ state: absent - name: Verify Cloud and Non-Cloud Sites in use. - include_tasks: ../../../../../../integration/targets/aci_cloud_provider/tasks/main.yml + ansible.builtin.include_tasks: ../../../../../../integration/targets/aci_cloud_provider/tasks/main.yml - name: Execute tasks only for non-cloud sites when: query_cloud.current == [] # This condition will execute only non-cloud sites @@ -66,7 +66,7 @@ register: nm_add_rtp_2 - name: asserts for creation tasks - assert: + ansible.builtin.assert: that: - cm_add_rtp is changed - cm_add_rtp.previous == [] @@ -93,7 +93,7 @@ register: query_first_rtp - name: asserts query tasks - assert: + ansible.builtin.assert: that: - query_all_rtp is not changed - query_all_rtp.current.0.fvTenant.children | length >= 2 @@ -130,7 +130,7 @@ register: nm_delete_rtp_2 - name: asserts for deletion tasks - assert: + ansible.builtin.assert: that: - cm_delete_rtp is changed - cm_delete_rtp.proposed == {} diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_l3out_static_routes/tasks/main.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_l3out_static_routes/tasks/main.yml index 147d180fc..90f8c4cbb 100644 --- a/ansible_collections/cisco/aci/tests/integration/targets/aci_l3out_static_routes/tasks/main.yml +++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_l3out_static_routes/tasks/main.yml @@ -4,12 +4,12 @@ # GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) - name: Test that we have an ACI APIC host, ACI username and ACI password - fail: + ansible.builtin.fail: msg: 'Please define the following variables: aci_hostname, aci_username and aci_password.' when: aci_hostname is not defined or aci_username is not defined or aci_password is not defined - name: Set vars - set_fact: + ansible.builtin.set_fact: aci_info: &aci_info host: "{{ aci_hostname }}" username: "{{ aci_username }}" @@ -21,26 +21,26 @@ # CLEAN ENVIRONMENT - name: Remove the ansible_tenant - aci_tenant: + cisco.aci.aci_tenant: <<: *aci_info tenant: ansible_tenant state: absent - name: Verify Cloud and Non-Cloud Sites in use. - include_tasks: ../../../../../../integration/targets/aci_cloud_provider/tasks/main.yml + ansible.builtin.include_tasks: ../../../../../../integration/targets/aci_cloud_provider/tasks/main.yml - name: Execute tasks only for non-cloud sites when: query_cloud.current == [] # This condition will execute only non-cloud sites block: # block specifies execution of tasks within, based on conditions - name: Add a new tenant - aci_tenant: + cisco.aci.aci_tenant: <<: *aci_info tenant: ansible_tenant description: Ansible tenant state: present - name: Add a new L3Out - aci_l3out: + cisco.aci.aci_l3out: <<: *aci_info tenant: ansible_tenant name: ansible_l3out @@ -71,7 +71,7 @@ register: l3out_logical_node - name: Verify l3out_logical_node - assert: + ansible.builtin.assert: that: - l3out_logical_node is changed - l3out_logical_node.previous == [] @@ -80,7 +80,7 @@ - l3out_logical_node.sent.l3extRsNodeL3OutAtt.attributes.tDn == 'topology/pod-1/node-101' - name: Add static routes (check_mode) - aci_l3out_static_routes: &route_present + cisco.aci.aci_l3out_static_routes: &route_present <<: *aci_info tenant: ansible_tenant l3out: ansible_l3out @@ -93,12 +93,12 @@ register: cm_add_route - name: Add static routes (normal_mode) - aci_l3out_static_routes: + cisco.aci.aci_l3out_static_routes: <<: *route_present register: nm_add_route - name: Verify cm_add_route and nm_add_route - assert: + ansible.builtin.assert: that: - cm_add_route is changed - nm_add_route is changed @@ -109,18 +109,18 @@ - nm_add_route.current[0].ipRouteP.attributes.annotation == 'orchestrator:ansible' - name: Add static routes again (check_mode) - aci_l3out_static_routes: + cisco.aci.aci_l3out_static_routes: <<: *route_present check_mode: true register: cm_add_route_again - name: Add static routes again (normal_mode) - aci_l3out_static_routes: + cisco.aci.aci_l3out_static_routes: <<: *route_present register: nm_add_route_again - name: Verify cm_add_route_again and nm_add_route_again - assert: + ansible.builtin.assert: that: - cm_add_route_again is not changed - nm_add_route_again is not changed @@ -130,14 +130,14 @@ - nm_add_route_again.current[0].ipRouteP.attributes.ip == "10.1.0.1/24" - name: Query system information - aci_system: + cisco.aci.aci_system: <<: *aci_info id: 1 state: query register: version - name: Add static routes with bfd - aci_l3out_static_routes: + cisco.aci.aci_l3out_static_routes: <<: *aci_info tenant: ansible_tenant l3out: ansible_l3out @@ -152,7 +152,7 @@ register: nm_add_route_with_bfd - name: Verify nm_add_route_with_bfd - assert: + ansible.builtin.assert: that: - nm_add_route_with_bfd is changed - nm_add_route_with_bfd.current[0].ipRouteP.attributes.dn == "uni/tn-ansible_tenant/out-ansible_l3out/lnodep-lNode/rsnodeL3OutAtt-[topology/pod-1/node-101]/rt-[10.1.0.1/24]" @@ -162,7 +162,7 @@ when: version.current.0.topSystem.attributes.version is version('4.2', '>=') - name: Query for a specific MO under l3out - aci_l3out_static_routes: + cisco.aci.aci_l3out_static_routes: <<: *aci_info tenant: ansible_tenant l3out: ansible_l3out @@ -174,14 +174,14 @@ register: query_specific_mo - name: Verify query_specific_mo - assert: + ansible.builtin.assert: that: - query_specific_mo is not changed - query_specific_mo.current|length == 1 - query_specific_mo.current[0].ipRouteP.attributes.ip == "10.1.0.1/24" - name: Query all relationships - aci_l3out_static_routes: + cisco.aci.aci_l3out_static_routes: <<: *aci_info tenant: ansible_tenant state: query @@ -189,7 +189,7 @@ register: query_all_relationships - name: Verify query_all_relationships - assert: + ansible.builtin.assert: that: - query_all_relationships is not changed - query_all_relationships.current|length == 1 @@ -201,13 +201,13 @@ - query_all_relationships.current[0].fvTenant.children[0].l3extOut.children[0].l3extLNodeP.children[0].l3extRsNodeL3OutAtt.attributes.tDn == "topology/pod-1/node-101" - name: Verify query_all_relationships for bfd - assert: + ansible.builtin.assert: that: - query_all_relationships.current[0].fvTenant.children[0].l3extOut.children[0].l3extLNodeP.children[0].l3extRsNodeL3OutAtt.children[0].ipRouteP.attributes.rtCtrl == "bfd" when: version.current.0.topSystem.attributes.version is version('4.2', '>=') - name: Remove static routes (check_mode) - aci_l3out_static_routes: &route_absent + cisco.aci.aci_l3out_static_routes: &route_absent <<: *aci_info tenant: ansible_tenant l3out: ansible_l3out @@ -220,12 +220,12 @@ register: cm_remove_static_routes - name: Remove static routes (normal_mode) - aci_l3out_static_routes: + cisco.aci.aci_l3out_static_routes: <<: *route_absent register: nm_remove_static_routes - name: Verify cm_remove_static_routes and nm_remove_static_routes - assert: + ansible.builtin.assert: that: - cm_remove_static_routes is changed - nm_remove_static_routes is changed @@ -233,18 +233,18 @@ - nm_remove_static_routes.current|length == 0 - name: Remove static routes again (check_mode) - aci_l3out_static_routes: + cisco.aci.aci_l3out_static_routes: <<: *route_absent check_mode: true register: cm_remove_static_routes_again - name: Remove static routes again (normal_mode) - aci_l3out_static_routes: + cisco.aci.aci_l3out_static_routes: <<: *route_absent register: nm_remove_static_routes_again - name: Verify cm_remove_static_routes_again and nm_remove_static_routes_again - assert: + ansible.builtin.assert: that: - cm_remove_static_routes_again is not changed - nm_remove_static_routes_again is not changed @@ -252,7 +252,7 @@ - nm_remove_static_routes_again.current|length == 0 - name: Remove the ansible_tenant - aci_tenant: + cisco.aci.aci_tenant: <<: *aci_info tenant: ansible_tenant state: absent diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_l3out_static_routes_nexthop/tasks/main.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_l3out_static_routes_nexthop/tasks/main.yml index 7d4de1a09..1e7d495fe 100644 --- a/ansible_collections/cisco/aci/tests/integration/targets/aci_l3out_static_routes_nexthop/tasks/main.yml +++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_l3out_static_routes_nexthop/tasks/main.yml @@ -3,7 +3,7 @@ # SET VARS - name: Set vars - set_fact: + ansible.builtin.set_fact: aci_info: &aci_info host: '{{ aci_hostname }}' username: '{{ aci_username }}' @@ -21,7 +21,7 @@ state: absent - name: Verify Cloud and Non-Cloud Sites in use. - include_tasks: ../../../../../../integration/targets/aci_cloud_provider/tasks/main.yml + ansible.builtin.include_tasks: ../../../../../../integration/targets/aci_cloud_provider/tasks/main.yml - name: Execute tasks only for non-cloud sites when: query_cloud.current == [] # This condition will execute only non-cloud sites @@ -85,7 +85,7 @@ register: nm_add_nh - name: Verify nm_add_nh - assert: + ansible.builtin.assert: that: - cm_add_nh is changed - nm_add_nh is changed @@ -99,7 +99,7 @@ register: add_nh_again - name: Verify add_nh_again - assert: + ansible.builtin.assert: that: - add_nh_again is not changed @@ -117,7 +117,7 @@ register: query_all_nhs - name: Verify query_all_nhs - assert: + ansible.builtin.assert: that: - query_all_nhs is not changed - query_all_nhs.current|length >= 1 @@ -130,7 +130,7 @@ register: query_spec_nh - name: Verify query_spec_node - assert: + ansible.builtin.assert: that: - query_spec_nh is not changed - query_spec_nh.current|length == 1 @@ -143,7 +143,7 @@ register: remove_nh - name: Verify remove_nh - assert: + ansible.builtin.assert: that: - remove_nh is changed - remove_nh.current == [] diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_l3out_to_sr_mpls_infra_l3out/aliases b/ansible_collections/cisco/aci/tests/integration/targets/aci_l3out_to_sr_mpls_infra_l3out/aliases new file mode 100644 index 000000000..209b793f9 --- /dev/null +++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_l3out_to_sr_mpls_infra_l3out/aliases @@ -0,0 +1,2 @@ +# No ACI simulator yet, so not enabled +# unsupported diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_l3out_to_sr_mpls_infra_l3out/tasks/main.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_l3out_to_sr_mpls_infra_l3out/tasks/main.yml new file mode 100644 index 000000000..f4e987492 --- /dev/null +++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_l3out_to_sr_mpls_infra_l3out/tasks/main.yml @@ -0,0 +1,238 @@ +# Test code for the ACI modules +# Copyright: (c) 2023, Akini Ross (@akinross) + +# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) + +- name: Test that we have an ACI APIC host, ACI username and ACI password + ansible.builtin.fail: + msg: 'Please define the following variables: aci_hostname, aci_username and aci_password.' + when: aci_hostname is not defined or aci_username is not defined or aci_password is not defined + +- name: Set vars + ansible.builtin.set_fact: + aci_info: &aci_info + host: "{{ aci_hostname }}" + username: "{{ aci_username }}" + password: "{{ aci_password }}" + validate_certs: '{{ aci_validate_certs | default(false) }}' + use_ssl: '{{ aci_use_ssl | default(true) }}' + use_proxy: '{{ aci_use_proxy | default(true) }}' + output_level: debug + +- name: Query system information + cisco.aci.aci_system: + <<: *aci_info + id: 1 + state: query + register: version + +- name: Verify Cloud and Non-Cloud Sites in use. + ansible.builtin.include_tasks: ../../../../../../integration/targets/aci_cloud_provider/tasks/main.yml + +- name: Execute tasks only for non-cloud sites + when: + - query_cloud.current == [] # This condition will execute only non-cloud sites + - version.current.0.topSystem.attributes.version is version('5', '>=') # This condition will execute only for APIC version 5.x and above + block: # block specifies execution of tasks within, based on conditions + + # CLEAN ENVIRONMENT + - name: Remove the ansible_tenant + cisco.aci.aci_tenant: &aci_tenant_absent + <<: *aci_info + tenant: ansible_test + state: absent + + - name: Ensure infra sr mpls l3out does not exist + cisco.aci.aci_l3out: &aci_infra_sr_mpls_l3out_absent + <<: *aci_info + tenant: infra + name: ansible_infra_sr_mpls_l3out + domain: ansible_dom + vrf: overlay-1 + mpls: "yes" + l3protocol: bgp + state: absent + + - name: Add a new ansible_tenant + cisco.aci.aci_tenant: + <<: *aci_tenant_absent + state: present + + - name: Add a infra sr mpls l3out + cisco.aci.aci_l3out: + <<: *aci_infra_sr_mpls_l3out_absent + state: present + + - name: Add a sr mpls l3out + cisco.aci.aci_l3out: + <<: *aci_tenant_absent + name: ansible_sr_mpls_l3out + domain: ansible_dom + vrf: ansible_vrf + mpls: "yes" + state: present + + - name: Add a new l3out to sr-mpls infra l3out (check_mode) + cisco.aci.aci_l3out_to_sr_mpls_infra_l3out: &l3out_to_infra_present + <<: *aci_tenant_absent + l3out: ansible_sr_mpls_l3out + description: ansible_sr_mpls_l3out_description + infra_l3out: ansible_infra_sr_mpls_l3out + external_epg: uni/tn-ansible_test/out-ansible_sr_mpls_l3out/instP-ansible_external_epg + outbound_route_map: uni/tn-ansible_test/prof-outbound_route_map + state: present + check_mode: true + register: cm_add_l3out_to_infra + + - name: Add a new l3out to sr-mpls infra l3out + cisco.aci.aci_l3out_to_sr_mpls_infra_l3out: + <<: *l3out_to_infra_present + register: nm_add_l3out_to_infra + + - name: Add a new l3out to sr-mpls infra l3out again + cisco.aci.aci_l3out_to_sr_mpls_infra_l3out: + <<: *l3out_to_infra_present + register: nm_add_l3out_to_infra_again + + - name: Assert creation of l3out to sr-mpls infra l3outs + ansible.builtin.assert: + that: + - cm_add_l3out_to_infra is changed + - cm_add_l3out_to_infra.previous == [] + - cm_add_l3out_to_infra.proposed.l3extConsLbl.attributes.name == "ansible_infra_sr_mpls_l3out" + - cm_add_l3out_to_infra.proposed.l3extConsLbl.attributes.descr == "ansible_sr_mpls_l3out_description" + - cm_add_l3out_to_infra.proposed.l3extConsLbl.children.0.l3extRsLblToProfile.attributes.direction == "export" + - cm_add_l3out_to_infra.proposed.l3extConsLbl.children.0.l3extRsLblToProfile.attributes.tDn == "uni/tn-ansible_test/prof-outbound_route_map" + - cm_add_l3out_to_infra.proposed.l3extConsLbl.children.1.l3extRsLblToInstP.attributes.tDn == "uni/tn-ansible_test/out-ansible_sr_mpls_l3out/instP-ansible_external_epg" + - nm_add_l3out_to_infra is changed + - nm_add_l3out_to_infra.previous == [] + - nm_add_l3out_to_infra.current.0.l3extConsLbl.attributes.name == "ansible_infra_sr_mpls_l3out" + - nm_add_l3out_to_infra.current.0.l3extConsLbl.attributes.descr == "ansible_sr_mpls_l3out_description" + - nm_add_l3out_to_infra.current.0.l3extConsLbl.children.1.l3extRsLblToProfile.attributes.direction == "export" + - nm_add_l3out_to_infra.current.0.l3extConsLbl.children.1.l3extRsLblToProfile.attributes.tDn == "uni/tn-ansible_test/prof-outbound_route_map" + - nm_add_l3out_to_infra.current.0.l3extConsLbl.children.0.l3extRsLblToInstP.attributes.tDn == "uni/tn-ansible_test/out-ansible_sr_mpls_l3out/instP-ansible_external_epg" + - nm_add_l3out_to_infra_again is not changed + - nm_add_l3out_to_infra_again.previous.0.l3extConsLbl.attributes.name == "ansible_infra_sr_mpls_l3out" + - nm_add_l3out_to_infra_again.previous.0.l3extConsLbl.attributes.descr == "ansible_sr_mpls_l3out_description" + - nm_add_l3out_to_infra_again.previous.0.l3extConsLbl.children.1.l3extRsLblToProfile.attributes.direction == "export" + - nm_add_l3out_to_infra_again.previous.0.l3extConsLbl.children.1.l3extRsLblToProfile.attributes.tDn == "uni/tn-ansible_test/prof-outbound_route_map" + - nm_add_l3out_to_infra_again.previous.0.l3extConsLbl.children.0.l3extRsLblToInstP.attributes.tDn == "uni/tn-ansible_test/out-ansible_sr_mpls_l3out/instP-ansible_external_epg" + - nm_add_l3out_to_infra_again.current.0.l3extConsLbl.attributes.name == "ansible_infra_sr_mpls_l3out" + - nm_add_l3out_to_infra_again.current.0.l3extConsLbl.attributes.descr == "ansible_sr_mpls_l3out_description" + - nm_add_l3out_to_infra_again.current.0.l3extConsLbl.children.1.l3extRsLblToProfile.attributes.direction == "export" + - nm_add_l3out_to_infra_again.current.0.l3extConsLbl.children.1.l3extRsLblToProfile.attributes.tDn == "uni/tn-ansible_test/prof-outbound_route_map" + - nm_add_l3out_to_infra_again.current.0.l3extConsLbl.children.0.l3extRsLblToInstP.attributes.tDn == "uni/tn-ansible_test/out-ansible_sr_mpls_l3out/instP-ansible_external_epg" + + - name: Update a l3out to sr-mpls infra l3out + cisco.aci.aci_l3out_to_sr_mpls_infra_l3out: &l3out_to_infra_present_updated + <<: *l3out_to_infra_present + description: ansible_sr_mpls_l3out_description_updated + external_epg: uni/tn-ansible_test/out-ansible_sr_mpls_l3out/instP-ansible_external_epg_updated + outbound_route_map: uni/tn-ansible_test/prof-outbound_route_map_updated + inbound_route_map: uni/tn-ansible_test/prof-inbound_route_map + register: nm_update_l3out_to_infra + + - name: Update a l3out to sr-mpls infra l3out to remove inbound route map + cisco.aci.aci_l3out_to_sr_mpls_infra_l3out: + <<: *l3out_to_infra_present_updated + inbound_route_map: "" + register: nm_update_l3out_to_infra_remove_inbound_route_map + + - name: Assert updates of l3out to sr-mpls infra l3outs + ansible.builtin.assert: + that: + - nm_update_l3out_to_infra is changed + - nm_update_l3out_to_infra.previous.0.l3extConsLbl.attributes.name == "ansible_infra_sr_mpls_l3out" + - nm_update_l3out_to_infra.previous.0.l3extConsLbl.attributes.descr == "ansible_sr_mpls_l3out_description" + - nm_update_l3out_to_infra.previous.0.l3extConsLbl.children.1.l3extRsLblToProfile.attributes.direction == "export" + - nm_update_l3out_to_infra.previous.0.l3extConsLbl.children.1.l3extRsLblToProfile.attributes.tDn == "uni/tn-ansible_test/prof-outbound_route_map" + - nm_update_l3out_to_infra.previous.0.l3extConsLbl.children.0.l3extRsLblToInstP.attributes.tDn == "uni/tn-ansible_test/out-ansible_sr_mpls_l3out/instP-ansible_external_epg" + - nm_update_l3out_to_infra.previous.0.l3extConsLbl.children | length == 2 + - nm_update_l3out_to_infra.current.0.l3extConsLbl.attributes.name == "ansible_infra_sr_mpls_l3out" + - nm_update_l3out_to_infra.current.0.l3extConsLbl.attributes.descr == "ansible_sr_mpls_l3out_description_updated" + - nm_update_l3out_to_infra.current.0.l3extConsLbl.children.1.l3extRsLblToProfile.attributes.direction == "import" + - nm_update_l3out_to_infra.current.0.l3extConsLbl.children.1.l3extRsLblToProfile.attributes.tDn == "uni/tn-ansible_test/prof-inbound_route_map" + - nm_update_l3out_to_infra.current.0.l3extConsLbl.children.2.l3extRsLblToProfile.attributes.direction == "export" + - nm_update_l3out_to_infra.current.0.l3extConsLbl.children.2.l3extRsLblToProfile.attributes.tDn == "uni/tn-ansible_test/prof-outbound_route_map_updated" + - nm_update_l3out_to_infra.current.0.l3extConsLbl.children.0.l3extRsLblToInstP.attributes.tDn == "uni/tn-ansible_test/out-ansible_sr_mpls_l3out/instP-ansible_external_epg_updated" + - nm_update_l3out_to_infra.current.0.l3extConsLbl.children | length == 3 + - nm_update_l3out_to_infra_remove_inbound_route_map is changed + - nm_update_l3out_to_infra_remove_inbound_route_map.previous.0.l3extConsLbl.attributes.name == "ansible_infra_sr_mpls_l3out" + - nm_update_l3out_to_infra_remove_inbound_route_map.previous.0.l3extConsLbl.attributes.descr == "ansible_sr_mpls_l3out_description_updated" + - nm_update_l3out_to_infra_remove_inbound_route_map.previous.0.l3extConsLbl.children.1.l3extRsLblToProfile.attributes.direction == "import" + - nm_update_l3out_to_infra_remove_inbound_route_map.previous.0.l3extConsLbl.children.1.l3extRsLblToProfile.attributes.tDn == "uni/tn-ansible_test/prof-inbound_route_map" + - nm_update_l3out_to_infra_remove_inbound_route_map.previous.0.l3extConsLbl.children.2.l3extRsLblToProfile.attributes.direction == "export" + - nm_update_l3out_to_infra_remove_inbound_route_map.previous.0.l3extConsLbl.children.2.l3extRsLblToProfile.attributes.tDn == "uni/tn-ansible_test/prof-outbound_route_map_updated" + - nm_update_l3out_to_infra_remove_inbound_route_map.previous.0.l3extConsLbl.children.0.l3extRsLblToInstP.attributes.tDn == "uni/tn-ansible_test/out-ansible_sr_mpls_l3out/instP-ansible_external_epg_updated" + - nm_update_l3out_to_infra_remove_inbound_route_map.previous.0.l3extConsLbl.children | length == 3 + - nm_update_l3out_to_infra_remove_inbound_route_map.current.0.l3extConsLbl.attributes.name == "ansible_infra_sr_mpls_l3out" + - nm_update_l3out_to_infra_remove_inbound_route_map.current.0.l3extConsLbl.attributes.descr == "ansible_sr_mpls_l3out_description_updated" + - nm_update_l3out_to_infra_remove_inbound_route_map.current.0.l3extConsLbl.children.1.l3extRsLblToProfile.attributes.direction == "export" + - nm_update_l3out_to_infra_remove_inbound_route_map.current.0.l3extConsLbl.children.1.l3extRsLblToProfile.attributes.tDn == "uni/tn-ansible_test/prof-outbound_route_map_updated" + - nm_update_l3out_to_infra_remove_inbound_route_map.current.0.l3extConsLbl.children.0.l3extRsLblToInstP.attributes.tDn == "uni/tn-ansible_test/out-ansible_sr_mpls_l3out/instP-ansible_external_epg_updated" + - nm_update_l3out_to_infra_remove_inbound_route_map.current.0.l3extConsLbl.children | length == 2 + + - name: Query a l3out to sr-mpls infra l3out + cisco.aci.aci_l3out_to_sr_mpls_infra_l3out: + <<: *l3out_to_infra_present + state: query + register: query_one + + - name: Query all l3out to sr-mpls infra l3outs + cisco.aci.aci_l3out_to_sr_mpls_infra_l3out: + <<: *aci_info + state: query + register: query_all + + - name: Assert l3out to sr-mpls infra l3outs queries + ansible.builtin.assert: + that: + - query_one is not changed + - query_one.current | length == 1 + - query_one.current.0.l3extConsLbl.attributes.name == "ansible_infra_sr_mpls_l3out" + - query_one.current.0.l3extConsLbl.children | length == 4 + - query_one.current.0.l3extConsLbl.children.0.bgpDomainIdAllocator.attributes.rn == "bgpdomainid" + - query_one.current.0.l3extConsLbl.children.1.l3extRsProvLblDef.attributes.tDn == "resPolCont/tn-[uni/tn-infra]/provlbl-ansible_infra_sr_mpls_l3out" + - query_one.current.0.l3extConsLbl.children.2.l3extRsLblToInstP.attributes.tDn == "uni/tn-ansible_test/out-ansible_sr_mpls_l3out/instP-ansible_external_epg_updated" + - query_one.current.0.l3extConsLbl.children.3.l3extRsLblToProfile.attributes.tDn == "uni/tn-ansible_test/prof-outbound_route_map_updated" + - query_all is not changed + - query_all.current | length >= 1 + + - name: Delete a l3out to sr-mpls infra l3out (check_mode) + cisco.aci.aci_l3out_to_sr_mpls_infra_l3out: &l3out_to_infra_absent + <<: *l3out_to_infra_present + state: absent + check_mode: true + register: cm_delete_l3out_to_infra + + - name: Delete a l3out to sr-mpls infra l3out + cisco.aci.aci_l3out_to_sr_mpls_infra_l3out: + <<: *l3out_to_infra_absent + register: nm_delete_l3out_to_infra + + - name: Delete a l3out to sr-mpls infra l3out again + cisco.aci.aci_l3out_to_sr_mpls_infra_l3out: + <<: *l3out_to_infra_absent + register: nm_delete_l3out_to_infra_again + + - name: Assert deletion of l3out to sr-mpls infra l3outs + ansible.builtin.assert: + that: + - cm_delete_l3out_to_infra is changed + - cm_delete_l3out_to_infra.previous.0.l3extConsLbl.attributes.name == "ansible_infra_sr_mpls_l3out" + - cm_delete_l3out_to_infra.proposed == {} + - nm_delete_l3out_to_infra is changed + - nm_delete_l3out_to_infra.previous.0.l3extConsLbl.attributes.name == "ansible_infra_sr_mpls_l3out" + - nm_delete_l3out_to_infra.current == [] + - nm_delete_l3out_to_infra_again is not changed + - nm_delete_l3out_to_infra_again.previous == [] + - nm_delete_l3out_to_infra_again.current == [] + + # CLEAN ENVIRONMENT END OF TESTS + - name: Delete the ansible_tenant at the end of tests + cisco.aci.aci_tenant: + <<: *aci_tenant_absent + + - name: Delete a infra sr mpls l3out at the end of tests + cisco.aci.aci_l3out: + <<: *aci_infra_sr_mpls_l3out_absent diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_lookup_interface_range/tasks/main.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_lookup_interface_range/tasks/main.yml index 5660d0b87..cac0c5b52 100644 --- a/ansible_collections/cisco/aci/tests/integration/targets/aci_lookup_interface_range/tasks/main.yml +++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_lookup_interface_range/tasks/main.yml @@ -4,12 +4,12 @@ # GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) - name: Test that we have an ACI APIC host, ACI username and ACI password - fail: + ansible.builtin.fail: msg: 'Please define the following variables: aci_hostname, aci_username and aci_password.' when: aci_hostname is not defined or aci_username is not defined or aci_password is not defined - name: Set vars - set_fact: + ansible.builtin.set_fact: aci_info: &aci_info host: "{{ aci_hostname }}" username: "{{ aci_username }}" @@ -26,7 +26,7 @@ register: single_string_single_range - name: Valid input assertions - assert: + ansible.builtin.assert: that: - single_string_single_range.results.0.item == "5/0" - single_string_single_range.results.1.item == "5/1" @@ -39,7 +39,7 @@ register: single_string_multiple_interface - name: Valid input assertions - assert: + ansible.builtin.assert: that: - single_string_multiple_interface.results.0.item == "1/1" - single_string_multiple_interface.results.1.item == "1/2" @@ -59,7 +59,7 @@ register: single_string_single_interface_as_range - name: Valid input assertions - assert: + ansible.builtin.assert: that: - single_string_single_interface_as_range.results.0.item == "1/1" @@ -70,7 +70,7 @@ register: single_string_mix_ranges - name: Valid input assertions - assert: + ansible.builtin.assert: that: - single_string_mix_ranges.results.0.item == "1/1" - single_string_mix_ranges.results.1.item == "1/2" @@ -101,7 +101,7 @@ register: invalid_range_order - name: Invalid input assertions - assert: + ansible.builtin.assert: that: - "'Invalid range inputs,' in invalid_pattern.msg" - "'Invalid range inputs,' in invalid_range_order.msg" @@ -121,7 +121,7 @@ msg: "{{ disable_leaf_int }}" - name: Valid disable interface assertions - assert: + ansible.builtin.assert: that: - disable_leaf_int.results.0.current.0.fabricRsOosPath.attributes.lc == "blacklist" - disable_leaf_int.results.0.current.0.fabricRsOosPath.attributes.tDn == "topology/pod-1/paths-1101/pathep-[eth1/30]" @@ -141,7 +141,7 @@ register: enable_leaf_int - name: Valid enable interface assertions - assert: + ansible.builtin.assert: that: - enable_leaf_int.results.0.current == [] - enable_leaf_int.results.1.current == [] diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_maintenance_group/tasks/main.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_maintenance_group/tasks/main.yml index 12284c8a6..b3a6701f4 100644 --- a/ansible_collections/cisco/aci/tests/integration/targets/aci_maintenance_group/tasks/main.yml +++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_maintenance_group/tasks/main.yml @@ -4,12 +4,12 @@ # GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) - name: Test that we have an ACI APIC host, ACI username and ACI password - fail: + ansible.builtin.fail: msg: 'Please define the following variables: aci_hostname, aci_username and aci_password.' when: aci_hostname is not defined or aci_username is not defined or aci_password is not defined - name: Set vars - set_fact: + ansible.builtin.set_fact: aci_info: &aci_info host: "{{ aci_hostname }}" username: "{{ aci_username }}" @@ -20,27 +20,27 @@ output_level: debug - name: Verify Cloud and Non-Cloud Sites in use. - include_tasks: ../../../../../../integration/targets/aci_cloud_provider/tasks/main.yml + ansible.builtin.include_tasks: ../../../../../../integration/targets/aci_cloud_provider/tasks/main.yml - name: Execute tasks only for non-cloud sites when: query_cloud.current == [] # This condition will execute only non-cloud sites block: # block specifies execution of tasks within, based on conditions # Clean Environment - name: Create Scheduler - aci_fabric_scheduler: &aci_fabric_scheduler_present + cisco.aci.aci_fabric_scheduler: &aci_fabric_scheduler_present <<: *aci_info name: anstest_scheduler state: present - name: Create maintenance policy - aci_maintenance_policy: &aci_maintenance_policy_present + cisco.aci.aci_maintenance_policy: &aci_maintenance_policy_present <<: *aci_info name: anstest_policy scheduler: anstest_scheduler state: present - name: Ensure first maintenance group does not exist - aci_maintenance_group: &aci_maintenance_group_absent + cisco.aci.aci_maintenance_group: &aci_maintenance_group_absent <<: *aci_info group: anstest_group policy: anstest_policy @@ -50,37 +50,37 @@ state: absent - name: Ensure second maintenance group does not exist - aci_maintenance_group: &aci_maintenance_group_2_absent + cisco.aci.aci_maintenance_group: &aci_maintenance_group_2_absent <<: *aci_info group: anstest_group_2 policy: anstest_policy_2 state: absent - name: Create first maintenance group (check_mode) - aci_maintenance_group: &aci_maintenance_group_present + cisco.aci.aci_maintenance_group: &aci_maintenance_group_present <<: *aci_maintenance_group_absent state: present check_mode: true register: cm_add_maintenance_group_1 - name: Create first maintenance group (normal_mode) - aci_maintenance_group: + cisco.aci.aci_maintenance_group: <<: *aci_maintenance_group_present register: nm_add_maintenance_group_1 - name: Create first maintenance group again - testing idempotency - aci_maintenance_group: + cisco.aci.aci_maintenance_group: <<: *aci_maintenance_group_present register: idempotency_add_maintenance_group_1 - name: Create second maintenance group - aci_maintenance_group: &aci_maintenance_group_2_present + cisco.aci.aci_maintenance_group: &aci_maintenance_group_2_present <<: *aci_maintenance_group_2_absent state: present register: nm_add_maintenance_group_2 - name: Asserts for creation tasks - assert: + ansible.builtin.assert: that: - cm_add_maintenance_group_1 is changed - cm_add_maintenance_group_1.previous == [] @@ -99,19 +99,19 @@ - name: Query all maintenance groups - aci_maintenance_group: + cisco.aci.aci_maintenance_group: <<: *aci_info state: query register: query_all_maintenance_group - name: Query first maintenance group - aci_maintenance_group: + cisco.aci.aci_maintenance_group: <<: *aci_maintenance_group_present state: query register: query_first_maintenance_group - name: Asserts for query tasks - assert: + ansible.builtin.assert: that: - query_all_maintenance_group is not changed - query_all_maintenance_group.current | length >= 2 @@ -126,32 +126,32 @@ - query_first_maintenance_group.current.0.maintMaintGrp.attributes.type == "ALL" - name: Delete first maintenance group (check_mode) - aci_maintenance_group: + cisco.aci.aci_maintenance_group: <<: *aci_maintenance_group_present state: absent check_mode: true register: cm_delete_maintenance_group_1 - name: Delete first maintenance group (normal_mode) - aci_maintenance_group: + cisco.aci.aci_maintenance_group: <<: *aci_maintenance_group_present state: absent register: nm_delete_maintenance_group_1 - name: Delete first maintenance group again - testing idempotency - aci_maintenance_group: + cisco.aci.aci_maintenance_group: <<: *aci_maintenance_group_present state: absent register: idempotency_delete_maintenance_group_1 - name: Delete second maintenance group (normal_mode) - aci_maintenance_group: + cisco.aci.aci_maintenance_group: <<: *aci_maintenance_group_2_present state: absent register: nm_delete_maintenance_group_2 - name: Asserts for deletion tasks - assert: + ansible.builtin.assert: that: - cm_delete_maintenance_group_1 is changed - cm_delete_maintenance_group_1.proposed == {} @@ -165,11 +165,11 @@ - nm_delete_maintenance_group_2.current == [] - name: Delete maintenance policy - clean up the environment - aci_maintenance_policy: + cisco.aci.aci_maintenance_policy: <<: *aci_maintenance_policy_present state: absent - name: Delete scheduler - clean up the environment - aci_fabric_scheduler: + cisco.aci.aci_fabric_scheduler: <<: *aci_fabric_scheduler_present state: absent diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_maintenance_group_node/tasks/main.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_maintenance_group_node/tasks/main.yml index 9be9ecbe8..d2223e892 100644 --- a/ansible_collections/cisco/aci/tests/integration/targets/aci_maintenance_group_node/tasks/main.yml +++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_maintenance_group_node/tasks/main.yml @@ -4,12 +4,12 @@ # GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) - name: Test that we have an ACI APIC host, ACI username and ACI password - fail: + ansible.builtin.fail: msg: 'Please define the following variables: aci_hostname, aci_username and aci_password.' when: aci_hostname is not defined or aci_username is not defined or aci_password is not defined - name: Set vars - set_fact: + ansible.builtin.set_fact: aci_info: &aci_info host: "{{ aci_hostname }}" username: "{{ aci_username }}" @@ -20,71 +20,71 @@ output_level: debug - name: Verify Cloud and Non-Cloud Sites in use. - include_tasks: ../../../../../../integration/targets/aci_cloud_provider/tasks/main.yml + ansible.builtin.include_tasks: ../../../../../../integration/targets/aci_cloud_provider/tasks/main.yml - name: Execute tasks only for non-cloud sites when: query_cloud.current == [] # This condition will execute only non-cloud sites block: # block specifies execution of tasks within, based on conditions # Clean Environment - name: Create Scheduler - aci_fabric_scheduler: &aci_fabric_scheduler_present + cisco.aci.aci_fabric_scheduler: &aci_fabric_scheduler_present <<: *aci_info name: anstest_scheduler state: present - name: Create maintenance policy - aci_maintenance_policy: &aci_maintenance_policy_present + cisco.aci.aci_maintenance_policy: &aci_maintenance_policy_present <<: *aci_info name: anstest_policy scheduler: anstest_scheduler state: present - name: Create maintenance groupe - aci_maintenance_group: &aci_maintenance_group_present + cisco.aci.aci_maintenance_group: &aci_maintenance_group_present <<: *aci_info group: anstest_group policy: anstest_policy state: present - name: Ensure first maintenance group node does not exist - aci_maintenance_group_node: &aci_maintenance_group_node_absent + cisco.aci.aci_maintenance_group_node: &aci_maintenance_group_node_absent <<: *aci_info group: anstest_group node: 1001 state: absent - name: Ensure second maintenance group node does not exist - aci_maintenance_group_node: &aci_maintenance_group_node_2_absent + cisco.aci.aci_maintenance_group_node: &aci_maintenance_group_node_2_absent <<: *aci_info group: anstest_group node: 1002 state: absent - name: Create first maintenance group node (check_mode) - aci_maintenance_group_node: &aci_maintenance_group_node_present + cisco.aci.aci_maintenance_group_node: &aci_maintenance_group_node_present <<: *aci_maintenance_group_node_absent state: present check_mode: true register: cm_add_maintenance_group_node_1 - name: Create first maintenance group node (normal_mode) - aci_maintenance_group_node: + cisco.aci.aci_maintenance_group_node: <<: *aci_maintenance_group_node_present register: nm_add_maintenance_group_node_1 - name: Create first maintenance group node again - testing idempotency - aci_maintenance_group_node: + cisco.aci.aci_maintenance_group_node: <<: *aci_maintenance_group_node_present register: idempotency_add_maintenance_group_node_1 - name: Create second maintenance group node - aci_maintenance_group_node: &aci_maintenance_group_node_2_present + cisco.aci.aci_maintenance_group_node: &aci_maintenance_group_node_2_present <<: *aci_maintenance_group_node_2_absent state: present register: nm_add_maintenance_group_node_2 - name: Asserts for creation tasks - assert: + ansible.builtin.assert: that: - cm_add_maintenance_group_node_1 is changed - cm_add_maintenance_group_node_1.previous == [] @@ -99,19 +99,19 @@ - name: Query all maintenance group nodes - aci_maintenance_group_node: + cisco.aci.aci_maintenance_group_node: <<: *aci_info state: query register: query_all_maintenance_group_node - name: Query first maintenance group nnode - aci_maintenance_group_node: + cisco.aci.aci_maintenance_group_node: <<: *aci_maintenance_group_node_present state: query register: query_first_maintenance_group_node - name: Asserts for query tasks - assert: + ansible.builtin.assert: that: - query_all_maintenance_group_node is not changed - query_all_maintenance_group_node.current | length >= 2 @@ -120,32 +120,32 @@ - query_first_maintenance_group_node.current.0.fabricNodeBlk.attributes.to_ == "1001" - name: Delete first maintenance group (check_mode) - aci_maintenance_group_node: + cisco.aci.aci_maintenance_group_node: <<: *aci_maintenance_group_node_present state: absent check_mode: true register: cm_delete_maintenance_group_node_1 - name: Delete first maintenance group (normal_mode) - aci_maintenance_group_node: + cisco.aci.aci_maintenance_group_node: <<: *aci_maintenance_group_node_present state: absent register: nm_delete_maintenance_group_node_1 - name: Delete first maintenance group again - testing idempotency - aci_maintenance_group_node: + cisco.aci.aci_maintenance_group_node: <<: *aci_maintenance_group_node_present state: absent register: idempotency_delete_maintenance_group_1 - name: Delete second maintenance group (normal_mode) - aci_maintenance_group_node: + cisco.aci.aci_maintenance_group_node: <<: *aci_maintenance_group_node_2_present state: absent register: nm_delete_maintenance_group_node_2 - name: Asserts for deletion tasks - assert: + ansible.builtin.assert: that: - cm_delete_maintenance_group_node_1 is changed - cm_delete_maintenance_group_node_1.proposed == {} @@ -159,16 +159,16 @@ - nm_delete_maintenance_group_node_2.current == [] - name: Delete maintenance group - clean up the environment - aci_maintenance_group: + cisco.aci.aci_maintenance_group: <<: *aci_maintenance_group_present state: absent - name: Delete maintenance policy - clean up the environment - aci_maintenance_policy: + cisco.aci.aci_maintenance_policy: <<: *aci_maintenance_policy_present state: absent - name: Delete scheduler - clean up the environment - aci_fabric_scheduler: + cisco.aci.aci_fabric_scheduler: <<: *aci_fabric_scheduler_present state: absent diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_maintenance_policy/tasks/main.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_maintenance_policy/tasks/main.yml index 8628c2a84..28abdbc72 100644 --- a/ansible_collections/cisco/aci/tests/integration/targets/aci_maintenance_policy/tasks/main.yml +++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_maintenance_policy/tasks/main.yml @@ -4,12 +4,12 @@ # GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) - name: Test that we have an ACI APIC host, ACI username and ACI password - fail: + ansible.builtin.fail: msg: 'Please define the following variables: aci_hostname, aci_username and aci_password.' when: aci_hostname is not defined or aci_username is not defined or aci_password is not defined - name: Set vars - set_fact: + ansible.builtin.set_fact: aci_info: &aci_info host: "{{ aci_hostname }}" username: "{{ aci_username }}" @@ -20,20 +20,20 @@ output_level: debug - name: Verify Cloud and Non-Cloud Sites in use. - include_tasks: ../../../../../../integration/targets/aci_cloud_provider/tasks/main.yml + ansible.builtin.include_tasks: ../../../../../../integration/targets/aci_cloud_provider/tasks/main.yml - name: Execute tasks only for non-cloud sites when: query_cloud.current == [] # This condition will execute only non-cloud sites block: # block specifies execution of tasks within, based on conditions # Clean Environment - name: Create Scheduler - aci_fabric_scheduler: &aci_fabric_scheduler_present + cisco.aci.aci_fabric_scheduler: &aci_fabric_scheduler_present <<: *aci_info name: anstest_scheduler state: present - name: Ensure first maintenance policy does not exist - aci_maintenance_policy: &aci_maintenance_policy_absent + cisco.aci.aci_maintenance_policy: &aci_maintenance_policy_absent <<: *aci_info name: anstest_policy description: test for maintenance policy @@ -49,37 +49,37 @@ state: absent - name: Ensure second maintenance policy does not exist - aci_maintenance_policy: &aci_maintenance_policy_2_absent + cisco.aci.aci_maintenance_policy: &aci_maintenance_policy_2_absent <<: *aci_info name: anstest_policy_2 scheduler: anstest_scheduler state: absent - name: Create first maintenance policy (check_mode) - aci_maintenance_policy: &aci_maintenance_policy_present + cisco.aci.aci_maintenance_policy: &aci_maintenance_policy_present <<: *aci_maintenance_policy_absent state: present check_mode: true register: cm_add_maintenance_policy_1 - name: Create first maintenance policy (normal_mode) - aci_maintenance_policy: + cisco.aci.aci_maintenance_policy: <<: *aci_maintenance_policy_present register: nm_add_maintenance_policy_1 - name: Create first maintenance policy again - testing idempotency - aci_maintenance_policy: + cisco.aci.aci_maintenance_policy: <<: *aci_maintenance_policy_present register: idempotency_add_maintenance_policy_1 - name: Create second maintenance policy - aci_maintenance_policy: &aci_maintenance_policy_2_present + cisco.aci.aci_maintenance_policy: &aci_maintenance_policy_2_present <<: *aci_maintenance_policy_2_absent state: present register: nm_add_maintenance_policy_2 - name: Asserts for creation tasks - assert: + ansible.builtin.assert: that: - cm_add_maintenance_policy_1 is changed - cm_add_maintenance_policy_1.previous == [] @@ -109,19 +109,19 @@ - nm_add_maintenance_policy_2.current.0.maintMaintP.children.0.maintRsPolScheduler.attributes.tnTrigSchedPName == "anstest_scheduler" - name: Query all maintenance policies - aci_maintenance_policy: + cisco.aci.aci_maintenance_policy: <<: *aci_info state: query register: query_all_maintenance_policy - name: Query first maintenance policy - aci_maintenance_policy: + cisco.aci.aci_maintenance_policy: <<: *aci_maintenance_policy_present state: query register: query_first_maintenance_policy - name: Asserts for query tasks - assert: + ansible.builtin.assert: that: - query_all_maintenance_policy is not changed - query_all_maintenance_policy.current | length >= 2 @@ -140,32 +140,32 @@ - query_first_maintenance_policy.current.0.maintMaintP.children.0.maintRsPolScheduler.attributes.tnTrigSchedPName == "anstest_scheduler" - name: Delete first maintenance policy (check_mode) - aci_maintenance_policy: + cisco.aci.aci_maintenance_policy: <<: *aci_maintenance_policy_present state: absent check_mode: true register: cm_delete_maintenance_policy_1 - name: Delete first maintenance policy (normal_mode) - aci_maintenance_policy: + cisco.aci.aci_maintenance_policy: <<: *aci_maintenance_policy_present state: absent register: nm_delete_maintenance_policy_1 - name: Delete first maintenance policy again - testing idempotency - aci_maintenance_policy: + cisco.aci.aci_maintenance_policy: <<: *aci_maintenance_policy_present state: absent register: idempotency_delete_maintenance_policy_1 - name: Delete second maintenance policy (normal_mode) - aci_maintenance_policy: + cisco.aci.aci_maintenance_policy: <<: *aci_maintenance_policy_2_present state: absent register: nm_delete_maintenance_policy_2 - name: Asserts for deletion tasks - assert: + ansible.builtin.assert: that: - cm_delete_maintenance_policy_1 is changed - cm_delete_maintenance_policy_1.proposed == {} @@ -179,6 +179,6 @@ - nm_delete_maintenance_policy_2.current == [] - name: Delete scheduler - clean up the environment - aci_fabric_scheduler: + cisco.aci.aci_fabric_scheduler: <<: *aci_fabric_scheduler_present state: absent diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_match_as_path_regex_term/tasks/main.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_match_as_path_regex_term/tasks/main.yml index cdabd8b4e..120acf12d 100644 --- a/ansible_collections/cisco/aci/tests/integration/targets/aci_match_as_path_regex_term/tasks/main.yml +++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_match_as_path_regex_term/tasks/main.yml @@ -4,12 +4,12 @@ # GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) - name: Test that we have an ACI APIC host, ACI username and ACI password - fail: + ansible.builtin.fail: msg: 'Please define the following variables: aci_hostname, aci_username and aci_password.' when: aci_hostname is not defined or aci_username is not defined or aci_password is not defined - name: Set vars - set_fact: + ansible.builtin.set_fact: aci_info: &aci_info host: "{{ aci_hostname }}" username: "{{ aci_username }}" @@ -21,26 +21,26 @@ # CLEAN ENVIRONMENT - name: Remove the ansible_tenant - aci_tenant: &aci_tenant_absent + cisco.aci.aci_tenant: &aci_tenant_absent <<: *aci_info tenant: ansible_tenant state: absent - name: Verify Cloud and Non-Cloud Sites in use. - include_tasks: ../../../../../../integration/targets/aci_cloud_provider/tasks/main.yml + ansible.builtin.include_tasks: ../../../../../../integration/targets/aci_cloud_provider/tasks/main.yml - name: Execute tasks only for non-cloud sites when: query_cloud.current == [] # This condition will execute only non-cloud sites block: # block specifies execution of tasks within, based on conditions - name: Add a new tenant - aci_tenant: &aci_tenant_present + cisco.aci.aci_tenant: &aci_tenant_present <<: *aci_info tenant: ansible_tenant description: Ansible tenant state: present - name: Add a match rule profile - aci_match_rule: + cisco.aci.aci_match_rule: <<: *aci_info tenant: ansible_tenant match_rule: ansible_match_rule @@ -49,7 +49,7 @@ register: cm_add_match_rule - name: Add a match regex AS-Path term (check_mode) - aci_match_as_path_regex_term: &aci_match_as_path_regex_term_present + cisco.aci.aci_match_as_path_regex_term: &aci_match_as_path_regex_term_present <<: *aci_info tenant: ansible_tenant match_rule: ansible_match_rule @@ -61,17 +61,17 @@ register: cm_add_match_as_path_regex_term - name: Add a match regex AS-Path term (normal_mode) - aci_match_as_path_regex_term: + cisco.aci.aci_match_as_path_regex_term: <<: *aci_match_as_path_regex_term_present register: nm_add_match_as_path_regex_term - name: Add the first match regex AS-Path term again - testing idempotency - aci_match_as_path_regex_term: + cisco.aci.aci_match_as_path_regex_term: <<: *aci_match_as_path_regex_term_present register: nm_add_match_as_path_regex_term_idempotency - name: Add a second match regex AS-Path term (normal_mode) - aci_match_as_path_regex_term: + cisco.aci.aci_match_as_path_regex_term: <<: *aci_info tenant: ansible_tenant match_rule: ansible_match_rule @@ -81,7 +81,7 @@ register: nm_add_match_as_path_regex_term_2 - name: Asserts for match regex AS-Path terms creation tasks - assert: + ansible.builtin.assert: that: - cm_add_match_as_path_regex_term is changed - cm_add_match_as_path_regex_term.previous == [] @@ -96,19 +96,19 @@ - nm_add_match_as_path_regex_term_2.current.0.rtctrlMatchAsPathRegexTerm.attributes.regex == "" - name: Query all match regex AS-Path terms - aci_match_as_path_regex_term: + cisco.aci.aci_match_as_path_regex_term: <<: *aci_info state: query register: query_all_match_as_path_regex_term - name: Query ansible_match_as_path_regex_term_1 - aci_match_as_path_regex_term: + cisco.aci.aci_match_as_path_regex_term: <<: *aci_match_as_path_regex_term_present state: query register: query_ansible_match_as_path_regex_term_1 - name: Asserts query tasks - assert: + ansible.builtin.assert: that: - query_all_match_as_path_regex_term is not changed - query_all_match_as_path_regex_term.current|length >= 2 @@ -117,24 +117,24 @@ - query_ansible_match_as_path_regex_term_1.current.0.rtctrlMatchAsPathRegexTerm.attributes.regex == ".*" - name: Remove match regex AS-Path term for l3out (check_mode) - aci_match_as_path_regex_term: &match_as_path_regex_term_absent + cisco.aci.aci_match_as_path_regex_term: &match_as_path_regex_term_absent <<: *aci_match_as_path_regex_term_present state: absent check_mode: true register: cm_remove_match_as_path_regex_term - name: Remove match regex AS-Path term for l3out (normal_mode) - aci_match_as_path_regex_term: + cisco.aci.aci_match_as_path_regex_term: <<: *match_as_path_regex_term_absent register: nm_remove_match_as_path_regex_term - name: Remove match regex AS-Path term for l3out again - testing previous Removal - aci_match_as_path_regex_term: + cisco.aci.aci_match_as_path_regex_term: <<: *match_as_path_regex_term_absent register: nm_remove_match_as_path_regex_term_idempotency - name: Asserts deletion tasks - assert: + ansible.builtin.assert: that: - cm_remove_match_as_path_regex_term is changed - cm_remove_match_as_path_regex_term.proposed == {} @@ -145,6 +145,6 @@ - nm_remove_match_as_path_regex_term_idempotency.previous == [] - name: Remove the ansible_tenant - cleanup before ending tests - aci_tenant: + cisco.aci.aci_tenant: <<: *aci_tenant_present state: absent diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_match_community_factor/tasks/main.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_match_community_factor/tasks/main.yml index 2cc1f3ac1..22a69dcfe 100644 --- a/ansible_collections/cisco/aci/tests/integration/targets/aci_match_community_factor/tasks/main.yml +++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_match_community_factor/tasks/main.yml @@ -4,12 +4,12 @@ # GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) - name: Test that we have an ACI APIC host, ACI username and ACI password - fail: + ansible.builtin.fail: msg: 'Please define the following variables: aci_hostname, aci_username and aci_password.' when: aci_hostname is not defined or aci_username is not defined or aci_password is not defined - name: Set vars - set_fact: + ansible.builtin.set_fact: aci_info: &aci_info host: "{{ aci_hostname }}" username: "{{ aci_username }}" @@ -21,26 +21,26 @@ # CLEAN ENVIRONMENT - name: Remove the ansible_tenant - aci_tenant: &aci_tenant_absent + cisco.aci.aci_tenant: &aci_tenant_absent <<: *aci_info tenant: ansible_tenant state: absent - name: Verify Cloud and Non-Cloud Sites in use. - include_tasks: ../../../../../../integration/targets/aci_cloud_provider/tasks/main.yml + ansible.builtin.include_tasks: ../../../../../../integration/targets/aci_cloud_provider/tasks/main.yml - name: Execute tasks only for non-cloud sites when: query_cloud.current == [] # This condition will execute only non-cloud sites block: # block specifies execution of tasks within, based on conditions - name: Add a new tenant - aci_tenant: &aci_tenant_present + cisco.aci.aci_tenant: &aci_tenant_present <<: *aci_info tenant: ansible_tenant description: Ansible tenant state: present - name: Add a match rule profile - aci_match_rule: + cisco.aci.aci_match_rule: <<: *aci_info tenant: ansible_tenant match_rule: ansible_match_rule @@ -48,7 +48,7 @@ state: present - name: Add a match community term - aci_match_community_term: + cisco.aci.aci_match_community_term: <<: *aci_info tenant: ansible_tenant match_rule: ansible_match_rule @@ -57,7 +57,7 @@ state: present - name: Add a match community factor (check_mode) - aci_match_community_factor: &aci_match_community_factor_present + cisco.aci.aci_match_community_factor: &aci_match_community_factor_present <<: *aci_info tenant: ansible_tenant match_rule: ansible_match_rule @@ -70,17 +70,17 @@ register: cm_add_match_community_factor - name: Add a match community factor (normal_mode) - aci_match_community_factor: + cisco.aci.aci_match_community_factor: <<: *aci_match_community_factor_present register: nm_add_match_community_factor - name: Add the first match community factor again - testing idempotency - aci_match_community_factor: + cisco.aci.aci_match_community_factor: <<: *aci_match_community_factor_present register: nm_add_match_community_factor_idempotency - name: Add a second match community factor (normal_mode) - aci_match_community_factor: + cisco.aci.aci_match_community_factor: <<: *aci_info tenant: ansible_tenant match_rule: ansible_match_rule @@ -91,7 +91,7 @@ register: nm_add_match_community_factor_2 - name: Asserts for match community factors creation tasks - assert: + ansible.builtin.assert: that: - cm_add_match_community_factor is changed - cm_add_match_community_factor.previous == [] @@ -104,19 +104,19 @@ - nm_add_match_community_factor_2.current.0.rtctrlMatchCommFactor.attributes.community == "regular:as2-nn2:4:16" - name: Query all match community factors - aci_match_community_factor: + cisco.aci.aci_match_community_factor: <<: *aci_info state: query register: query_all_match_community_factor - name: Query a specific match community factor - aci_match_community_factor: + cisco.aci.aci_match_community_factor: <<: *aci_match_community_factor_present state: query register: query_ansible_match_community_factor_1 - name: Asserts query tasks - assert: + ansible.builtin.assert: that: - query_all_match_community_factor is not changed - query_all_match_community_factor.current|length >= 2 @@ -124,24 +124,24 @@ - query_ansible_match_community_factor_1.current.0.rtctrlMatchCommFactor.attributes.community == "regular:as2-nn2:4:15" - name: Remove match community factor (check_mode) - aci_match_community_factor: &match_community_term_absent + cisco.aci.aci_match_community_factor: &match_community_term_absent <<: *aci_match_community_factor_present state: absent check_mode: true register: cm_remove_match_community_factor - name: Remove match community factor (normal_mode) - aci_match_community_factor: + cisco.aci.aci_match_community_factor: <<: *match_community_term_absent register: nm_remove_match_community_factor - name: Remove match community factor again - testing previous Removal - aci_match_community_factor: + cisco.aci.aci_match_community_factor: <<: *match_community_term_absent register: nm_remove_match_community_factor_idempotency - name: Asserts deletion tasks - assert: + ansible.builtin.assert: that: - cm_remove_match_community_factor is changed - cm_remove_match_community_factor.proposed == {} @@ -152,6 +152,6 @@ - nm_remove_match_community_factor_idempotency.previous == [] - name: Remove the ansible_tenant - cleanup before ending tests - aci_tenant: + cisco.aci.aci_tenant: <<: *aci_tenant_present state: absent diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_match_community_regex_term/tasks/main.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_match_community_regex_term/tasks/main.yml index c0b12c78c..264a04afa 100644 --- a/ansible_collections/cisco/aci/tests/integration/targets/aci_match_community_regex_term/tasks/main.yml +++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_match_community_regex_term/tasks/main.yml @@ -4,12 +4,12 @@ # GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) - name: Test that we have an ACI APIC host, ACI username and ACI password - fail: + ansible.builtin.fail: msg: 'Please define the following variables: aci_hostname, aci_username and aci_password.' when: aci_hostname is not defined or aci_username is not defined or aci_password is not defined - name: Set vars - set_fact: + ansible.builtin.set_fact: aci_info: &aci_info host: "{{ aci_hostname }}" username: "{{ aci_username }}" @@ -21,26 +21,26 @@ # CLEAN ENVIRONMENT - name: Remove the ansible_tenant - aci_tenant: &aci_tenant_absent + cisco.aci.aci_tenant: &aci_tenant_absent <<: *aci_info tenant: ansible_tenant state: absent - name: Verify Cloud and Non-Cloud Sites in use. - include_tasks: ../../../../../../integration/targets/aci_cloud_provider/tasks/main.yml + ansible.builtin.include_tasks: ../../../../../../integration/targets/aci_cloud_provider/tasks/main.yml - name: Execute tasks only for non-cloud sites when: query_cloud.current == [] # This condition will execute only non-cloud sites block: # block specifies execution of tasks within, based on conditions - name: Add a new tenant - aci_tenant: &aci_tenant_present + cisco.aci.aci_tenant: &aci_tenant_present <<: *aci_info tenant: ansible_tenant description: Ansible tenant state: present - name: Add a match rule profile - aci_match_rule: + cisco.aci.aci_match_rule: <<: *aci_info tenant: ansible_tenant match_rule: ansible_match_rule @@ -49,7 +49,7 @@ register: cm_add_match_rule - name: Add a match community regex term (check_mode) - aci_match_community_regex_term: &aci_match_community_regex_term_present + cisco.aci.aci_match_community_regex_term: &aci_match_community_regex_term_present <<: *aci_info tenant: ansible_tenant match_rule: ansible_match_rule @@ -62,17 +62,17 @@ register: cm_add_match_community_regex_term - name: Add a match community regex term (normal_mode) - aci_match_community_regex_term: + cisco.aci.aci_match_community_regex_term: <<: *aci_match_community_regex_term_present register: nm_add_match_community_regex_term - name: Add the first match community regex term again - testing idempotency - aci_match_community_regex_term: + cisco.aci.aci_match_community_regex_term: <<: *aci_match_community_regex_term_present register: nm_add_match_community_regex_term_idempotency - name: Add a second match community regex term (normal_mode) - aci_match_community_regex_term: &aci_match_community_regex_term_2_present + cisco.aci.aci_match_community_regex_term: &aci_match_community_regex_term_2_present <<: *aci_info tenant: ansible_tenant match_rule: ansible_match_rule @@ -81,7 +81,7 @@ register: nm_add_match_community_regex_term_2 - name: Asserts for match community regex terms creation tasks - assert: + ansible.builtin.assert: that: - cm_add_match_community_regex_term is changed - cm_add_match_community_regex_term.previous == [] @@ -97,20 +97,20 @@ - nm_add_match_community_regex_term_2.current.0.rtctrlMatchCommRegexTerm.attributes.commType == "regular" - name: Query all match community regex terms - aci_match_community_regex_term: + cisco.aci.aci_match_community_regex_term: <<: *aci_info state: query community_type: extended register: query_all_match_community_regex_term - name: Query ansible_match_community_regex_term_regular - aci_match_community_regex_term: + cisco.aci.aci_match_community_regex_term: <<: *aci_match_community_regex_term_2_present state: query register: query_ansible_match_community_regex_term_regular - name: Asserts query tasks - assert: + ansible.builtin.assert: that: - query_all_match_community_regex_term is not changed - query_all_match_community_regex_term.current.0.rtctrlMatchCommRegexTerm.attributes.commType == "extended" @@ -119,24 +119,24 @@ - query_ansible_match_community_regex_term_regular.current.0.rtctrlMatchCommRegexTerm.attributes.commType == "regular" - name: Remove match community regex term (check_mode) - aci_match_community_regex_term: &match_community_regex_term_absent + cisco.aci.aci_match_community_regex_term: &match_community_regex_term_absent <<: *aci_match_community_regex_term_present state: absent check_mode: true register: cm_remove_match_community_regex_term - name: Remove match community regex term (normal_mode) - aci_match_community_regex_term: + cisco.aci.aci_match_community_regex_term: <<: *match_community_regex_term_absent register: nm_remove_match_community_regex_term - name: Remove match community regex term again - testing previous Removal - aci_match_community_regex_term: + cisco.aci.aci_match_community_regex_term: <<: *match_community_regex_term_absent register: nm_remove_match_community_regex_term_idempotency - name: Asserts deletion tasks - assert: + ansible.builtin.assert: that: - cm_remove_match_community_regex_term is changed - cm_remove_match_community_regex_term.proposed == {} @@ -147,6 +147,6 @@ - nm_remove_match_community_regex_term_idempotency.previous == [] - name: Remove the ansible_tenant - cleanup before ending tests - aci_tenant: + cisco.aci.aci_tenant: <<: *aci_tenant_present state: absent \ No newline at end of file diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_match_community_term/tasks/main.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_match_community_term/tasks/main.yml index aecf89096..038abb761 100644 --- a/ansible_collections/cisco/aci/tests/integration/targets/aci_match_community_term/tasks/main.yml +++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_match_community_term/tasks/main.yml @@ -4,12 +4,12 @@ # GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) - name: Test that we have an ACI APIC host, ACI username and ACI password - fail: + ansible.builtin.fail: msg: 'Please define the following variables: aci_hostname, aci_username and aci_password.' when: aci_hostname is not defined or aci_username is not defined or aci_password is not defined - name: Set vars - set_fact: + ansible.builtin.set_fact: aci_info: &aci_info host: "{{ aci_hostname }}" username: "{{ aci_username }}" @@ -21,26 +21,26 @@ # CLEAN ENVIRONMENT - name: Remove the ansible_tenant - aci_tenant: &aci_tenant_absent + cisco.aci.aci_tenant: &aci_tenant_absent <<: *aci_info tenant: ansible_tenant state: absent - name: Verify Cloud and Non-Cloud Sites in use. - include_tasks: ../../../../../../integration/targets/aci_cloud_provider/tasks/main.yml + ansible.builtin.include_tasks: ../../../../../../integration/targets/aci_cloud_provider/tasks/main.yml - name: Execute tasks only for non-cloud sites when: query_cloud.current == [] # This condition will execute only non-cloud sites block: # block specifies execution of tasks within, based on conditions - name: Add a new tenant - aci_tenant: &aci_tenant_present + cisco.aci.aci_tenant: &aci_tenant_present <<: *aci_info tenant: ansible_tenant description: Ansible tenant state: present - name: Add a match rule profile - aci_match_rule: + cisco.aci.aci_match_rule: <<: *aci_info tenant: ansible_tenant match_rule: ansible_match_rule @@ -49,7 +49,7 @@ register: cm_add_match_rule - name: Add a match community term (check_mode) - aci_match_community_term: &aci_match_community_term_present + cisco.aci.aci_match_community_term: &aci_match_community_term_present <<: *aci_info tenant: ansible_tenant match_rule: ansible_match_rule @@ -60,17 +60,17 @@ register: cm_add_match_community_term - name: Add a match community term (normal_mode) - aci_match_community_term: + cisco.aci.aci_match_community_term: <<: *aci_match_community_term_present register: nm_add_match_community_term - name: Add the first match community term again - testing idempotency - aci_match_community_term: + cisco.aci.aci_match_community_term: <<: *aci_match_community_term_present register: nm_add_match_community_term_idempotency - name: Add a second match community term (normal_mode) - aci_match_community_term: + cisco.aci.aci_match_community_term: <<: *aci_info tenant: ansible_tenant match_rule: ansible_match_rule @@ -80,7 +80,7 @@ register: nm_add_match_community_term_2 - name: Asserts for match community terms creation tasks - assert: + ansible.builtin.assert: that: - cm_add_match_community_term is changed - cm_add_match_community_term.previous == [] @@ -93,19 +93,19 @@ - nm_add_match_community_term_2.current.0.rtctrlMatchCommTerm.attributes.name == "ansible_match_community_term_2" - name: Query all match community terms - aci_match_community_term: + cisco.aci.aci_match_community_term: <<: *aci_info state: query register: query_all_match_community_term - name: Query ansible_match_community_term_1 - aci_match_community_term: + cisco.aci.aci_match_community_term: <<: *aci_match_community_term_present state: query register: query_ansible_match_community_term_1 - name: Asserts query tasks - assert: + ansible.builtin.assert: that: - query_all_match_community_term is not changed - query_all_match_community_term.current|length >= 2 @@ -113,24 +113,24 @@ - query_ansible_match_community_term_1.current.0.rtctrlMatchCommTerm.attributes.name == "ansible_match_community_term_1" - name: Remove match community term (check_mode) - aci_match_community_term: &match_community_term_absent + cisco.aci.aci_match_community_term: &match_community_term_absent <<: *aci_match_community_term_present state: absent check_mode: true register: cm_remove_match_community_term - name: Remove match community term (normal_mode) - aci_match_community_term: + cisco.aci.aci_match_community_term: <<: *match_community_term_absent register: nm_remove_match_community_term - name: Remove match community term again - testing previous Removal - aci_match_community_term: + cisco.aci.aci_match_community_term: <<: *match_community_term_absent register: nm_remove_match_community_term_idempotency - name: Asserts deletion tasks - assert: + ansible.builtin.assert: that: - cm_remove_match_community_term is changed - cm_remove_match_community_term.proposed == {} @@ -141,6 +141,6 @@ - nm_remove_match_community_term_idempotency.previous == [] - name: Remove the ansible_tenant - cleanup before ending tests - aci_tenant: + cisco.aci.aci_tenant: <<: *aci_tenant_present state: absent diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_match_route_destination/tasks/main.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_match_route_destination/tasks/main.yml index b4d49c2ff..54d906952 100644 --- a/ansible_collections/cisco/aci/tests/integration/targets/aci_match_route_destination/tasks/main.yml +++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_match_route_destination/tasks/main.yml @@ -5,12 +5,12 @@ # GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) - name: Test that we have an ACI APIC host, ACI username and ACI password - fail: + ansible.builtin.fail: msg: 'Please define the following variables: aci_hostname, aci_username and aci_password.' when: aci_hostname is not defined or aci_username is not defined or aci_password is not defined - name: Set vars - set_fact: + ansible.builtin.set_fact: aci_info: &aci_info host: "{{ aci_hostname }}" username: "{{ aci_username }}" @@ -22,26 +22,26 @@ # CLEAN ENVIRONMENT - name: Remove the ansible_tenant - aci_tenant: &aci_tenant_absent + cisco.aci.aci_tenant: &aci_tenant_absent <<: *aci_info tenant: ansible_tenant state: absent - name: Verify Cloud and Non-Cloud Sites in use. - include_tasks: ../../../../../../integration/targets/aci_cloud_provider/tasks/main.yml + ansible.builtin.include_tasks: ../../../../../../integration/targets/aci_cloud_provider/tasks/main.yml - name: Execute tasks only for non-cloud sites when: query_cloud.current == [] # This condition will execute only non-cloud sites block: # block specifies execution of tasks within, based on conditions - name: Add a new tenant - aci_tenant: &aci_tenant_present + cisco.aci.aci_tenant: &aci_tenant_present <<: *aci_info tenant: ansible_tenant description: Ansible tenant state: present - name: Add a match rule profile - aci_match_rule: + cisco.aci.aci_match_rule: <<: *aci_info tenant: ansible_tenant match_rule: ansible_match_rule @@ -50,7 +50,7 @@ register: cm_add_match_rule - name: Add a match route destination rule (check_mode) - aci_match_route_destination: &aci_match_route_destination_present + cisco.aci.aci_match_route_destination: &aci_match_route_destination_present <<: *aci_info tenant: ansible_tenant match_rule: ansible_match_rule @@ -64,17 +64,17 @@ register: cm_add_match_route_destination - name: Add a match route destination rule (normal_mode) - aci_match_route_destination: + cisco.aci.aci_match_route_destination: <<: *aci_match_route_destination_present register: nm_add_match_route_destination - name: Add the first match route destination rule again - testing idempotency - aci_match_route_destination: + cisco.aci.aci_match_route_destination: <<: *aci_match_route_destination_present register: nm_add_match_route_destination_idempotency - name: Add a second match route destination rule (normal_mode) - aci_match_route_destination: + cisco.aci.aci_match_route_destination: <<: *aci_info tenant: ansible_tenant match_rule: ansible_match_rule @@ -84,7 +84,7 @@ register: nm_add_match_route_destination_2 - name: Asserts for match route destination rule creation tasks - assert: + ansible.builtin.assert: that: - cm_add_match_route_destination is changed - cm_add_match_route_destination.previous == [] @@ -103,19 +103,19 @@ - nm_add_match_route_destination_2.current.0.rtctrlMatchRtDest.attributes.toPfxLen == "0" - name: Query all match regex AS-Path terms - aci_match_route_destination: + cisco.aci.aci_match_route_destination: <<: *aci_info state: query register: query_all_match_route_destination - name: Query ansible_match_route_destination_1 - aci_match_route_destination: + cisco.aci.aci_match_route_destination: <<: *aci_match_route_destination_present state: query register: query_ansible_match_route_destination_1 - name: Asserts query tasks - assert: + ansible.builtin.assert: that: - query_all_match_route_destination is not changed - query_all_match_route_destination.current|length >= 2 @@ -126,24 +126,24 @@ - query_ansible_match_route_destination_1.current.0.rtctrlMatchRtDest.attributes.toPfxLen == "32" - name: Remove match route destination rule (check_mode) - aci_match_route_destination: &match_route_destination_absent + cisco.aci.aci_match_route_destination: &match_route_destination_absent <<: *aci_match_route_destination_present state: absent check_mode: true register: cm_remove_match_route_destination - name: Remove match route destination rule (normal_mode) - aci_match_route_destination: + cisco.aci.aci_match_route_destination: <<: *match_route_destination_absent register: nm_remove_match_route_destination - name: Remove match route destination rule again - testing previous Removal - aci_match_route_destination: + cisco.aci.aci_match_route_destination: <<: *match_route_destination_absent register: nm_remove_match_route_destination_idempotency - name: Asserts deletion tasks - assert: + ansible.builtin.assert: that: - cm_remove_match_route_destination is changed - cm_remove_match_route_destination.proposed == {} @@ -154,6 +154,6 @@ - nm_remove_match_route_destination_idempotency.previous == [] - name: Remove the ansible_tenant - cleanup before ending tests - aci_tenant: + cisco.aci.aci_tenant: <<: *aci_tenant_present state: absent \ No newline at end of file diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_match_rule/tasks/main.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_match_rule/tasks/main.yml index 23509494c..4d453d017 100644 --- a/ansible_collections/cisco/aci/tests/integration/targets/aci_match_rule/tasks/main.yml +++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_match_rule/tasks/main.yml @@ -5,12 +5,12 @@ # GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) - name: Test that we have an ACI APIC host, ACI username and ACI password - fail: + ansible.builtin.fail: msg: 'Please define the following variables: aci_hostname, aci_username and aci_password.' when: aci_hostname is not defined or aci_username is not defined or aci_password is not defined - name: Set vars - set_fact: + ansible.builtin.set_fact: aci_info: &aci_info host: "{{ aci_hostname }}" username: "{{ aci_username }}" @@ -22,26 +22,26 @@ # CLEAN ENVIRONMENT - name: Remove the ansible_tenant - aci_tenant: &aci_tenant_absent + cisco.aci.aci_tenant: &aci_tenant_absent <<: *aci_info tenant: ansible_tenant state: absent - name: Verify Cloud and Non-Cloud Sites in use. - include_tasks: ../../../../../../integration/targets/aci_cloud_provider/tasks/main.yml + ansible.builtin.include_tasks: ../../../../../../integration/targets/aci_cloud_provider/tasks/main.yml - name: Execute tasks only for non-cloud sites when: query_cloud.current == [] # This condition will execute only non-cloud sites block: # block specifies execution of tasks within, based on conditions - name: Add a new tenant - aci_tenant: &aci_tenant_present + cisco.aci.aci_tenant: &aci_tenant_present <<: *aci_info tenant: ansible_tenant description: Ansible tenant state: present - name: Add a match rule profile (check_mode) - aci_match_rule: &aci_match_rule_present + cisco.aci.aci_match_rule: &aci_match_rule_present <<: *aci_info tenant: ansible_tenant match_rule: ansible_match_rule_1 @@ -51,17 +51,17 @@ register: cm_add_match_rule - name: Add a match rule profile (normal_mode) - aci_match_rule: + cisco.aci.aci_match_rule: <<: *aci_match_rule_present register: nm_add_match_rule - name: Add the first match rule profile again - testing idempotency - aci_match_rule: + cisco.aci.aci_match_rule: <<: *aci_match_rule_present register: nm_add_match_rule_idempotency - name: Add a second match rule profile (normal_mode) - aci_match_rule: + cisco.aci.aci_match_rule: <<: *aci_info tenant: ansible_tenant match_rule: ansible_match_rule_2 @@ -70,7 +70,7 @@ register: nm_add_match_rule_2 - name: Asserts for match rule profiles creation tasks - assert: + ansible.builtin.assert: that: - cm_add_match_rule is changed - cm_add_match_rule.previous == [] @@ -83,19 +83,19 @@ - nm_add_match_rule_2.current.0.rtctrlSubjP.attributes.name == "ansible_match_rule_2" - name: Query all match rule profiles - aci_match_rule: + cisco.aci.aci_match_rule: <<: *aci_info state: query register: query_all_match_rule - name: Query ansible_match_rule_1 - aci_match_rule: + cisco.aci.aci_match_rule: <<: *aci_match_rule_present state: query register: query_ansible_match_rule_1 - name: Asserts query tasks - assert: + ansible.builtin.assert: that: - query_all_match_rule is not changed - query_all_match_rule.current|length >= 2 @@ -103,24 +103,24 @@ - query_ansible_match_rule_1.current.0.rtctrlSubjP.attributes.name == "ansible_match_rule_1" - name: Remove match rule profile for l3out (check_mode) - aci_match_rule: &match_rule_absent + cisco.aci.aci_match_rule: &match_rule_absent <<: *aci_match_rule_present state: absent check_mode: true register: cm_remove_match_rule - name: Remove match rule profile for l3out (normal_mode) - aci_match_rule: + cisco.aci.aci_match_rule: <<: *match_rule_absent register: nm_remove_match_rule - name: Remove match rule profile for l3out again - testing previous Removal - aci_match_rule: + cisco.aci.aci_match_rule: <<: *match_rule_absent register: nm_remove_match_rule_idempotency - name: Asserts deletion tasks - assert: + ansible.builtin.assert: that: - cm_remove_match_rule is changed - cm_remove_match_rule.proposed == {} @@ -131,6 +131,6 @@ - nm_remove_match_rule_idempotency.previous == [] - name: Remove the ansible_tenant - cleanup before ending tests - aci_tenant: + cisco.aci.aci_tenant: <<: *aci_tenant_present state: absent diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_netflow_exporter_policy/aliases b/ansible_collections/cisco/aci/tests/integration/targets/aci_netflow_exporter_policy/aliases new file mode 100644 index 000000000..209b793f9 --- /dev/null +++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_netflow_exporter_policy/aliases @@ -0,0 +1,2 @@ +# No ACI simulator yet, so not enabled +# unsupported diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_netflow_exporter_policy/tasks/main.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_netflow_exporter_policy/tasks/main.yml new file mode 100644 index 000000000..a5b58cb39 --- /dev/null +++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_netflow_exporter_policy/tasks/main.yml @@ -0,0 +1,337 @@ +# Test code for the ACI modules +# Copyright: (c) 2023, Gaspard Micol (@gmicol) + +# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) + +- name: Test that we have an ACI APIC host, ACI username and ACI password + ansible.builtin.fail: + msg: 'Please define the following variables: aci_hostname, aci_username and aci_password.' + when: aci_hostname is not defined or aci_username is not defined or aci_password is not defined + +- name: Set vars + ansible.builtin.set_fact: + aci_info: &aci_info + host: "{{ aci_hostname }}" + username: "{{ aci_username }}" + password: "{{ aci_password }}" + validate_certs: '{{ aci_validate_certs | default(false) }}' + use_ssl: '{{ aci_use_ssl | default(true) }}' + use_proxy: '{{ aci_use_proxy | default(true) }}' + output_level: '{{ aci_output_level | default("info") }}' + +# CLEAN ENVIRONMENT BEFORE TESTS +- name: Remove the ansible_tenant + cisco.aci.aci_tenant: &aci_tenant_absent + <<: *aci_info + tenant: ansible_tenant + state: absent + +- name: Verify Cloud and Non-Cloud Sites in use. + ansible.builtin.include_tasks: ../../../../../../integration/targets/aci_cloud_provider/tasks/main.yml + +- name: Execute tasks only for non-cloud sites + when: query_cloud.current == [] # This condition will execute only non-cloud sites + block: # block specifies execution of tasks within, based on conditions + - name: Add a new tenant + cisco.aci.aci_tenant: &aci_tenant_present + <<: *aci_info + tenant: ansible_tenant + description: Ansible tenant + state: present + + - name: Add a new VRF + cisco.aci.aci_vrf: + <<: *aci_info + tenant: ansible_tenant + vrf: ansible_vrf + description: ansible VRF for ansible_tenant tenant + state: present + + - name: Add a new Application Profile + cisco.aci.aci_ap: + <<: *aci_info + tenant: ansible_tenant + ap: ansible_ap + description: ansible Application Profile for ansible_tenant tenant + state: present + + - name: Add a new EPG + cisco.aci.aci_epg: + <<: *aci_info + tenant: ansible_tenant + ap: ansible_ap + epg: ansible_epg + description: ansible EPG for ansible_ap Application Profile + state: present + + - name: Add a new L3Out + cisco.aci.aci_l3out: + <<: *aci_info + tenant: ansible_tenant + vrf: ansible_vrf + domain: ansible_dom + l3out: ansible_l3out + description: ansible L3Out for ansible_tenant tenant + state: present + + - name: Add a new External EPG + cisco.aci.aci_l3out_extepg: + <<: *aci_info + tenant: ansible_tenant + extepg: ansible_extepg + l3out: ansible_l3out + description: ansible External EPG for ansible_l3out L3Out + state: present + + # CREATE NETFLOW EXPORTER POLICY + - name: Add a Netflow Exporter policy (check_mode) + cisco.aci.aci_netflow_exporter_policy: &aci_netflow_exporter_policy_present + <<: *aci_info + tenant: ansible_tenant + netflow_exporter_policy: ansible_netflow_exporter_policy_1 + description: Netflow Exporter policy 1 for ansible_tenant tenant + dscp: AF12 + destination_address: 11.11.11.1 + destination_port: smtp + source_ip_type: inband_management_ip + associated_epg: + tenant: ansible_tenant + ap: ansible_ap + epg: ansible_epg + state: present + associated_vrf: + tenant: ansible_tenant + vrf: ansible_vrf + check_mode: true + register: cm_add_netflow_exporter_policy + + - name: Add a Netflow Exporter policy (normal_mode) + cisco.aci.aci_netflow_exporter_policy: + <<: *aci_netflow_exporter_policy_present + register: nm_add_netflow_exporter_policy + + - name: Add the first Netflow Exporter policy again - testing idempotency + cisco.aci.aci_netflow_exporter_policy: + <<: *aci_netflow_exporter_policy_present + register: nm_add_netflow_exporter_policy_idempotency + + - name: Add a second Netflow Exporter policy (normal_mode) + cisco.aci.aci_netflow_exporter_policy: &aci_netflow_exporter_policy_2_present + <<: *aci_info + tenant: ansible_tenant + netflow_exporter_policy: ansible_netflow_exporter_policy_2 + description: Netflow Exporter policy 2 for ansible_tenant tenant + dscp: CS2 + destination_address: 11.11.11.2 + destination_port: https + custom_source_address: 12.12.12.2/12 + associated_extepg: + tenant: ansible_tenant + l3out: ansible_l3out + extepg: ansible_extepg + state: present + register: nm_add_netflow_exporter_policy_2 + + - name: Asserts for Netflow Exporter policy creation tasks + ansible.builtin.assert: + that: + - cm_add_netflow_exporter_policy is changed + - cm_add_netflow_exporter_policy.previous == [] + - cm_add_netflow_exporter_policy.current == [] + - cm_add_netflow_exporter_policy.proposed.netflowExporterPol.attributes.name == "ansible_netflow_exporter_policy_1" + - cm_add_netflow_exporter_policy.proposed.netflowExporterPol.attributes.dscp == "AF12" + - cm_add_netflow_exporter_policy.proposed.netflowExporterPol.attributes.dstAddr == "11.11.11.1" + - cm_add_netflow_exporter_policy.proposed.netflowExporterPol.attributes.dstPort == "smtp" + - cm_add_netflow_exporter_policy.proposed.netflowExporterPol.attributes.sourceIpType == "inband-mgmt-ip" + - cm_add_netflow_exporter_policy.proposed.netflowExporterPol.children.0.netflowRsExporterToCtx.attributes.tDn == "uni/tn-ansible_tenant/ctx-ansible_vrf" + - cm_add_netflow_exporter_policy.proposed.netflowExporterPol.children.1.netflowRsExporterToEPg.attributes.tDn == "uni/tn-ansible_tenant/ap-ansible_ap/epg-ansible_epg" + - nm_add_netflow_exporter_policy is changed + - nm_add_netflow_exporter_policy.previous == [] + - nm_add_netflow_exporter_policy.current.0.netflowExporterPol.attributes.name == "ansible_netflow_exporter_policy_1" + - nm_add_netflow_exporter_policy.current.0.netflowExporterPol.attributes.dscp == "AF12" + - nm_add_netflow_exporter_policy.current.0.netflowExporterPol.attributes.dstAddr == "11.11.11.1" + - nm_add_netflow_exporter_policy.current.0.netflowExporterPol.attributes.dstPort == "smtp" + - nm_add_netflow_exporter_policy.current.0.netflowExporterPol.attributes.sourceIpType == "inband-mgmt-ip" + - nm_add_netflow_exporter_policy.current.0.netflowExporterPol.attributes.srcAddr == "0.0.0.0" + - nm_add_netflow_exporter_policy.current.0.netflowExporterPol.children.0.netflowRsExporterToCtx.attributes.tDn == "uni/tn-ansible_tenant/ctx-ansible_vrf" + - nm_add_netflow_exporter_policy.current.0.netflowExporterPol.children.1.netflowRsExporterToEPg.attributes.tDn == "uni/tn-ansible_tenant/ap-ansible_ap/epg-ansible_epg" + - nm_add_netflow_exporter_policy_idempotency is not changed + - nm_add_netflow_exporter_policy_idempotency.current.0.netflowExporterPol.attributes.name == "ansible_netflow_exporter_policy_1" + - nm_add_netflow_exporter_policy_idempotency.current.0.netflowExporterPol.attributes.dscp == "AF12" + - nm_add_netflow_exporter_policy_idempotency.current.0.netflowExporterPol.attributes.dstAddr == "11.11.11.1" + - nm_add_netflow_exporter_policy_idempotency.current.0.netflowExporterPol.attributes.dstPort == "smtp" + - nm_add_netflow_exporter_policy_idempotency.current.0.netflowExporterPol.attributes.sourceIpType == "inband-mgmt-ip" + - nm_add_netflow_exporter_policy_idempotency.current.0.netflowExporterPol.attributes.srcAddr == "0.0.0.0" + - nm_add_netflow_exporter_policy_idempotency.current.0.netflowExporterPol.children.0.netflowRsExporterToCtx.attributes.tDn == "uni/tn-ansible_tenant/ctx-ansible_vrf" + - nm_add_netflow_exporter_policy_idempotency.current.0.netflowExporterPol.children.1.netflowRsExporterToEPg.attributes.tDn == "uni/tn-ansible_tenant/ap-ansible_ap/epg-ansible_epg" + - nm_add_netflow_exporter_policy_2 is changed + - nm_add_netflow_exporter_policy_2.previous == [] + - nm_add_netflow_exporter_policy_2.current.0.netflowExporterPol.attributes.name == "ansible_netflow_exporter_policy_2" + - nm_add_netflow_exporter_policy_2.current.0.netflowExporterPol.attributes.dscp == "CS2" + - nm_add_netflow_exporter_policy_2.current.0.netflowExporterPol.attributes.dstAddr == "11.11.11.2" + - nm_add_netflow_exporter_policy_2.current.0.netflowExporterPol.attributes.dstPort == "https" + - nm_add_netflow_exporter_policy_2.current.0.netflowExporterPol.attributes.sourceIpType == "custom-src-ip" + - nm_add_netflow_exporter_policy_2.current.0.netflowExporterPol.attributes.srcAddr == "12.12.12.2/12" + - nm_add_netflow_exporter_policy_2.current.0.netflowExporterPol.children.0.netflowRsExporterToEPg.attributes.tDn == "uni/tn-ansible_tenant/out-ansible_l3out/instP-ansible_extepg" + + # QUERY NETFLOW EXPORTER POLICY + - name: Query all Netflow Exporter policies + cisco.aci.aci_netflow_exporter_policy: + <<: *aci_info + state: query + register: query_all_netflow_exporter_policy + + - name: Query ansible_netflow_exporter_policy_1 + cisco.aci.aci_netflow_exporter_policy: + <<: *aci_netflow_exporter_policy_present + state: query + register: query_ansible_netflow_exporter_policy_1 + + - name: Asserts query tasks + ansible.builtin.assert: + that: + - query_all_netflow_exporter_policy is not changed + - query_all_netflow_exporter_policy.current|length >= 2 + - query_ansible_netflow_exporter_policy_1 is not changed + - query_ansible_netflow_exporter_policy_1.current|length == 1 + - query_ansible_netflow_exporter_policy_1.current.0.netflowExporterPol.attributes.name == "ansible_netflow_exporter_policy_1" + - query_ansible_netflow_exporter_policy_1.current.0.netflowExporterPol.attributes.dscp == "AF12" + - query_ansible_netflow_exporter_policy_1.current.0.netflowExporterPol.attributes.dstAddr == "11.11.11.1" + - query_ansible_netflow_exporter_policy_1.current.0.netflowExporterPol.attributes.dstPort == "smtp" + - query_ansible_netflow_exporter_policy_1.current.0.netflowExporterPol.attributes.sourceIpType == "inband-mgmt-ip" + - query_ansible_netflow_exporter_policy_1.current.0.netflowExporterPol.attributes.srcAddr == "0.0.0.0" + - query_ansible_netflow_exporter_policy_1.current.0.netflowExporterPol.children.0.netflowRsExporterToCtx.attributes.tDn == "uni/tn-ansible_tenant/ctx-ansible_vrf" + - query_ansible_netflow_exporter_policy_1.current.0.netflowExporterPol.children.1.netflowRsExporterToEPg.attributes.tDn == "uni/tn-ansible_tenant/ap-ansible_ap/epg-ansible_epg" + + #REMOVE ASSOCIATED EPG/EXTERNAL EPG FROM NETFLOW EXPORTER POLICIES + - name: Remove associated EPG from first Netflow Exporter policy (check_mode) + cisco.aci.aci_netflow_exporter_policy: &aci_netflow_exporter_policy_remove_epg + <<: *aci_netflow_exporter_policy_present + associated_epg: {} + associated_vrf: {} + check_mode: true + register: cm_remove_epg_netflow_exporter_policy + + - name: Remove associated EPG from first Netflow Exporter policy (normal_mode) + cisco.aci.aci_netflow_exporter_policy: + <<: *aci_netflow_exporter_policy_remove_epg + register: nm_remove_epg_netflow_exporter_policy + + - name: Remove associated EPG from first Netflow Exporter policy again - testing idempotency + cisco.aci.aci_netflow_exporter_policy: + <<: *aci_netflow_exporter_policy_remove_epg + register: nm_remove_epg_netflow_exporter_policy_idempotency + + - name: Remove associated external EPG from second Netflow Exporter policy (normal_mode) + cisco.aci.aci_netflow_exporter_policy: &aci_netflow_exporter_policy_2_remove_extepg + <<: *aci_netflow_exporter_policy_2_present + associated_extepg: {} + register: nm_remove_extepg_netflow_exporter_policy_2 + + - name: Remove associated external EPG from second Netflow Exporter policy again - testing idempotency + cisco.aci.aci_netflow_exporter_policy: + <<: *aci_netflow_exporter_policy_2_remove_extepg + register: nm_remove_extepg_netflow_exporter_policy_2_idempotency + + - name: Asserts for associated EPGs removal tasks + ansible.builtin.assert: + that: + - cm_remove_epg_netflow_exporter_policy is changed + - cm_remove_epg_netflow_exporter_policy.current == cm_remove_epg_netflow_exporter_policy.previous + - cm_remove_epg_netflow_exporter_policy.proposed.netflowExporterPol.children.0.netflowRsExporterToCtx.attributes.status == "deleted" + - cm_remove_epg_netflow_exporter_policy.proposed.netflowExporterPol.children.1.netflowRsExporterToEPg.attributes.status == "deleted" + - nm_remove_epg_netflow_exporter_policy is changed + - nm_remove_epg_netflow_exporter_policy.proposed.netflowExporterPol.children.0.netflowRsExporterToCtx.attributes.status == "deleted" + - nm_remove_epg_netflow_exporter_policy.proposed.netflowExporterPol.children.1.netflowRsExporterToEPg.attributes.status == "deleted" + - '"children" not in nm_remove_epg_netflow_exporter_policy.current.0.netflowExporterPol' + - nm_remove_epg_netflow_exporter_policy_idempotency is not changed + - '"children" not in nm_remove_epg_netflow_exporter_policy_idempotency.current.0.netflowExporterPol' + - nm_remove_extepg_netflow_exporter_policy_2 is changed + - nm_remove_extepg_netflow_exporter_policy_2.proposed.netflowExporterPol.children.0.netflowRsExporterToEPg.attributes.status == "deleted" + - '"children" not in nm_remove_extepg_netflow_exporter_policy_2.current.0.netflowExporterPol' + - nm_remove_extepg_netflow_exporter_policy_2_idempotency is not changed + - '"children" not in nm_remove_extepg_netflow_exporter_policy_2_idempotency.current.0.netflowExporterPol' + + #UPDATE NETFLOW EXPORTER POLICY + - name: Update first Netflow Exporter policy (check_mode) + cisco.aci.aci_netflow_exporter_policy: &aci_netflow_exporter_policy_update + <<: *aci_netflow_exporter_policy_remove_epg + dscp: AF13 + destination_address: 11.11.11.3 + destination_port: http + source_ip_type: out_of_band_management_ip + description: Updated description for first ansible Netflow Exporter policy + check_mode: true + register: cm_update_netflow_exporter_policy + + - name: Update first Netflow Exporter policy (normal_mode) + cisco.aci.aci_netflow_exporter_policy: + <<: *aci_netflow_exporter_policy_update + register: nm_update_netflow_exporter_policy + + - name: Update first Netflow Exporter policy again - testing idempotency + cisco.aci.aci_netflow_exporter_policy: + <<: *aci_netflow_exporter_policy_update + register: nm_udpate_netflow_exporter_policy_idempotency + + - name: Asserts for Netflow Exporter policy update tasks + ansible.builtin.assert: + that: + - cm_update_netflow_exporter_policy is changed + - cm_update_netflow_exporter_policy.previous == cm_update_netflow_exporter_policy.current + - cm_update_netflow_exporter_policy.proposed.netflowExporterPol.attributes.dscp == "AF13" + - cm_update_netflow_exporter_policy.proposed.netflowExporterPol.attributes.dstAddr == "11.11.11.3" + - cm_update_netflow_exporter_policy.proposed.netflowExporterPol.attributes.dstPort == "http" + - cm_update_netflow_exporter_policy.proposed.netflowExporterPol.attributes.sourceIpType == "oob-mgmt-ip" + - cm_update_netflow_exporter_policy.proposed.netflowExporterPol.attributes.descr == "Updated description for first ansible Netflow Exporter policy" + - nm_update_netflow_exporter_policy is changed + - nm_update_netflow_exporter_policy.current.0.netflowExporterPol.attributes.dscp == "AF13" + - nm_update_netflow_exporter_policy.current.0.netflowExporterPol.attributes.dstAddr == "11.11.11.3" + - nm_update_netflow_exporter_policy.current.0.netflowExporterPol.attributes.dstPort == "http" + - nm_update_netflow_exporter_policy.current.0.netflowExporterPol.attributes.sourceIpType == "oob-mgmt-ip" + - nm_update_netflow_exporter_policy.current.0.netflowExporterPol.attributes.srcAddr == "0.0.0.0" + - nm_update_netflow_exporter_policy.current.0.netflowExporterPol.attributes.descr == "Updated description for first ansible Netflow Exporter policy" + - nm_udpate_netflow_exporter_policy_idempotency is not changed + - nm_udpate_netflow_exporter_policy_idempotency.current.0.netflowExporterPol.attributes.dstAddr == "11.11.11.3" + - nm_udpate_netflow_exporter_policy_idempotency.current.0.netflowExporterPol.attributes.dstPort == "http" + - nm_udpate_netflow_exporter_policy_idempotency.current.0.netflowExporterPol.attributes.sourceIpType == "oob-mgmt-ip" + - nm_udpate_netflow_exporter_policy_idempotency.current.0.netflowExporterPol.attributes.srcAddr == "0.0.0.0" + - nm_udpate_netflow_exporter_policy_idempotency.current.0.netflowExporterPol.attributes.descr == "Updated description for first ansible Netflow Exporter policy" + + # DELETE NETFLOW EXPORTER POLICY + - name: Remove Netflow Exporter policy (check_mode) + cisco.aci.aci_netflow_exporter_policy: &netflow_exporter_policy_absent + <<: *aci_netflow_exporter_policy_update + state: absent + check_mode: true + register: cm_remove_netflow_exporter_policy + + - name: Remove Netflow Exporter policy (normal_mode) + cisco.aci.aci_netflow_exporter_policy: + <<: *netflow_exporter_policy_absent + register: nm_remove_netflow_exporter_policy + + - name: Remove Netflow Exporter policy - testing idempotency + cisco.aci.aci_netflow_exporter_policy: + <<: *netflow_exporter_policy_absent + register: nm_remove_netflow_exporter_policy_idempotency + + - name: Asserts deletion tasks + ansible.builtin.assert: + that: + - cm_remove_netflow_exporter_policy is changed + - cm_remove_netflow_exporter_policy.current == cm_remove_netflow_exporter_policy.previous + - cm_remove_netflow_exporter_policy.proposed == {} + - nm_remove_netflow_exporter_policy is changed + - nm_remove_netflow_exporter_policy.previous != [] + - nm_remove_netflow_exporter_policy.proposed == {} + - nm_remove_netflow_exporter_policy.current == [] + - nm_remove_netflow_exporter_policy_idempotency is not changed + - nm_remove_netflow_exporter_policy_idempotency.previous == [] + - nm_remove_netflow_exporter_policy_idempotency.current == [] + + # CLEAN ENVIRONMENT BEFORE ENDING TESTS + - name: Remove the ansible_tenant - cleanup before ending tests + cisco.aci.aci_tenant: + <<: *aci_tenant_present + state: absent diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_netflow_monitor_policy/aliases b/ansible_collections/cisco/aci/tests/integration/targets/aci_netflow_monitor_policy/aliases new file mode 100644 index 000000000..209b793f9 --- /dev/null +++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_netflow_monitor_policy/aliases @@ -0,0 +1,2 @@ +# No ACI simulator yet, so not enabled +# unsupported diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_netflow_monitor_policy/tasks/main.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_netflow_monitor_policy/tasks/main.yml new file mode 100644 index 000000000..ada9d5ad8 --- /dev/null +++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_netflow_monitor_policy/tasks/main.yml @@ -0,0 +1,193 @@ +# Test code for the ACI modules +# Copyright: (c) 2023, Gaspard Micol (@gmicol) + +# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) + +- name: Test that we have an ACI APIC host, ACI username and ACI password + ansible.builtin.fail: + msg: 'Please define the following variables: aci_hostname, aci_username and aci_password.' + when: aci_hostname is not defined or aci_username is not defined or aci_password is not defined + +- name: Set vars + ansible.builtin.set_fact: + aci_info: &aci_info + host: "{{ aci_hostname }}" + username: "{{ aci_username }}" + password: "{{ aci_password }}" + validate_certs: '{{ aci_validate_certs | default(false) }}' + use_ssl: '{{ aci_use_ssl | default(true) }}' + use_proxy: '{{ aci_use_proxy | default(true) }}' + output_level: '{{ aci_output_level | default("info") }}' + +# CLEAN ENVIRONMENT BEFORE TESTS +- name: Remove the ansible_tenant + cisco.aci.aci_tenant: &aci_tenant_absent + <<: *aci_info + tenant: ansible_tenant + state: absent + +- name: Verify Cloud and Non-Cloud Sites in use. + ansible.builtin.include_tasks: ../../../../../../integration/targets/aci_cloud_provider/tasks/main.yml + +- name: Execute tasks only for non-cloud sites + when: query_cloud.current == [] # This condition will execute only non-cloud sites + block: # block specifies execution of tasks within, based on conditions + - name: Add a new tenant + cisco.aci.aci_tenant: &aci_tenant_present + <<: *aci_info + tenant: ansible_tenant + description: Ansible tenant + state: present + + - name: Add a Netflow Record policy + cisco.aci.aci_netflow_record_policy: + <<: *aci_info + tenant: ansible_tenant + netflow_record_policy: ansible_netflow_record_policy + description: Netflow Record policy for ansible_tenant tenant + state: present + + # CREATE NETFLOW MONITOR POLICY + - name: Add a Netflow Monitor policy (check_mode) + cisco.aci.aci_netflow_monitor_policy: &aci_netflow_monitor_policy_present + <<: *aci_info + tenant: ansible_tenant + netflow_monitor_policy: ansible_netflow_monitor_policy_1 + netflow_record_policy: ansible_netflow_record_policy + description: Netflow Monitor policy 1 for ansible_tenant tenant + state: present + check_mode: true + register: cm_add_netflow_monitor_policy + + - name: Add a Netflow Monitor policy (normal_mode) + cisco.aci.aci_netflow_monitor_policy: + <<: *aci_netflow_monitor_policy_present + register: nm_add_netflow_monitor_policy + + - name: Add the first Netflow Monitor policy again - testing idempotency + cisco.aci.aci_netflow_monitor_policy: + <<: *aci_netflow_monitor_policy_present + register: nm_add_netflow_monitor_policy_idempotency + + - name: Add a second Netflow Monitor policy (normal_mode) + cisco.aci.aci_netflow_monitor_policy: + <<: *aci_info + tenant: ansible_tenant + netflow_monitor_policy: ansible_netflow_monitor_policy_2 + description: Netflow Monitor policy 2 for ansible_tenant tenant + state: present + register: nm_add_netflow_monitor_policy_2 + + - name: Asserts for Netflow Monitor policy creation tasks + ansible.builtin.assert: + that: + - cm_add_netflow_monitor_policy is changed + - cm_add_netflow_monitor_policy.previous == [] + - cm_add_netflow_monitor_policy.current == [] + - cm_add_netflow_monitor_policy.proposed.netflowMonitorPol.attributes.name == "ansible_netflow_monitor_policy_1" + - cm_add_netflow_monitor_policy.proposed.netflowMonitorPol.children.0.netflowRsMonitorToRecord.attributes.tnNetflowRecordPolName == "ansible_netflow_record_policy" + - nm_add_netflow_monitor_policy is changed + - nm_add_netflow_monitor_policy.previous == [] + - nm_add_netflow_monitor_policy.current.0.netflowMonitorPol.attributes.name == "ansible_netflow_monitor_policy_1" + - nm_add_netflow_monitor_policy.current.0.netflowMonitorPol.children.0.netflowRsMonitorToRecord.attributes.tnNetflowRecordPolName == "ansible_netflow_record_policy" + - nm_add_netflow_monitor_policy_idempotency is not changed + - nm_add_netflow_monitor_policy_idempotency.current.0.netflowMonitorPol.attributes.name == "ansible_netflow_monitor_policy_1" + - nm_add_netflow_monitor_policy_idempotency.current.0.netflowMonitorPol.children.0.netflowRsMonitorToRecord.attributes.tnNetflowRecordPolName == "ansible_netflow_record_policy" + - nm_add_netflow_monitor_policy_2 is changed + - nm_add_netflow_monitor_policy_2.previous == [] + - nm_add_netflow_monitor_policy_2.current.0.netflowMonitorPol.attributes.name == "ansible_netflow_monitor_policy_2" + + # QUERY NETFLOW MONITOR POLICY + - name: Query all Netflow Monitor policies + cisco.aci.aci_netflow_monitor_policy: + <<: *aci_info + state: query + register: query_all_netflow_monitor_policy + + - name: Query ansible_netflow_monitor_policy_1 + cisco.aci.aci_netflow_monitor_policy: + <<: *aci_netflow_monitor_policy_present + state: query + register: query_ansible_netflow_monitor_policy_1 + + - name: Asserts query tasks + ansible.builtin.assert: + that: + - query_all_netflow_monitor_policy is not changed + - query_all_netflow_monitor_policy.current|length >= 2 + - query_ansible_netflow_monitor_policy_1 is not changed + - query_ansible_netflow_monitor_policy_1.current|length == 1 + - query_ansible_netflow_monitor_policy_1.current.0.netflowMonitorPol.attributes.name == "ansible_netflow_monitor_policy_1" + - query_ansible_netflow_monitor_policy_1.current.0.netflowMonitorPol.children.0.netflowRsMonitorToRecord.attributes.tDn == "uni/tn-ansible_tenant/recordpol-ansible_netflow_record_policy" + + # UPDATE NETFLOW MONITOR POLICY + - name: Add a Netflow Monitor policy (check_mode) + cisco.aci.aci_netflow_monitor_policy: &aci_netflow_monitor_policy_update + <<: *aci_netflow_monitor_policy_present + netflow_record_policy: "" + description: Updated Netflow Monitor policy 1 for ansible_tenant tenant + state: present + check_mode: true + register: cm_update_netflow_monitor_policy + + - name: Add a Netflow Monitor policy (normal_mode) + cisco.aci.aci_netflow_monitor_policy: + <<: *aci_netflow_monitor_policy_update + register: nm_update_netflow_monitor_policy + + - name: Add the first Netflow Monitor policy again - testing idempotency + cisco.aci.aci_netflow_monitor_policy: + <<: *aci_netflow_monitor_policy_update + register: nm_update_netflow_monitor_policy_idempotency + + - name: Asserts for Netflow Monitor policy update tasks + ansible.builtin.assert: + that: + - cm_update_netflow_monitor_policy is changed + - cm_update_netflow_monitor_policy.previous == cm_update_netflow_monitor_policy.current + - cm_update_netflow_monitor_policy.proposed.netflowMonitorPol.attributes.descr == "Updated Netflow Monitor policy 1 for ansible_tenant tenant" + - cm_update_netflow_monitor_policy.proposed.netflowMonitorPol.children.0.netflowRsMonitorToRecord.attributes.tnNetflowRecordPolName == "" + - nm_update_netflow_monitor_policy is changed + - nm_update_netflow_monitor_policy.current.0.netflowMonitorPol.attributes.descr == "Updated Netflow Monitor policy 1 for ansible_tenant tenant" + - nm_update_netflow_monitor_policy.current.0.netflowMonitorPol.children.0.netflowRsMonitorToRecord.attributes.tnNetflowRecordPolName == "" + - nm_update_netflow_monitor_policy_idempotency is not changed + - nm_update_netflow_monitor_policy_idempotency.current.0.netflowMonitorPol.attributes.descr == "Updated Netflow Monitor policy 1 for ansible_tenant tenant" + - nm_update_netflow_monitor_policy_idempotency.current.0.netflowMonitorPol.children.0.netflowRsMonitorToRecord.attributes.tnNetflowRecordPolName == "" + + # DELETE NETFLOW MONITOR POLICY + - name: Remove Netflow Monitor policy (check_mode) + cisco.aci.aci_netflow_monitor_policy: &netflow_monitor_policy_absent + <<: *aci_netflow_monitor_policy_update + state: absent + check_mode: true + register: cm_remove_netflow_monitor_policy + + - name: Remove Netflow Monitor policy (normal_mode) + cisco.aci.aci_netflow_monitor_policy: + <<: *netflow_monitor_policy_absent + register: nm_remove_netflow_monitor_policy + + - name: Remove Netflow Monitor policy - testing idempotency + cisco.aci.aci_netflow_monitor_policy: + <<: *netflow_monitor_policy_absent + register: nm_remove_netflow_monitor_policy_idempotency + + - name: Asserts deletion tasks + ansible.builtin.assert: + that: + - cm_remove_netflow_monitor_policy is changed + - cm_remove_netflow_monitor_policy.current == cm_remove_netflow_monitor_policy.previous + - cm_remove_netflow_monitor_policy.proposed == {} + - nm_remove_netflow_monitor_policy is changed + - nm_remove_netflow_monitor_policy.previous != [] + - nm_remove_netflow_monitor_policy.proposed == {} + - nm_remove_netflow_monitor_policy.current == [] + - nm_remove_netflow_monitor_policy_idempotency is not changed + - nm_remove_netflow_monitor_policy_idempotency.previous == [] + - nm_remove_netflow_monitor_policy_idempotency.current == [] + + # CLEAN ENVIRONMENT BEFORE ENDING TESTS + - name: Remove the ansible_tenant - cleanup before ending tests + cisco.aci.aci_tenant: + <<: *aci_tenant_present + state: absent diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_netflow_monitor_to_exporter/aliases b/ansible_collections/cisco/aci/tests/integration/targets/aci_netflow_monitor_to_exporter/aliases new file mode 100644 index 000000000..209b793f9 --- /dev/null +++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_netflow_monitor_to_exporter/aliases @@ -0,0 +1,2 @@ +# No ACI simulator yet, so not enabled +# unsupported diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_netflow_monitor_to_exporter/tasks/main.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_netflow_monitor_to_exporter/tasks/main.yml new file mode 100644 index 000000000..7ee25f61c --- /dev/null +++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_netflow_monitor_to_exporter/tasks/main.yml @@ -0,0 +1,172 @@ +# Test code for the ACI modules +# Copyright: (c) 2023, Gaspard Micol (@gmicol) + +# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) + +- name: Test that we have an ACI APIC host, ACI username and ACI password + ansible.builtin.fail: + msg: 'Please define the following variables: aci_hostname, aci_username and aci_password.' + when: aci_hostname is not defined or aci_username is not defined or aci_password is not defined + +- name: Set vars + ansible.builtin.set_fact: + aci_info: &aci_info + host: "{{ aci_hostname }}" + username: "{{ aci_username }}" + password: "{{ aci_password }}" + validate_certs: '{{ aci_validate_certs | default(false) }}' + use_ssl: '{{ aci_use_ssl | default(true) }}' + use_proxy: '{{ aci_use_proxy | default(true) }}' + output_level: '{{ aci_output_level | default("info") }}' + +# CLEAN ENVIRONMENT BEFORE TESTS +- name: Remove the ansible_tenant + cisco.aci.aci_tenant: &aci_tenant_absent + <<: *aci_info + tenant: ansible_tenant + state: absent + +- name: Verify Cloud and Non-Cloud Sites in use. + ansible.builtin.include_tasks: ../../../../../../integration/targets/aci_cloud_provider/tasks/main.yml + +- name: Execute tasks only for non-cloud sites + when: query_cloud.current == [] # This condition will execute only non-cloud sites + block: # block specifies execution of tasks within, based on conditions + - name: Add a new tenant + cisco.aci.aci_tenant: &aci_tenant_present + <<: *aci_info + tenant: ansible_tenant + description: Ansible tenant + state: present + + - name: Add a Netflow Monitor policy + cisco.aci.aci_netflow_monitor_policy: + <<: *aci_info + tenant: ansible_tenant + netflow_monitor_policy: ansible_netflow_monitor_policy + description: Netflow Monitor policy for ansible_tenant tenant + state: present + + - name: Add a first Netflow Exporter policy + cisco.aci.aci_netflow_exporter_policy: + <<: *aci_info + tenant: ansible_tenant + netflow_exporter_policy: ansible_netflow_exporter_policy_1 + description: Netflow Exporter policy 1 for ansible_tenant tenant + destination_address: 11.11.11.1 + destination_port: https + state: present + + - name: Add a second Netflow Exporter policy + cisco.aci.aci_netflow_exporter_policy: + <<: *aci_info + tenant: ansible_tenant + netflow_exporter_policy: ansible_netflow_exporter_policy_2 + description: Netflow Exporter policy 2 for ansible_tenant tenant + destination_address: 12.12.12.2 + destination_port: http + state: present + + # CREATE NETFLOW MONITOR TO EXPORTER + - name: Add a first Netflow Exporter policy to the Netflow Monitor policy (check_mode) + cisco.aci.aci_netflow_monitor_to_exporter: &aci_netflow_monitor_to_exporter_present + <<: *aci_info + tenant: ansible_tenant + netflow_monitor_policy: ansible_netflow_monitor_policy + netflow_exporter_policy: ansible_netflow_exporter_policy_1 + state: present + check_mode: true + register: cm_add_netflow_monitor_to_exporter + + - name: Add a first Netflow Exporter policy to the Netflow Monitor policy (normal_mode) + cisco.aci.aci_netflow_monitor_to_exporter: + <<: *aci_netflow_monitor_to_exporter_present + register: nm_add_netflow_monitor_to_exporter + + - name: Add the first Netflow Monitor policy again - testing idempotency + cisco.aci.aci_netflow_monitor_to_exporter: + <<: *aci_netflow_monitor_to_exporter_present + register: nm_add_netflow_monitor_to_exporter_idempotency + + - name: Add a second Netflow Monitor policy (normal_mode) + cisco.aci.aci_netflow_monitor_to_exporter: + <<: *aci_info + tenant: ansible_tenant + netflow_monitor_policy: ansible_netflow_monitor_policy + netflow_exporter_policy: ansible_netflow_exporter_policy_2 + state: present + register: nm_add_netflow_monitor_to_exporter_2 + + - name: Asserts for Netflow Monitor policy creation tasks + ansible.builtin.assert: + that: + - cm_add_netflow_monitor_to_exporter is changed + - cm_add_netflow_monitor_to_exporter.previous == [] + - cm_add_netflow_monitor_to_exporter.current == [] + - cm_add_netflow_monitor_to_exporter.proposed.netflowRsMonitorToExporter.attributes.tnNetflowExporterPolName == "ansible_netflow_exporter_policy_1" + - nm_add_netflow_monitor_to_exporter is changed + - nm_add_netflow_monitor_to_exporter.previous == [] + - nm_add_netflow_monitor_to_exporter.current.0.netflowRsMonitorToExporter.attributes.tnNetflowExporterPolName == "ansible_netflow_exporter_policy_1" + - nm_add_netflow_monitor_to_exporter_idempotency is not changed + - nm_add_netflow_monitor_to_exporter_idempotency.current.0.netflowRsMonitorToExporter.attributes.tnNetflowExporterPolName == "ansible_netflow_exporter_policy_1" + - nm_add_netflow_monitor_to_exporter_2 is changed + - nm_add_netflow_monitor_to_exporter_2.previous == [] + - nm_add_netflow_monitor_to_exporter_2.current.0.netflowRsMonitorToExporter.attributes.tnNetflowExporterPolName == "ansible_netflow_exporter_policy_2" + + # QUERY NETFLOW MONITOR TO EXPORTER + - name: Query all Netflow Monitor to Exporter Associations + cisco.aci.aci_netflow_monitor_to_exporter: + <<: *aci_info + state: query + register: query_all_netflow_monitor_to_exporter + + - name: Query first Netflow Monitor to Exporter Association + cisco.aci.aci_netflow_monitor_to_exporter: + <<: *aci_netflow_monitor_to_exporter_present + state: query + register: query_ansible_netflow_monitor_policy_to_exporter + + - name: Asserts query tasks + ansible.builtin.assert: + that: + - query_all_netflow_monitor_to_exporter is not changed + - query_all_netflow_monitor_to_exporter.current|length >= 2 + - query_ansible_netflow_monitor_policy_to_exporter is not changed + - query_ansible_netflow_monitor_policy_to_exporter.current|length == 1 + - query_ansible_netflow_monitor_policy_to_exporter.current.0.netflowRsMonitorToExporter.attributes.tnNetflowExporterPolName == "ansible_netflow_exporter_policy_1" + + # DELETE NETFLOW MONITOR TO EXPORTER + - name: Remove first Netflow Exporter policy from the Netflow Monitor policy (check_mode) + cisco.aci.aci_netflow_monitor_to_exporter: &netflow_monitor_to_exporter_absent + <<: *aci_netflow_monitor_to_exporter_present + state: absent + check_mode: true + register: cm_remove_netflow_monitor_to_exporter + + - name: Remove first Netflow Exporter policy from the Netflow Monitor policy (normal_mode) + cisco.aci.aci_netflow_monitor_to_exporter: + <<: *netflow_monitor_to_exporter_absent + register: nm_remove_netflow_monitor_to_exporter + + - name: Remove first Netflow Exporter policy from the Netflow Monitor policy - testing idempotency + cisco.aci.aci_netflow_monitor_to_exporter: + <<: *netflow_monitor_to_exporter_absent + register: nm_remove_netflow_monitor_to_exporter_idempotency + + - name: Asserts deletion tasks + ansible.builtin.assert: + that: + - cm_remove_netflow_monitor_to_exporter is changed + - cm_remove_netflow_monitor_to_exporter.current == cm_remove_netflow_monitor_to_exporter.previous + - cm_remove_netflow_monitor_to_exporter.proposed == {} + - nm_remove_netflow_monitor_to_exporter is changed + - nm_remove_netflow_monitor_to_exporter.previous != [] + - nm_remove_netflow_monitor_to_exporter.current == [] + - nm_remove_netflow_monitor_to_exporter_idempotency is not changed + - nm_remove_netflow_monitor_to_exporter_idempotency.previous == [] + + # CLEAN ENVIRONMENT BEFORE ENDING TESTS + - name: Remove the ansible_tenant - cleanup before ending tests + cisco.aci.aci_tenant: + <<: *aci_tenant_present + state: absent diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_netflow_record_policy/aliases b/ansible_collections/cisco/aci/tests/integration/targets/aci_netflow_record_policy/aliases new file mode 100644 index 000000000..209b793f9 --- /dev/null +++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_netflow_record_policy/aliases @@ -0,0 +1,2 @@ +# No ACI simulator yet, so not enabled +# unsupported diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_netflow_record_policy/tasks/main.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_netflow_record_policy/tasks/main.yml new file mode 100644 index 000000000..0645e9159 --- /dev/null +++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_netflow_record_policy/tasks/main.yml @@ -0,0 +1,194 @@ +# Test code for the ACI modules +# Copyright: (c) 2023, Gaspard Micol (@gmicol) + +# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) + +- name: Test that we have an ACI APIC host, ACI username and ACI password + ansible.builtin.fail: + msg: 'Please define the following variables: aci_hostname, aci_username and aci_password.' + when: aci_hostname is not defined or aci_username is not defined or aci_password is not defined + +- name: Set vars + ansible.builtin.set_fact: + aci_info: &aci_info + host: "{{ aci_hostname }}" + username: "{{ aci_username }}" + password: "{{ aci_password }}" + validate_certs: '{{ aci_validate_certs | default(false) }}' + use_ssl: '{{ aci_use_ssl | default(true) }}' + use_proxy: '{{ aci_use_proxy | default(true) }}' + output_level: '{{ aci_output_level | default("info") }}' + +# CLEAN ENVIRONMENT BEFORE TESTS +- name: Remove the ansible_tenant + cisco.aci.aci_tenant: &aci_tenant_absent + <<: *aci_info + tenant: ansible_tenant + state: absent + +- name: Verify Cloud and Non-Cloud Sites in use. + ansible.builtin.include_tasks: ../../../../../../integration/targets/aci_cloud_provider/tasks/main.yml + +- name: Execute tasks only for non-cloud sites + when: query_cloud.current == [] # This condition will execute only non-cloud sites + block: # block specifies execution of tasks within, based on conditions + - name: Add a new tenant + cisco.aci.aci_tenant: &aci_tenant_present + <<: *aci_info + tenant: ansible_tenant + description: Ansible tenant + state: present + + # CREATE NETFLOW RECORD POLICY + - name: Add a Netflow Record policy (check_mode) + cisco.aci.aci_netflow_record_policy: &aci_netflow_record_policy_present + <<: *aci_info + tenant: ansible_tenant + netflow_record_policy: ansible_netflow_record_policy_1 + description: Netflow Record policy 1 for ansible_tenant tenant + collect: [sampler_id, bytes_counter] + match: [destination_ipv4_v6, source_ipv4_v6] + state: present + check_mode: true + register: cm_add_netflow_record_policy + + - name: Add a Netflow Record policy (normal_mode) + cisco.aci.aci_netflow_record_policy: + <<: *aci_netflow_record_policy_present + register: nm_add_netflow_record_policy + + - name: Add the first Netflow Record policy again - testing idempotency + cisco.aci.aci_netflow_record_policy: + <<: *aci_netflow_record_policy_present + register: nm_add_netflow_record_policy_idempotency + + - name: Add a second Netflow Record policy (normal_mode) + cisco.aci.aci_netflow_record_policy: + <<: *aci_info + tenant: ansible_tenant + netflow_record_policy: ansible_netflow_record_policy_2 + description: Netflow Record policy 2 for ansible_tenant tenant + state: present + register: nm_add_netflow_record_policy_2 + + - name: Asserts for Netflow Record policy creation tasks + ansible.builtin.assert: + that: + - cm_add_netflow_record_policy is changed + - cm_add_netflow_record_policy.previous == [] + - cm_add_netflow_record_policy.current == [] + - cm_add_netflow_record_policy.proposed.netflowRecordPol.attributes.name == "ansible_netflow_record_policy_1" + - cm_add_netflow_record_policy.proposed.netflowRecordPol.attributes.collect == "count-bytes,sampler-id" + - cm_add_netflow_record_policy.proposed.netflowRecordPol.attributes.match == "dst-ip,src-ip" + - nm_add_netflow_record_policy is changed + - nm_add_netflow_record_policy.previous == [] + - nm_add_netflow_record_policy.current.0.netflowRecordPol.attributes.name == "ansible_netflow_record_policy_1" + - nm_add_netflow_record_policy.current.0.netflowRecordPol.attributes.collect == "count-bytes,sampler-id" + - nm_add_netflow_record_policy.current.0.netflowRecordPol.attributes.match == "dst-ip,src-ip" + - nm_add_netflow_record_policy_idempotency is not changed + - nm_add_netflow_record_policy_idempotency.current.0.netflowRecordPol.attributes.name == "ansible_netflow_record_policy_1" + - nm_add_netflow_record_policy_idempotency.current.0.netflowRecordPol.attributes.collect == "count-bytes,sampler-id" + - nm_add_netflow_record_policy_idempotency.current.0.netflowRecordPol.attributes.match == "dst-ip,src-ip" + - nm_add_netflow_record_policy_2 is changed + - nm_add_netflow_record_policy_2.previous == [] + - nm_add_netflow_record_policy_2.current.0.netflowRecordPol.attributes.name == "ansible_netflow_record_policy_2" + - nm_add_netflow_record_policy_2.current.0.netflowRecordPol.attributes.collect == "src-intf" + - nm_add_netflow_record_policy_2.current.0.netflowRecordPol.attributes.match == "" + + # QUERY NETFLOW RECORD POLICY + - name: Query all Netflow Record policies + cisco.aci.aci_netflow_record_policy: + <<: *aci_info + state: query + register: query_all_netflow_record_policy + + - name: Query ansible_netflow_record_policy_1 + cisco.aci.aci_netflow_record_policy: + <<: *aci_netflow_record_policy_present + state: query + register: query_ansible_netflow_record_policy_1 + + - name: Asserts query tasks + ansible.builtin.assert: + that: + - query_all_netflow_record_policy is not changed + - query_all_netflow_record_policy.current|length >= 2 + - query_ansible_netflow_record_policy_1 is not changed + - query_ansible_netflow_record_policy_1.current|length == 1 + - query_ansible_netflow_record_policy_1.current.0.netflowRecordPol.attributes.name == "ansible_netflow_record_policy_1" + - query_ansible_netflow_record_policy_1.current.0.netflowRecordPol.attributes.collect == "count-bytes,sampler-id" + - query_ansible_netflow_record_policy_1.current.0.netflowRecordPol.attributes.match == "dst-ip,src-ip" + + #UPDATE NETFLOW RECORD POLICY + - name: Update first Netflow Record policy (check_mode) + cisco.aci.aci_netflow_record_policy: &aci_netflow_record_policy_update + <<: *aci_netflow_record_policy_present + collect: [pkts_counter, pkt_disposition] + match: [destination_ipv4, source_ipv4] + state: present + check_mode: true + register: cm_update_netflow_record_policy + + - name: Update first Netflow Record policy (normal_mode) + cisco.aci.aci_netflow_record_policy: + <<: *aci_netflow_record_policy_update + register: nm_update_netflow_record_policy + + - name: Update first Netflow Record policy again - testing idempotency + cisco.aci.aci_netflow_record_policy: + <<: *aci_netflow_record_policy_update + register: nm_udpate_netflow_record_policy_idempotency + + - name: Asserts for Netflow Record policy update tasks + ansible.builtin.assert: + that: + - cm_update_netflow_record_policy is changed + - cm_update_netflow_record_policy.previous == cm_update_netflow_record_policy.current + - cm_update_netflow_record_policy.proposed.netflowRecordPol.attributes.name == "ansible_netflow_record_policy_1" + - cm_update_netflow_record_policy.proposed.netflowRecordPol.attributes.collect == "count-pkts,pkt-disp" + - cm_update_netflow_record_policy.proposed.netflowRecordPol.attributes.match == "dst-ipv4,src-ipv4" + - nm_update_netflow_record_policy is changed + - nm_update_netflow_record_policy.current.0.netflowRecordPol.attributes.name == "ansible_netflow_record_policy_1" + - nm_update_netflow_record_policy.current.0.netflowRecordPol.attributes.collect == "count-pkts,pkt-disp" + - nm_update_netflow_record_policy.current.0.netflowRecordPol.attributes.match == "dst-ipv4,src-ipv4" + - nm_udpate_netflow_record_policy_idempotency is not changed + - nm_udpate_netflow_record_policy_idempotency.current.0.netflowRecordPol.attributes.name == "ansible_netflow_record_policy_1" + - nm_udpate_netflow_record_policy_idempotency.current.0.netflowRecordPol.attributes.collect == "count-pkts,pkt-disp" + - nm_udpate_netflow_record_policy_idempotency.current.0.netflowRecordPol.attributes.match == "dst-ipv4,src-ipv4" + + # DELETE NETFLOW RECORD POLICY + - name: Remove Netflow Record policy (check_mode) + cisco.aci.aci_netflow_record_policy: &netflow_record_policy_absent + <<: *aci_netflow_record_policy_update + state: absent + check_mode: true + register: cm_remove_netflow_record_policy + + - name: Remove Netflow Record policy (normal_mode) + cisco.aci.aci_netflow_record_policy: + <<: *netflow_record_policy_absent + register: nm_remove_netflow_record_policy + + - name: Remove Netflow Record policy - testing idempotency + cisco.aci.aci_netflow_record_policy: + <<: *netflow_record_policy_absent + register: nm_remove_netflow_record_policy_idempotency + + - name: Asserts deletion tasks + ansible.builtin.assert: + that: + - cm_remove_netflow_record_policy is changed + - cm_remove_netflow_record_policy.current == cm_remove_netflow_record_policy.previous + - cm_remove_netflow_record_policy.proposed == {} + - nm_remove_netflow_record_policy is changed + - nm_remove_netflow_record_policy.previous != [] + - nm_remove_netflow_record_policy.current == [] + - nm_remove_netflow_record_policy_idempotency is not changed + - nm_remove_netflow_record_policy_idempotency.previous == [] + - nm_remove_netflow_record_policy_idempotency.current == [] + + # CLEAN ENVIRONMENT BEFORE ENDING TESTS + - name: Remove the ansible_tenant - cleanup before ending tests + cisco.aci.aci_tenant: + <<: *aci_tenant_present + state: absent diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_node_block/aliases b/ansible_collections/cisco/aci/tests/integration/targets/aci_node_block/aliases new file mode 100644 index 000000000..209b793f9 --- /dev/null +++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_node_block/aliases @@ -0,0 +1,2 @@ +# No ACI simulator yet, so not enabled +# unsupported diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_node_block/tasks/main.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_node_block/tasks/main.yml new file mode 100644 index 000000000..a7f77758b --- /dev/null +++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_node_block/tasks/main.yml @@ -0,0 +1,275 @@ +# Test code for the ACI modules +# Copyright: (c) 2024, Gaspard Micol (@gmicol) + +# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) + +- name: Test that we have an ACI APIC host, ACI username and ACI password + ansible.builtin.fail: + msg: 'Please define the following variables: aci_hostname, aci_username and aci_password.' + when: aci_hostname is not defined or aci_username is not defined or aci_password is not defined + +- name: Set vars + ansible.builtin.set_fact: + aci_info: &aci_info + host: "{{ aci_hostname }}" + username: "{{ aci_username }}" + password: "{{ aci_password }}" + validate_certs: '{{ aci_validate_certs | default(false) }}' + use_ssl: '{{ aci_use_ssl | default(true) }}' + use_proxy: '{{ aci_use_proxy | default(true) }}' + output_level: '{{ aci_output_level | default("info") }}' + +- name: Verify Cloud and Non-Cloud Sites in use. + ansible.builtin.include_tasks: ../../../../../../integration/targets/aci_cloud_provider/tasks/main.yml + +- name: Execute tasks only for non-cloud sites + when: query_cloud.current == [] # This condition will execute only non-cloud sites + block: # block specifies execution of tasks within, based on conditions + # CLEAN ENVIRONMENT + - name: Remove the ansible_access_spine_switch_profile + cisco.aci.aci_access_spine_switch_profile: &aci_access_spine_switch_profile_absent + <<: *aci_info + switch_profile: ansible_access_spine_switch_profile + state: absent + + - name: Remove the ansible_access_leaf_switch_profile + cisco.aci.aci_switch_policy_leaf_profile: &aci_access_leaf_switch_profile_absent + <<: *aci_info + leaf_profile: ansible_access_leaf_switch_profile + state: absent + + # CREATE ACCESS SWITCH POLICY PROFILES + - name: Add a new Access Spine Switch profile + cisco.aci.aci_access_spine_switch_profile: &aci_access_spine_switch_profile_present + <<: *aci_access_spine_switch_profile_absent + state: present + + - name: Add a new Access Leaf Switch profile + cisco.aci.aci_switch_policy_leaf_profile: &aci_access_leaf_switch_profile_present + <<: *aci_access_leaf_switch_profile_absent + state: present + + # CREATE ACCESS SWITCH POLICY SELECTORS + - name: Add a new Access Spine Switch selector + cisco.aci.aci_access_spine_switch_selector: + <<: *aci_access_spine_switch_profile_present + switch_selector: ansible_access_spine_switch_selector + selector_type: range + state: present + + - name: Add a new Access Leaf Switch selector + cisco.aci.aci_switch_leaf_selector: + <<: *aci_access_leaf_switch_profile_present + leaf: ansible_access_leaf_switch_selector + state: present + + # CREATE NODE BLOCK FOR SWITCH POLICY LEAF SELECTOR + - name: Add a new Node Block for Switch policy leaf selector (check_mode) + cisco.aci.aci_node_block: &aci_node_block_leaf_present + <<: *aci_info + switch_profile: ansible_access_leaf_switch_profile + port_selector: ansible_access_leaf_switch_selector + node_block: ansible_node_block_leaf_1 + from: 1011 + to: 1011 + description: Node Block for Switch policy leaf selector 1 + type_node: leaf + state: present + check_mode: true + register: cm_add_node_block_leaf + + - name: Add a new Node Block for Switch policy leaf selector (normal_mode) + cisco.aci.aci_node_block: + <<: *aci_node_block_leaf_present + register: nm_add_node_block_leaf + + - name: Add the first Node Block for Switch policy leaf selector again - testing idempotency + cisco.aci.aci_node_block: + <<: *aci_node_block_leaf_present + register: nm_add_node_block_leaf_idempotency + + - name: Add a second Node Block for Switch policy leaf selector (normal_mode) + cisco.aci.aci_node_block: &aci_node_block_leaf_2_present + <<: *aci_info + switch_profile: ansible_access_leaf_switch_profile + port_selector: ansible_access_leaf_switch_selector + node_block: ansible_node_block_leaf_2 + from: 1012 + to: 1012 + description: Node Block for Switch policy leaf selector 2 + type_node: leaf + state: present + register: nm_add_node_block_leaf_2 + + - name: Add a Node Block for Switch policy spine selector (normal_mode) + cisco.aci.aci_node_block: &aci_node_block_spine_present + <<: *aci_info + switch_profile: ansible_access_spine_switch_profile + port_selector: ansible_access_spine_switch_selector + node_block: ansible_node_block_spine + from: 1014 + to: 1014 + description: Node Block for Switch policy spine selector + type_node: spine + state: present + register: nm_add_node_block_spine + + - name: Asserts for Node Blocks creation tasks + ansible.builtin.assert: + that: + - cm_add_node_block_leaf is changed + - cm_add_node_block_leaf.previous == [] + - cm_add_node_block_leaf.current == [] + - cm_add_node_block_leaf.proposed.infraNodeBlk.attributes.name == "ansible_node_block_leaf_1" + - cm_add_node_block_leaf.proposed.infraNodeBlk.attributes.descr == "Node Block for Switch policy leaf selector 1" + - cm_add_node_block_leaf.proposed.infraNodeBlk.attributes.from_ == "1011" + - cm_add_node_block_leaf.proposed.infraNodeBlk.attributes.to_ == "1011" + - cm_add_node_block_leaf.proposed.infraNodeBlk.attributes.dn == "uni/infra/nprof-ansible_access_leaf_switch_profile/leaves-ansible_access_leaf_switch_selector-typ-range/nodeblk-ansible_node_block_leaf_1" + - nm_add_node_block_leaf is changed + - nm_add_node_block_leaf.previous == [] + - nm_add_node_block_leaf.current.0.infraNodeBlk.attributes.name == "ansible_node_block_leaf_1" + - nm_add_node_block_leaf.current.0.infraNodeBlk.attributes.descr == "Node Block for Switch policy leaf selector 1" + - nm_add_node_block_leaf.current.0.infraNodeBlk.attributes.from_ == "1011" + - nm_add_node_block_leaf.current.0.infraNodeBlk.attributes.to_ == "1011" + - nm_add_node_block_leaf.current.0.infraNodeBlk.attributes.dn == "uni/infra/nprof-ansible_access_leaf_switch_profile/leaves-ansible_access_leaf_switch_selector-typ-range/nodeblk-ansible_node_block_leaf_1" + - nm_add_node_block_leaf_idempotency is not changed + - nm_add_node_block_leaf_idempotency.current.0.infraNodeBlk.attributes.name == "ansible_node_block_leaf_1" + - nm_add_node_block_leaf_idempotency.current.0.infraNodeBlk.attributes.descr == "Node Block for Switch policy leaf selector 1" + - nm_add_node_block_leaf_idempotency.current.0.infraNodeBlk.attributes.from_ == "1011" + - nm_add_node_block_leaf_idempotency.current.0.infraNodeBlk.attributes.to_ == "1011" + - nm_add_node_block_leaf_idempotency.current.0.infraNodeBlk.attributes.dn == "uni/infra/nprof-ansible_access_leaf_switch_profile/leaves-ansible_access_leaf_switch_selector-typ-range/nodeblk-ansible_node_block_leaf_1" + - nm_add_node_block_leaf_2 is changed + - nm_add_node_block_leaf_2.previous == [] + - nm_add_node_block_leaf_2.current.0.infraNodeBlk.attributes.name == "ansible_node_block_leaf_2" + - nm_add_node_block_leaf_2.current.0.infraNodeBlk.attributes.descr == "Node Block for Switch policy leaf selector 2" + - nm_add_node_block_leaf_2.current.0.infraNodeBlk.attributes.from_ == "1012" + - nm_add_node_block_leaf_2.current.0.infraNodeBlk.attributes.to_ == "1012" + - nm_add_node_block_leaf_2.current.0.infraNodeBlk.attributes.dn == "uni/infra/nprof-ansible_access_leaf_switch_profile/leaves-ansible_access_leaf_switch_selector-typ-range/nodeblk-ansible_node_block_leaf_2" + - nm_add_node_block_leaf_2 is changed + - nm_add_node_block_leaf_2.previous == [] + - nm_add_node_block_spine.current.0.infraNodeBlk.attributes.name == "ansible_node_block_spine" + - nm_add_node_block_spine.current.0.infraNodeBlk.attributes.descr == "Node Block for Switch policy spine selector" + - nm_add_node_block_spine.current.0.infraNodeBlk.attributes.from_ == "1014" + - nm_add_node_block_spine.current.0.infraNodeBlk.attributes.to_ == "1014" + - nm_add_node_block_spine.current.0.infraNodeBlk.attributes.dn == "uni/infra/spprof-ansible_access_spine_switch_profile/spines-ansible_access_spine_switch_selector-typ-range/nodeblk-ansible_node_block_spine" + + # QUERY NODE BLOCKS + - name: Query all Node Block for Switch policy leaf selectors + cisco.aci.aci_node_block: + <<: *aci_info + state: query + register: query_all_node_block + + - name: Query ansible_node_block_leaf_1 + cisco.aci.aci_node_block: + <<: *aci_node_block_leaf_present + state: query + register: query_ansible_node_block_leaf_1 + + - name: Query ansible_node_block_spine + cisco.aci.aci_node_block: + <<: *aci_node_block_spine_present + state: query + register: query_ansible_node_block_spine + + - name: Asserts query tasks + ansible.builtin.assert: + that: + - query_all_node_block is not changed + - query_all_node_block.current|length >= 3 + - query_ansible_node_block_leaf_1 is not changed + - query_ansible_node_block_leaf_1.current|length == 1 + - query_ansible_node_block_leaf_1.current.0.infraNodeBlk.attributes.name == "ansible_node_block_leaf_1" + - query_ansible_node_block_leaf_1.current.0.infraNodeBlk.attributes.descr == "Node Block for Switch policy leaf selector 1" + - query_ansible_node_block_leaf_1.current.0.infraNodeBlk.attributes.from_ == "1011" + - query_ansible_node_block_leaf_1.current.0.infraNodeBlk.attributes.to_ == "1011" + - query_ansible_node_block_leaf_1.current.0.infraNodeBlk.attributes.dn == "uni/infra/nprof-ansible_access_leaf_switch_profile/leaves-ansible_access_leaf_switch_selector-typ-range/nodeblk-ansible_node_block_leaf_1" + - query_ansible_node_block_spine is not changed + - query_ansible_node_block_spine.current|length == 1 + - query_ansible_node_block_spine.current.0.infraNodeBlk.attributes.name == "ansible_node_block_spine" + - query_ansible_node_block_spine.current.0.infraNodeBlk.attributes.descr == "Node Block for Switch policy spine selector" + - query_ansible_node_block_spine.current.0.infraNodeBlk.attributes.from_ == "1014" + - query_ansible_node_block_spine.current.0.infraNodeBlk.attributes.to_ == "1014" + - query_ansible_node_block_spine.current.0.infraNodeBlk.attributes.dn == "uni/infra/spprof-ansible_access_spine_switch_profile/spines-ansible_access_spine_switch_selector-typ-range/nodeblk-ansible_node_block_spine" + + # UPDATE NODE BLOCKS + - name: Update first Node Block for Switch policy leaf selector (check_mode) + cisco.aci.aci_node_block: &aci_node_block_leaf_update + <<: *aci_node_block_leaf_present + description: Updated description for first ansible Node Block for Switch policy leaf selector + from: 1013 + to: 1013 + check_mode: true + register: cm_update_node_block + + - name: Update first Node Block for Switch policy leaf selector (normal_mode) + cisco.aci.aci_node_block: + <<: *aci_node_block_leaf_update + register: nm_update_node_block + + - name: Update first Node Block for Switch policy leaf selector again - testing idempotency + cisco.aci.aci_node_block: + <<: *aci_node_block_leaf_update + register: nm_udpate_node_block_leaf_idempotency + + - name: Asserts for Node Blocks update tasks + ansible.builtin.assert: + that: + - cm_update_node_block is changed + - cm_update_node_block.previous == cm_update_node_block.current + - cm_update_node_block.proposed.infraNodeBlk.attributes.descr == "Updated description for first ansible Node Block for Switch policy leaf selector" + - cm_update_node_block.proposed.infraNodeBlk.attributes.from_ == "1013" + - cm_update_node_block.proposed.infraNodeBlk.attributes.to_ == "1013" + - nm_update_node_block is changed + - nm_update_node_block.current.0.infraNodeBlk.attributes.name == "ansible_node_block_leaf_1" + - nm_update_node_block.current.0.infraNodeBlk.attributes.descr == "Updated description for first ansible Node Block for Switch policy leaf selector" + - nm_update_node_block.current.0.infraNodeBlk.attributes.from_ == "1013" + - nm_update_node_block.current.0.infraNodeBlk.attributes.to_ == "1013" + - nm_update_node_block.current.0.infraNodeBlk.attributes.dn == "uni/infra/nprof-ansible_access_leaf_switch_profile/leaves-ansible_access_leaf_switch_selector-typ-range/nodeblk-ansible_node_block_leaf_1" + - nm_udpate_node_block_leaf_idempotency is not changed + - nm_udpate_node_block_leaf_idempotency.current.0.infraNodeBlk.attributes.name == "ansible_node_block_leaf_1" + - nm_udpate_node_block_leaf_idempotency.current.0.infraNodeBlk.attributes.descr == "Updated description for first ansible Node Block for Switch policy leaf selector" + - nm_udpate_node_block_leaf_idempotency.current.0.infraNodeBlk.attributes.from_ == "1013" + - nm_udpate_node_block_leaf_idempotency.current.0.infraNodeBlk.attributes.to_ == "1013" + - nm_udpate_node_block_leaf_idempotency.current.0.infraNodeBlk.attributes.dn == "uni/infra/nprof-ansible_access_leaf_switch_profile/leaves-ansible_access_leaf_switch_selector-typ-range/nodeblk-ansible_node_block_leaf_1" + + # DELETE NODE BLOCKS + - name: Remove Node Block for Switch policy leaf selector (check_mode) + cisco.aci.aci_node_block: &node_block_leaf_absent + <<: *aci_node_block_leaf_update + state: absent + check_mode: true + register: cm_remove_node_block_leaf + + - name: Remove Node Block for Switch policy leaf selector (normal_mode) + cisco.aci.aci_node_block: + <<: *node_block_leaf_absent + register: nm_remove_node_block_leaf + + - name: Remove Node Block for Switch policy leaf selector - testing idempotency + cisco.aci.aci_node_block: + <<: *node_block_leaf_absent + register: nm_remove_node_block_leaf_idempotency + + - name: Asserts deletion tasks + ansible.builtin.assert: + that: + - cm_remove_node_block_leaf is changed + - cm_remove_node_block_leaf.current == cm_remove_node_block_leaf.previous + - cm_remove_node_block_leaf.proposed == {} + - nm_remove_node_block_leaf is changed + - nm_remove_node_block_leaf.previous != [] + - nm_remove_node_block_leaf.proposed == {} + - nm_remove_node_block_leaf.current == [] + - nm_remove_node_block_leaf_idempotency is not changed + - nm_remove_node_block_leaf_idempotency.previous == [] + - nm_remove_node_block_leaf_idempotency.current == [] + + # CLEAN ENVIRONMENT BEFORE ENDING TESTS + - name: Remove the Access Spine Switch profile - cleanup before ending tests + cisco.aci.aci_access_spine_switch_profile: + <<: *aci_access_spine_switch_profile_absent + + - name: Remove the Access Leaf Switch profile - cleanup before ending tests + cisco.aci.aci_switch_policy_leaf_profile: + <<: *aci_access_leaf_switch_profile_absent diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_node_mgmt_epg/tasks/main.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_node_mgmt_epg/tasks/main.yml index 310fc822b..8cdf876f6 100644 --- a/ansible_collections/cisco/aci/tests/integration/targets/aci_node_mgmt_epg/tasks/main.yml +++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_node_mgmt_epg/tasks/main.yml @@ -4,12 +4,12 @@ # GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) - name: Test that we have an ACI APIC host, ACI username and ACI password - fail: + ansible.builtin.fail: msg: 'Please define the following variables: aci_hostname, aci_username and aci_password.' when: aci_hostname is not defined or aci_username is not defined or aci_password is not defined - name: Set vars - set_fact: + ansible.builtin.set_fact: aci_info: &aci_info host: "{{ aci_hostname }}" username: "{{ aci_username }}" @@ -20,14 +20,14 @@ output_level: debug - name: Verify Cloud and Non-Cloud Sites in use. - include_tasks: ../../../../../../integration/targets/aci_cloud_provider/tasks/main.yml + ansible.builtin.include_tasks: ../../../../../../integration/targets/aci_cloud_provider/tasks/main.yml - name: Execute tasks only for non-cloud sites when: query_cloud.current == [] # This condition will execute only non-cloud sites block: # block specifies execution of tasks within, based on conditions # Clean Environment - name: Remove node mgmt in_band epg - aci_node_mgmt_epg: + cisco.aci.aci_node_mgmt_epg: <<: *aci_info type: in_band epg: "{{ item }}" @@ -39,7 +39,7 @@ - ansible-inband-2 - name: Remove node mgmt out_of_band epg - aci_node_mgmt_epg: + cisco.aci.aci_node_mgmt_epg: <<: *aci_info type: out_of_band epg: "{{ item }}" @@ -50,7 +50,7 @@ # Add operations - name: Add node mgmt in_band epg in check mode - aci_node_mgmt_epg: + cisco.aci.aci_node_mgmt_epg: <<: *aci_info type: in_band epg: ansible-inband @@ -61,7 +61,7 @@ register: add_cm_inband - name: Add node mgmt out_of_band epg in check mode - aci_node_mgmt_epg: + cisco.aci.aci_node_mgmt_epg: <<: *aci_info type: out_of_band epg: ansible-outofband @@ -70,7 +70,7 @@ register: add_cm_outofband - name: Add node mgmt in_band epg in normal mode - aci_node_mgmt_epg: + cisco.aci.aci_node_mgmt_epg: <<: *aci_info type: in_band epg: ansible-inband @@ -80,7 +80,7 @@ register: add_nm_inband - name: Add node mgmt out_of_band epg in normal mode - aci_node_mgmt_epg: + cisco.aci.aci_node_mgmt_epg: <<: *aci_info type: out_of_band epg: ansible-outofband @@ -88,7 +88,7 @@ register: add_nm_outofband - name: Add node mgmt in_band epg in normal mode again - aci_node_mgmt_epg: + cisco.aci.aci_node_mgmt_epg: <<: *aci_info type: in_band epg: ansible-inband @@ -98,7 +98,7 @@ register: add_nm_inband_again - name: Add node mgmt out_of_band epg in normal mode again - aci_node_mgmt_epg: + cisco.aci.aci_node_mgmt_epg: <<: *aci_info type: out_of_band epg: ansible-outofband @@ -106,7 +106,7 @@ register: add_nm_outofband_again - name: Add another node mgmt in_band epg in normal mode - aci_node_mgmt_epg: + cisco.aci.aci_node_mgmt_epg: <<: *aci_info type: in_band epg: ansible-inband-2 @@ -116,7 +116,7 @@ register: add_nm_inband_2 - name: Add another node mgmt out_of_band epg in normal mode - aci_node_mgmt_epg: + cisco.aci.aci_node_mgmt_epg: <<: *aci_info type: out_of_band epg: ansible-outofband-2 @@ -124,7 +124,7 @@ register: add_nm_outofband_2 - name: Add another node mgmt in_band epg in normal mode with change made to bd - aci_node_mgmt_epg: + cisco.aci.aci_node_mgmt_epg: <<: *aci_info type: in_band epg: ansible-inband-2 @@ -134,7 +134,7 @@ register: add_nm_inband_bd4 - name: Add another node mgmt in_band epg in normal mode with change made to encap - aci_node_mgmt_epg: + cisco.aci.aci_node_mgmt_epg: <<: *aci_info type: in_band epg: ansible-inband-2 @@ -144,7 +144,7 @@ register: add_nm_inband_encap4 - name: Verify add operations - assert: + ansible.builtin.assert: that: - add_cm_inband is changed - add_cm_inband.sent.mgmtInB.attributes.name == 'ansible-inband' @@ -173,7 +173,7 @@ # Query operations - name: Query node mgmt in_band epg - aci_node_mgmt_epg: + cisco.aci.aci_node_mgmt_epg: <<: *aci_info type: in_band epg: ansible-inband @@ -183,7 +183,7 @@ register: query_inband - name: Query node mgmt out_of_band epg - aci_node_mgmt_epg: + cisco.aci.aci_node_mgmt_epg: <<: *aci_info type: out_of_band epg: ansible-outofband @@ -191,21 +191,21 @@ register: query_outofband - name: Query all in band - aci_node_mgmt_epg: + cisco.aci.aci_node_mgmt_epg: <<: *aci_info type: in_band state: query register: query_all_inband - name: Query all out of band - aci_node_mgmt_epg: + cisco.aci.aci_node_mgmt_epg: <<: *aci_info type: out_of_band state: query register: query_all_outofband - name: Verify query operations - assert: + ansible.builtin.assert: that: - query_inband is not changed - query_inband.current.0.mgmtInB.attributes.name == 'ansible-inband' @@ -217,7 +217,7 @@ # Remove operations - name: Remove node mgmt in_band epg - aci_node_mgmt_epg: + cisco.aci.aci_node_mgmt_epg: <<: *aci_info type: in_band epg: ansible-inband-2 @@ -225,7 +225,7 @@ register: remove_inband_2 - name: Remove node mgmt out_of_band epg - aci_node_mgmt_epg: + cisco.aci.aci_node_mgmt_epg: <<: *aci_info type: out_of_band epg: ansible-outofband-2 @@ -233,7 +233,7 @@ register: remove_outofband_2 - name: Remove node mgmt in_band epg again - aci_node_mgmt_epg: + cisco.aci.aci_node_mgmt_epg: <<: *aci_info type: in_band epg: ansible-inband-2 @@ -241,7 +241,7 @@ register: remove_inband_2_again - name: Verify remove operations - assert: + ansible.builtin.assert: that: - remove_inband_2 is changed - remove_inband_2.previous.0.mgmtInB.attributes.name == 'ansible-inband-2' diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_ntp_policy/tasks/main.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_ntp_policy/tasks/main.yml index ddc5b69e6..6d07f2b00 100644 --- a/ansible_collections/cisco/aci/tests/integration/targets/aci_ntp_policy/tasks/main.yml +++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_ntp_policy/tasks/main.yml @@ -4,12 +4,12 @@ # GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) - name: Test that we have an ACI APIC host, ACI username and ACI password - fail: + ansible.builtin.fail: msg: 'Please define the following variables: aci_hostname, aci_username and aci_password.' when: aci_hostname is not defined or aci_username is not defined or aci_password is not defined - name: Set vars - set_fact: + ansible.builtin.set_fact: aci_info: &aci_info host: "{{ aci_hostname }}" username: "{{ aci_username }}" @@ -56,7 +56,7 @@ register: nm_add_policy_again - name: Verify add policy - assert: + ansible.builtin.assert: that: - cm_add_policy is changed - nm_add_policy is changed @@ -105,7 +105,7 @@ register: nm_modify_policy_again - name: Verify modify policy - assert: + ansible.builtin.assert: that: - cm_modify_policy is changed - nm_modify_policy is changed @@ -138,7 +138,7 @@ register: nm_query_all_policies - name: Verify query_all_policies - assert: + ansible.builtin.assert: that: - cm_query_all_policies is not changed - nm_query_all_policies is not changed @@ -158,7 +158,7 @@ register: nm_query_policy - name: Verify query_policy - assert: + ansible.builtin.assert: that: - cm_query_policy is not changed - nm_query_policy is not changed @@ -194,7 +194,7 @@ register: nm_remove_policy_again - name: Verify remove_policy - assert: + ansible.builtin.assert: that: - cm_remove_policy is changed - nm_remove_policy is changed diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_ntp_server/tasks/main.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_ntp_server/tasks/main.yml index 15c6799cb..1a1ea2879 100644 --- a/ansible_collections/cisco/aci/tests/integration/targets/aci_ntp_server/tasks/main.yml +++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_ntp_server/tasks/main.yml @@ -4,12 +4,12 @@ # GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) - name: Test that we have an ACI APIC host, ACI username and ACI password - fail: + ansible.builtin.fail: msg: 'Please define the following variables: aci_hostname, aci_username and aci_password.' when: aci_hostname is not defined or aci_username is not defined or aci_password is not defined - name: Set vars - set_fact: + ansible.builtin.set_fact: aci_info: &aci_info host: "{{ aci_hostname }}" username: "{{ aci_username }}" @@ -68,7 +68,7 @@ register: nm_add_server_again - name: Verify add server - assert: + ansible.builtin.assert: that: - cm_add_server is changed - nm_add_server is changed @@ -120,7 +120,7 @@ register: nm_modify_server_again - name: Verify modify policy - assert: + ansible.builtin.assert: that: - cm_modify_server is changed - nm_modify_server is changed @@ -156,7 +156,7 @@ register: nm_query_all_servers - name: Verify query_all_servers - assert: + ansible.builtin.assert: that: - cm_query_all_servers is not changed - nm_query_all_servers is not changed @@ -176,7 +176,7 @@ register: nm_query_server - name: Verify query_server - assert: + ansible.builtin.assert: that: - cm_query_server is not changed - nm_query_server is not changed @@ -215,7 +215,7 @@ register: nm_remove_server_again - name: Verify remove_server - assert: + ansible.builtin.assert: that: - cm_remove_server is changed - nm_remove_server is changed diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_pim_route_map_entry/aliases b/ansible_collections/cisco/aci/tests/integration/targets/aci_pim_route_map_entry/aliases new file mode 100644 index 000000000..209b793f9 --- /dev/null +++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_pim_route_map_entry/aliases @@ -0,0 +1,2 @@ +# No ACI simulator yet, so not enabled +# unsupported diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_pim_route_map_entry/tasks/main.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_pim_route_map_entry/tasks/main.yml new file mode 100644 index 000000000..c9cdf09c2 --- /dev/null +++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_pim_route_map_entry/tasks/main.yml @@ -0,0 +1,196 @@ +# Test code for the ACI modules +# Copyright: (c) 2023, Gaspard Micol (@gmicol) + +# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) + +- name: Test that we have an ACI APIC host, ACI username and ACI password + ansible.builtin.fail: + msg: 'Please define the following variables: aci_hostname, aci_username and aci_password.' + when: aci_hostname is not defined or aci_username is not defined or aci_password is not defined + +- name: Set vars + ansible.builtin.set_fact: + aci_info: &aci_info + host: "{{ aci_hostname }}" + username: "{{ aci_username }}" + password: "{{ aci_password }}" + validate_certs: '{{ aci_validate_certs | default(false) }}' + use_ssl: '{{ aci_use_ssl | default(true) }}' + use_proxy: '{{ aci_use_proxy | default(true) }}' + output_level: '{{ aci_output_level | default("info") }}' + +# CLEAN ENVIRONMENT +- name: Remove the ansible_tenant + cisco.aci.aci_tenant: &aci_tenant_absent + <<: *aci_info + tenant: ansible_tenant + state: absent + +- name: Verify Cloud and Non-Cloud Sites in use. + ansible.builtin.include_tasks: ../../../../../../integration/targets/aci_cloud_provider/tasks/main.yml + +- name: Execute tasks only for non-cloud sites + when: query_cloud.current == [] # This condition will execute only non-cloud sites + block: # block specifies execution of tasks within, based on conditions + - name: Add a new tenant + cisco.aci.aci_tenant: &aci_tenant_present + <<: *aci_info + tenant: ansible_tenant + description: Ansible tenant + state: present + + - name: Add a new PIM route map policy + cisco.aci.aci_pim_route_map_policy: + <<: *aci_info + tenant: ansible_tenant + pim_route_map_policy: ansible_pim_route_map_policy + description: PIM route map policy 1 for ansible_tenant tenant + state: present + + # CREATION TASKS + - name: Add a PIM route map entry (check_mode) + cisco.aci.aci_pim_route_map_entry: &aci_pim_route_map_entry_present + <<: *aci_info + tenant: ansible_tenant + pim_route_map_policy: ansible_pim_route_map_policy + order: 1 + description: PIM route map entry 1 for pim_route_map_policy + source_ip: 1.1.1.1/24 + group_ip: 224.0.0.1/24 + rp_ip: 1.1.1.2 + action: deny + state: present + check_mode: true + register: cm_add_pim_route_map_entry + + - name: Add a PIM route map entry (normal_mode) + cisco.aci.aci_pim_route_map_entry: + <<: *aci_pim_route_map_entry_present + register: nm_add_pim_route_map_entry + + - name: Add the first PIM route map entry again - testing idempotency + cisco.aci.aci_pim_route_map_entry: + <<: *aci_pim_route_map_entry_present + register: nm_add_pim_route_map_entry_idempotency + + - name: Add a second PIM route map entry (normal_mode) + cisco.aci.aci_pim_route_map_entry: + <<: *aci_info + tenant: ansible_tenant + pim_route_map_policy: ansible_pim_route_map_policy + order: 2 + description: PIM route map entry 2 for pim_route_map_policy + state: present + register: nm_add_pim_route_map_entry_2 + + - name: Asserts for PIM route map entry creation tasks + ansible.builtin.assert: + that: + - cm_add_pim_route_map_entry is changed + - cm_add_pim_route_map_entry.previous == [] + - cm_add_pim_route_map_entry.current == [] + - nm_add_pim_route_map_entry is changed + - nm_add_pim_route_map_entry.current.0.pimRouteMapEntry.attributes.order == "1" + - nm_add_pim_route_map_entry.current.0.pimRouteMapEntry.attributes.action == "deny" + - nm_add_pim_route_map_entry.current.0.pimRouteMapEntry.attributes.grp == "224.0.0.1/24" + - nm_add_pim_route_map_entry.current.0.pimRouteMapEntry.attributes.rp == "1.1.1.2" + - nm_add_pim_route_map_entry.current.0.pimRouteMapEntry.attributes.src == "1.1.1.1/24" + - nm_add_pim_route_map_entry_idempotency is not changed + - nm_add_pim_route_map_entry_2 is changed + - nm_add_pim_route_map_entry_2.previous == [] + - nm_add_pim_route_map_entry_2.current.0.pimRouteMapEntry.attributes.order == "2" + - nm_add_pim_route_map_entry_2.current.0.pimRouteMapEntry.attributes.action == "permit" + + # QUERY TASKS + - name: Query all PIM route map entries + cisco.aci.aci_pim_route_map_entry: + <<: *aci_info + state: query + register: query_all_pim_route_map_entry + + - name: Query ansible_pim_route_map_entry_1 + cisco.aci.aci_pim_route_map_entry: + <<: *aci_pim_route_map_entry_present + state: query + register: query_ansible_pim_route_map_entry_1 + + - name: Asserts query tasks + ansible.builtin.assert: + that: + - query_all_pim_route_map_entry is not changed + - query_all_pim_route_map_entry.current|length >= 2 + - query_ansible_pim_route_map_entry_1 is not changed + - query_ansible_pim_route_map_entry_1.current.0.pimRouteMapEntry.attributes.order == "1" + - query_ansible_pim_route_map_entry_1.current.0.pimRouteMapEntry.attributes.action == "deny" + - query_ansible_pim_route_map_entry_1.current.0.pimRouteMapEntry.attributes.grp == "224.0.0.1/24" + - query_ansible_pim_route_map_entry_1.current.0.pimRouteMapEntry.attributes.rp == "1.1.1.2" + - query_ansible_pim_route_map_entry_1.current.0.pimRouteMapEntry.attributes.src == "1.1.1.1/24" + + # UPDATE TASKS + - name: Update first PIM route map entry (check_mode) + cisco.aci.aci_pim_route_map_entry: &aci_pim_route_map_entry_update + <<: *aci_pim_route_map_entry_present + order: 3 + source_ip: 1.1.1.3/24 + group_ip: 224.0.0.3/24 + rp_ip: 1.1.1.3 + action: permit + check_mode: true + register: cm_update_pim_route_map_entry + + - name: Update first PIM route map entry (normal_mode) + cisco.aci.aci_pim_route_map_entry: + <<: *aci_pim_route_map_entry_update + register: nm_update_pim_route_map_entry + + - name: Update first PIM route map entry again - testing idempotency + cisco.aci.aci_pim_route_map_entry: + <<: *aci_pim_route_map_entry_update + register: nm_update_pim_route_map_entry_idempotency + + - name: Asserts for PIM route map entry update tasks + ansible.builtin.assert: + that: + - cm_update_pim_route_map_entry is changed + - cm_update_pim_route_map_entry.previous == cm_update_pim_route_map_entry.current + - nm_update_pim_route_map_entry is changed + - nm_update_pim_route_map_entry.current.0.pimRouteMapEntry.attributes.order == "3" + - nm_update_pim_route_map_entry.current.0.pimRouteMapEntry.attributes.action == "permit" + - nm_update_pim_route_map_entry.current.0.pimRouteMapEntry.attributes.grp == "224.0.0.3/24" + - nm_update_pim_route_map_entry.current.0.pimRouteMapEntry.attributes.rp == "1.1.1.3" + - nm_update_pim_route_map_entry.current.0.pimRouteMapEntry.attributes.src == "1.1.1.3/24" + - nm_update_pim_route_map_entry_idempotency is not changed + + # DELETION TASKS + - name: Remove PIM route map entry (check_mode) + cisco.aci.aci_pim_route_map_entry: &pim_route_map_entry_absent + <<: *aci_pim_route_map_entry_update + state: absent + check_mode: true + register: cm_remove_pim_route_map_entry + + - name: Remove PIM route map entry (normal_mode) + cisco.aci.aci_pim_route_map_entry: + <<: *pim_route_map_entry_absent + register: nm_remove_pim_route_map_entry + + - name: Remove PIM route map entry - testing idempotency + cisco.aci.aci_pim_route_map_entry: + <<: *pim_route_map_entry_absent + register: nm_remove_pim_route_map_entry_idempotency + + - name: Asserts deletion tasks + ansible.builtin.assert: + that: + - cm_remove_pim_route_map_entry is changed + - cm_remove_pim_route_map_entry.proposed == {} + - nm_remove_pim_route_map_entry is changed + - nm_remove_pim_route_map_entry.previous != [] + - nm_remove_pim_route_map_entry.current == [] + - nm_remove_pim_route_map_entry_idempotency is not changed + - nm_remove_pim_route_map_entry_idempotency.previous == [] + + - name: Remove the ansible_tenant - cleanup before ending tests + cisco.aci.aci_tenant: + <<: *aci_tenant_present + state: absent diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_pim_route_map_policy/aliases b/ansible_collections/cisco/aci/tests/integration/targets/aci_pim_route_map_policy/aliases new file mode 100644 index 000000000..209b793f9 --- /dev/null +++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_pim_route_map_policy/aliases @@ -0,0 +1,2 @@ +# No ACI simulator yet, so not enabled +# unsupported diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_pim_route_map_policy/tasks/main.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_pim_route_map_policy/tasks/main.yml new file mode 100644 index 000000000..4737bb2bb --- /dev/null +++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_pim_route_map_policy/tasks/main.yml @@ -0,0 +1,135 @@ +# Test code for the ACI modules +# Copyright: (c) 2023, Gaspard Micol (@gmicol) + +# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) + +- name: Test that we have an ACI APIC host, ACI username and ACI password + ansible.builtin.fail: + msg: 'Please define the following variables: aci_hostname, aci_username and aci_password.' + when: aci_hostname is not defined or aci_username is not defined or aci_password is not defined + +- name: Set vars + ansible.builtin.set_fact: + aci_info: &aci_info + host: "{{ aci_hostname }}" + username: "{{ aci_username }}" + password: "{{ aci_password }}" + validate_certs: '{{ aci_validate_certs | default(false) }}' + use_ssl: '{{ aci_use_ssl | default(true) }}' + use_proxy: '{{ aci_use_proxy | default(true) }}' + output_level: '{{ aci_output_level | default("info") }}' + +# CLEAN ENVIRONMENT +- name: Remove the ansible_tenant + cisco.aci.aci_tenant: &aci_tenant_absent + <<: *aci_info + tenant: ansible_tenant + state: absent + +- name: Verify Cloud and Non-Cloud Sites in use. + ansible.builtin.include_tasks: ../../../../../../integration/targets/aci_cloud_provider/tasks/main.yml + +- name: Execute tasks only for non-cloud sites + when: query_cloud.current == [] # This condition will execute only non-cloud sites + block: # block specifies execution of tasks within, based on conditions + - name: Add a new tenant + cisco.aci.aci_tenant: &aci_tenant_present + <<: *aci_info + tenant: ansible_tenant + description: Ansible tenant + state: present + + - name: Add a PIM route map policy (check_mode) + cisco.aci.aci_pim_route_map_policy: &aci_pim_route_map_policy_present + <<: *aci_info + tenant: ansible_tenant + pim_route_map_policy: ansible_pim_route_map_policy_1 + description: PIM route map policy 1 for ansible_tenant tenant + state: present + check_mode: true + register: cm_add_pim_route_map_policy + + - name: Add a PIM route map policy (normal_mode) + cisco.aci.aci_pim_route_map_policy: + <<: *aci_pim_route_map_policy_present + register: nm_add_pim_route_map_policy + + - name: Add the first PIM route map policy again - testing idempotency + cisco.aci.aci_pim_route_map_policy: + <<: *aci_pim_route_map_policy_present + register: nm_add_pim_route_map_policy_idempotency + + - name: Add a second PIM route map policy (normal_mode) + cisco.aci.aci_pim_route_map_policy: + <<: *aci_info + tenant: ansible_tenant + pim_route_map_policy: ansible_pim_route_map_policy_2 + description: PIM route map policy 2 for ansible_tenant tenant + state: present + register: nm_add_pim_route_map_policy_2 + + - name: Asserts for PIM route map policy creation tasks + ansible.builtin.assert: + that: + - cm_add_pim_route_map_policy is changed + - cm_add_pim_route_map_policy.previous == [] + - cm_add_pim_route_map_policy.current == [] + - nm_add_pim_route_map_policy is changed + - nm_add_pim_route_map_policy.current.0.pimRouteMapPol.attributes.name == "ansible_pim_route_map_policy_1" + - nm_add_pim_route_map_policy_idempotency is not changed + - nm_add_pim_route_map_policy_2 is changed + - nm_add_pim_route_map_policy_2.previous == [] + - nm_add_pim_route_map_policy_2.current.0.pimRouteMapPol.attributes.name == "ansible_pim_route_map_policy_2" + + - name: Query all PIM route map policies + cisco.aci.aci_pim_route_map_policy: + <<: *aci_info + state: query + register: query_all_pim_route_map_policy + + - name: Query ansible_pim_route_map_policy_1 + cisco.aci.aci_pim_route_map_policy: + <<: *aci_pim_route_map_policy_present + state: query + register: query_ansible_pim_route_map_policy_1 + + - name: Asserts query tasks + ansible.builtin.assert: + that: + - query_all_pim_route_map_policy is not changed + - query_all_pim_route_map_policy.current|length >= 2 + - query_ansible_pim_route_map_policy_1 is not changed + - query_ansible_pim_route_map_policy_1.current.0.pimRouteMapPol.attributes.name == "ansible_pim_route_map_policy_1" + + - name: Remove PIM route map policy (check_mode) + cisco.aci.aci_pim_route_map_policy: &pim_route_map_policy_absent + <<: *aci_pim_route_map_policy_present + state: absent + check_mode: true + register: cm_remove_pim_route_map_policy + + - name: Remove PIM route map policy (normal_mode) + cisco.aci.aci_pim_route_map_policy: + <<: *pim_route_map_policy_absent + register: nm_remove_pim_route_map_policy + + - name: Remove PIM route map policy - testing idempotency + cisco.aci.aci_pim_route_map_policy: + <<: *pim_route_map_policy_absent + register: nm_remove_pim_route_map_policy_idempotency + + - name: Asserts deletion tasks + ansible.builtin.assert: + that: + - cm_remove_pim_route_map_policy is changed + - cm_remove_pim_route_map_policy.proposed == {} + - nm_remove_pim_route_map_policy is changed + - nm_remove_pim_route_map_policy.previous != [] + - nm_remove_pim_route_map_policy.current == [] + - nm_remove_pim_route_map_policy_idempotency is not changed + - nm_remove_pim_route_map_policy_idempotency.previous == [] + + - name: Remove the ansible_tenant - cleanup before ending tests + cisco.aci.aci_tenant: + <<: *aci_tenant_present + state: absent diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_qos_custom_policy/aliases b/ansible_collections/cisco/aci/tests/integration/targets/aci_qos_custom_policy/aliases new file mode 100644 index 000000000..209b793f9 --- /dev/null +++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_qos_custom_policy/aliases @@ -0,0 +1,2 @@ +# No ACI simulator yet, so not enabled +# unsupported diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_qos_custom_policy/tasks/main.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_qos_custom_policy/tasks/main.yml new file mode 100644 index 000000000..0a984577a --- /dev/null +++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_qos_custom_policy/tasks/main.yml @@ -0,0 +1,139 @@ +# Test code for the ACI modules +# Copyright: (c) 2023, Gaspard Micol (@gmicol) + +# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) + +- name: Test that we have an ACI APIC host, ACI username and ACI password + ansible.builtin.fail: + msg: 'Please define the following variables: aci_hostname, aci_username and aci_password.' + when: aci_hostname is not defined or aci_username is not defined or aci_password is not defined + +- name: Set vars + ansible.builtin.set_fact: + aci_info: &aci_info + host: "{{ aci_hostname }}" + username: "{{ aci_username }}" + password: "{{ aci_password }}" + validate_certs: '{{ aci_validate_certs | default(false) }}' + use_ssl: '{{ aci_use_ssl | default(true) }}' + use_proxy: '{{ aci_use_proxy | default(true) }}' + output_level: '{{ aci_output_level | default("info") }}' + +# CLEAN ENVIRONMENT BEFORE TESTS +- name: Remove the ansible_tenant + cisco.aci.aci_tenant: &aci_tenant_absent + <<: *aci_info + tenant: ansible_tenant + state: absent + +- name: Verify Cloud and Non-Cloud Sites in use. + ansible.builtin.include_tasks: ../../../../../../integration/targets/aci_cloud_provider/tasks/main.yml + +- name: Execute tasks only for non-cloud sites + when: query_cloud.current == [] # This condition will execute only non-cloud sites + block: # block specifies execution of tasks within, based on conditions + - name: Add a new tenant + cisco.aci.aci_tenant: &aci_tenant_present + <<: *aci_info + tenant: ansible_tenant + description: Ansible tenant + state: present + + # CREATE QOS CUSTOM POLICY + - name: Add a QoS Custom policy (check_mode) + cisco.aci.aci_qos_custom_policy: &aci_qos_custom_policy_present + <<: *aci_info + tenant: ansible_tenant + qos_custom_policy: ansible_qos_custom_policy_1 + description: QoS Custom policy 1 for ansible_tenant tenant + state: present + check_mode: true + register: cm_add_qos_custom_policy + + - name: Add a QoS Custom policy (normal_mode) + cisco.aci.aci_qos_custom_policy: + <<: *aci_qos_custom_policy_present + register: nm_add_qos_custom_policy + + - name: Add the first QoS Custom policy again - testing idempotency + cisco.aci.aci_qos_custom_policy: + <<: *aci_qos_custom_policy_present + register: nm_add_qos_custom_policy_idempotency + + - name: Add a second QoS Custom policy (normal_mode) + cisco.aci.aci_qos_custom_policy: + <<: *aci_info + tenant: ansible_tenant + qos_custom_policy: ansible_qos_custom_policy_2 + description: QoS Custom policy 2 for ansible_tenant tenant + state: present + register: nm_add_qos_custom_policy_2 + + - name: Asserts for QoS Custom policy creation tasks + ansible.builtin.assert: + that: + - cm_add_qos_custom_policy is changed + - cm_add_qos_custom_policy.previous == [] + - cm_add_qos_custom_policy.current == [] + - nm_add_qos_custom_policy is changed + - nm_add_qos_custom_policy.current.0.qosCustomPol.attributes.name == "ansible_qos_custom_policy_1" + - nm_add_qos_custom_policy_idempotency is not changed + - nm_add_qos_custom_policy_2 is changed + - nm_add_qos_custom_policy_2.previous == [] + - nm_add_qos_custom_policy_2.current.0.qosCustomPol.attributes.name == "ansible_qos_custom_policy_2" + + # QUERY QOS CUSTOM POLICY + - name: Query all QoS Custom policies + cisco.aci.aci_qos_custom_policy: + <<: *aci_info + state: query + register: query_all_qos_custom_policy + + - name: Query ansible_qos_custom_policy_1 + cisco.aci.aci_qos_custom_policy: + <<: *aci_qos_custom_policy_present + state: query + register: query_ansible_qos_custom_policy_1 + + - name: Asserts query tasks + ansible.builtin.assert: + that: + - query_all_qos_custom_policy is not changed + - query_all_qos_custom_policy.current|length >= 2 + - query_ansible_qos_custom_policy_1 is not changed + - query_ansible_qos_custom_policy_1.current.0.qosCustomPol.attributes.name == "ansible_qos_custom_policy_1" + + # DELETE QOS CUSTOM POLICY + - name: Remove QoS Custom policy (check_mode) + cisco.aci.aci_qos_custom_policy: &qos_custom_policy_absent + <<: *aci_qos_custom_policy_present + state: absent + check_mode: true + register: cm_remove_qos_custom_policy + + - name: Remove QoS Custom policy (normal_mode) + cisco.aci.aci_qos_custom_policy: + <<: *qos_custom_policy_absent + register: nm_remove_qos_custom_policy + + - name: Remove QoS Custom policy - testing idempotency + cisco.aci.aci_qos_custom_policy: + <<: *qos_custom_policy_absent + register: nm_remove_qos_custom_policy_idempotency + + - name: Asserts deletion tasks + ansible.builtin.assert: + that: + - cm_remove_qos_custom_policy is changed + - cm_remove_qos_custom_policy.proposed == {} + - nm_remove_qos_custom_policy is changed + - nm_remove_qos_custom_policy.previous != [] + - nm_remove_qos_custom_policy.current == [] + - nm_remove_qos_custom_policy_idempotency is not changed + - nm_remove_qos_custom_policy_idempotency.previous == [] + + # CLEAN ENVIRONMENT BEFORE ENDING TESTS + - name: Remove the ansible_tenant - cleanup before ending tests + cisco.aci.aci_tenant: + <<: *aci_tenant_present + state: absent diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_qos_dot1p_class/aliases b/ansible_collections/cisco/aci/tests/integration/targets/aci_qos_dot1p_class/aliases new file mode 100644 index 000000000..209b793f9 --- /dev/null +++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_qos_dot1p_class/aliases @@ -0,0 +1,2 @@ +# No ACI simulator yet, so not enabled +# unsupported diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_qos_dot1p_class/tasks/main.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_qos_dot1p_class/tasks/main.yml new file mode 100644 index 000000000..efcfa993f --- /dev/null +++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_qos_dot1p_class/tasks/main.yml @@ -0,0 +1,167 @@ +# Test code for the ACI modules +# Copyright: (c) 2023, Gaspard Micol (@gmicol) + +# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) + +- name: Test that we have an ACI APIC host, ACI username and ACI password + ansible.builtin.fail: + msg: 'Please define the following variables: aci_hostname, aci_username and aci_password.' + when: aci_hostname is not defined or aci_username is not defined or aci_password is not defined + +- name: Set vars + ansible.builtin.set_fact: + aci_info: &aci_info + host: "{{ aci_hostname }}" + username: "{{ aci_username }}" + password: "{{ aci_password }}" + validate_certs: '{{ aci_validate_certs | default(false) }}' + use_ssl: '{{ aci_use_ssl | default(true) }}' + use_proxy: '{{ aci_use_proxy | default(true) }}' + output_level: '{{ aci_output_level | default("info") }}' + +# CLEAN ENVIRONMENT BEFORE TESTS +- name: Remove the ansible_tenant + cisco.aci.aci_tenant: &aci_tenant_absent + <<: *aci_info + tenant: ansible_tenant + state: absent + +- name: Verify Cloud and Non-Cloud Sites in use. + ansible.builtin.include_tasks: ../../../../../../integration/targets/aci_cloud_provider/tasks/main.yml + +- name: Execute tasks only for non-cloud sites + when: query_cloud.current == [] # This condition will execute only non-cloud sites + block: # block specifies execution of tasks within, based on conditions + - name: Add a new tenant + cisco.aci.aci_tenant: &aci_tenant_present + <<: *aci_info + tenant: ansible_tenant + description: Ansible tenant + state: present + + - name: Add a QoS Custom policy + cisco.aci.aci_qos_custom_policy: + <<: *aci_info + tenant: ansible_tenant + qos_custom_policy: ansible_qos_custom_policy_1 + description: QoS Custom policy 1 for ansible_tenant tenant + state: present + + # CREATE QOS Dot1P Class + - name: Add a QoS Dot1P Class (check_mode) + cisco.aci.aci_qos_dot1p_class: &aci_qos_dot1p_class_present + <<: *aci_info + tenant: ansible_tenant + qos_custom_policy: ansible_qos_custom_policy_1 + priority: level1 + dot1p_from: best_effort + dot1p_to: excellent_effort + dot1p_target: AF31 + target_cos: best_effort + state: present + check_mode: true + register: cm_add_qos_dot1p_class + + - name: Add a QoS Dot1P Class (normal_mode) + cisco.aci.aci_qos_dot1p_class: + <<: *aci_qos_dot1p_class_present + register: nm_add_qos_dot1p_class + + - name: Add the first QoS Dot1P Class again - testing idempotency + cisco.aci.aci_qos_dot1p_class: + <<: *aci_qos_dot1p_class_present + register: nm_add_qos_dot1p_class_idempotency + + - name: Add a second QoS Dot1P Class (normal_mode) + cisco.aci.aci_qos_dot1p_class: + <<: *aci_info + tenant: ansible_tenant + qos_custom_policy: ansible_qos_custom_policy_1 + dot1p_from: video + dot1p_to: voice + state: present + register: nm_add_qos_dot1p_class_2 + + - name: Asserts for QoS Dot1P Class creation tasks + ansible.builtin.assert: + that: + - cm_add_qos_dot1p_class is changed + - cm_add_qos_dot1p_class.previous == [] + - cm_add_qos_dot1p_class.current == [] + - nm_add_qos_dot1p_class is changed + - nm_add_qos_dot1p_class.current.0.qosDot1PClass.attributes.prio == "level1" + - nm_add_qos_dot1p_class.current.0.qosDot1PClass.attributes.from == "1" + - nm_add_qos_dot1p_class.current.0.qosDot1PClass.attributes.to == "2" + - nm_add_qos_dot1p_class.current.0.qosDot1PClass.attributes.target == "AF31" + - nm_add_qos_dot1p_class.current.0.qosDot1PClass.attributes.targetCos == "1" + - nm_add_qos_dot1p_class.current.0.qosDot1PClass.attributes.dn == "uni/tn-ansible_tenant/qoscustom-ansible_qos_custom_policy_1/dot1P-1-2" + - nm_add_qos_dot1p_class_idempotency is not changed + - nm_add_qos_dot1p_class_2 is changed + - nm_add_qos_dot1p_class_2.previous == [] + - nm_add_qos_dot1p_class_2.current.0.qosDot1PClass.attributes.prio == "unspecified" + - nm_add_qos_dot1p_class_2.current.0.qosDot1PClass.attributes.from == "4" + - nm_add_qos_dot1p_class_2.current.0.qosDot1PClass.attributes.to == "5" + - nm_add_qos_dot1p_class_2.current.0.qosDot1PClass.attributes.target == "unspecified" + - nm_add_qos_dot1p_class_2.current.0.qosDot1PClass.attributes.targetCos == "unspecified" + - nm_add_qos_dot1p_class_2.current.0.qosDot1PClass.attributes.dn == "uni/tn-ansible_tenant/qoscustom-ansible_qos_custom_policy_1/dot1P-4-5" + + # QUERY QOS Dot1P Class + - name: Query all QoS Custom policies + cisco.aci.aci_qos_dot1p_class: + <<: *aci_info + state: query + register: query_all_qos_dot1p_class + + - name: Query ansible_qos_dot1p_class_1 + cisco.aci.aci_qos_dot1p_class: + <<: *aci_qos_dot1p_class_present + state: query + register: query_ansible_qos_dot1p_class_1 + + - name: Asserts query tasks + ansible.builtin.assert: + that: + - query_all_qos_dot1p_class is not changed + - query_all_qos_dot1p_class.current|length >= 2 + - query_ansible_qos_dot1p_class_1 is not changed + - query_ansible_qos_dot1p_class_1.current.0.qosDot1PClass.attributes.prio == "level1" + - query_ansible_qos_dot1p_class_1.current.0.qosDot1PClass.attributes.from == "1" + - query_ansible_qos_dot1p_class_1.current.0.qosDot1PClass.attributes.to == "2" + - query_ansible_qos_dot1p_class_1.current.0.qosDot1PClass.attributes.target == "AF31" + - query_ansible_qos_dot1p_class_1.current.0.qosDot1PClass.attributes.targetCos == "1" + - query_ansible_qos_dot1p_class_1.current.0.qosDot1PClass.attributes.dn == "uni/tn-ansible_tenant/qoscustom-ansible_qos_custom_policy_1/dot1P-1-2" + + # DELETE QOS Dot1P Class + - name: Remove QoS Dot1P Class (check_mode) + cisco.aci.aci_qos_dot1p_class: &qos_dot1p_class_absent + <<: *aci_qos_dot1p_class_present + state: absent + check_mode: true + register: cm_remove_qos_dot1p_class + + - name: Remove QoS Dot1P Class (normal_mode) + cisco.aci.aci_qos_dot1p_class: + <<: *qos_dot1p_class_absent + register: nm_remove_qos_dot1p_class + + - name: Remove QoS Dot1P Class - testing idempotency + cisco.aci.aci_qos_dot1p_class: + <<: *qos_dot1p_class_absent + register: nm_remove_qos_dot1p_class_idempotency + + - name: Asserts deletion tasks + ansible.builtin.assert: + that: + - cm_remove_qos_dot1p_class is changed + - cm_remove_qos_dot1p_class.proposed == {} + - nm_remove_qos_dot1p_class is changed + - nm_remove_qos_dot1p_class.previous != [] + - nm_remove_qos_dot1p_class.current == [] + - nm_remove_qos_dot1p_class_idempotency is not changed + - nm_remove_qos_dot1p_class_idempotency.previous == [] + + # CLEAN ENVIRONMENT BEFORE ENDING TESTS + - name: Remove the ansible_tenant - cleanup before ending tests + cisco.aci.aci_tenant: + <<: *aci_tenant_present + state: absent diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_qos_dscp_class/aliases b/ansible_collections/cisco/aci/tests/integration/targets/aci_qos_dscp_class/aliases new file mode 100644 index 000000000..209b793f9 --- /dev/null +++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_qos_dscp_class/aliases @@ -0,0 +1,2 @@ +# No ACI simulator yet, so not enabled +# unsupported diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_qos_dscp_class/tasks/main.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_qos_dscp_class/tasks/main.yml new file mode 100644 index 000000000..b64848d05 --- /dev/null +++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_qos_dscp_class/tasks/main.yml @@ -0,0 +1,167 @@ +# Test code for the ACI modules +# Copyright: (c) 2023, Gaspard Micol (@gmicol) + +# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) + +- name: Test that we have an ACI APIC host, ACI username and ACI password + ansible.builtin.fail: + msg: 'Please define the following variables: aci_hostname, aci_username and aci_password.' + when: aci_hostname is not defined or aci_username is not defined or aci_password is not defined + +- name: Set vars + ansible.builtin.set_fact: + aci_info: &aci_info + host: "{{ aci_hostname }}" + username: "{{ aci_username }}" + password: "{{ aci_password }}" + validate_certs: '{{ aci_validate_certs | default(false) }}' + use_ssl: '{{ aci_use_ssl | default(true) }}' + use_proxy: '{{ aci_use_proxy | default(true) }}' + output_level: '{{ aci_output_level | default("info") }}' + +# CLEAN ENVIRONMENT BEFORE TESTS +- name: Remove the ansible_tenant + cisco.aci.aci_tenant: &aci_tenant_absent + <<: *aci_info + tenant: ansible_tenant + state: absent + +- name: Verify Cloud and Non-Cloud Sites in use. + ansible.builtin.include_tasks: ../../../../../../integration/targets/aci_cloud_provider/tasks/main.yml + +- name: Execute tasks only for non-cloud sites + when: query_cloud.current == [] # This condition will execute only non-cloud sites + block: # block specifies execution of tasks within, based on conditions + - name: Add a new tenant + cisco.aci.aci_tenant: &aci_tenant_present + <<: *aci_info + tenant: ansible_tenant + description: Ansible tenant + state: present + + - name: Add a QoS Custom policy + cisco.aci.aci_qos_custom_policy: + <<: *aci_info + tenant: ansible_tenant + qos_custom_policy: ansible_qos_custom_policy_1 + description: QoS Custom policy 1 for ansible_tenant tenant + state: present + + # CREATE QOS DSCP Class + - name: Add a QoS DSCP Class (check_mode) + cisco.aci.aci_qos_dscp_class: &aci_qos_dscp_class_present + <<: *aci_info + tenant: ansible_tenant + qos_custom_policy: ansible_qos_custom_policy_1 + priority: level1 + dscp_from: AF11 + dscp_to: AF21 + dscp_target: AF31 + target_cos: best_effort + state: present + check_mode: true + register: cm_add_qos_dscp_class + + - name: Add a QoS DSCP Class (normal_mode) + cisco.aci.aci_qos_dscp_class: + <<: *aci_qos_dscp_class_present + register: nm_add_qos_dscp_class + + - name: Add the first QoS DSCP Class again - testing idempotency + cisco.aci.aci_qos_dscp_class: + <<: *aci_qos_dscp_class_present + register: nm_add_qos_dscp_class_idempotency + + - name: Add a second QoS DSCP Class (normal_mode) + cisco.aci.aci_qos_dscp_class: + <<: *aci_info + tenant: ansible_tenant + qos_custom_policy: ansible_qos_custom_policy_1 + dscp_from: AF32 + dscp_to: AF42 + state: present + register: nm_add_qos_dscp_class_2 + + - name: Asserts for QoS DSCP Class creation tasks + ansible.builtin.assert: + that: + - cm_add_qos_dscp_class is changed + - cm_add_qos_dscp_class.previous == [] + - cm_add_qos_dscp_class.current == [] + - nm_add_qos_dscp_class is changed + - nm_add_qos_dscp_class.current.0.qosDscpClass.attributes.prio == "level1" + - nm_add_qos_dscp_class.current.0.qosDscpClass.attributes.from == "AF11" + - nm_add_qos_dscp_class.current.0.qosDscpClass.attributes.to == "AF21" + - nm_add_qos_dscp_class.current.0.qosDscpClass.attributes.target == "AF31" + - nm_add_qos_dscp_class.current.0.qosDscpClass.attributes.targetCos == "1" + - nm_add_qos_dscp_class.current.0.qosDscpClass.attributes.dn == "uni/tn-ansible_tenant/qoscustom-ansible_qos_custom_policy_1/dcsp-AF11-AF21" + - nm_add_qos_dscp_class_idempotency is not changed + - nm_add_qos_dscp_class_2 is changed + - nm_add_qos_dscp_class_2.previous == [] + - nm_add_qos_dscp_class_2.current.0.qosDscpClass.attributes.prio == "unspecified" + - nm_add_qos_dscp_class_2.current.0.qosDscpClass.attributes.from == "AF32" + - nm_add_qos_dscp_class_2.current.0.qosDscpClass.attributes.to == "AF42" + - nm_add_qos_dscp_class_2.current.0.qosDscpClass.attributes.target == "unspecified" + - nm_add_qos_dscp_class_2.current.0.qosDscpClass.attributes.targetCos == "unspecified" + - nm_add_qos_dscp_class_2.current.0.qosDscpClass.attributes.dn == "uni/tn-ansible_tenant/qoscustom-ansible_qos_custom_policy_1/dcsp-AF32-AF42" + + # QUERY QOS DSCP Class + - name: Query all QoS Custom policies + cisco.aci.aci_qos_dscp_class: + <<: *aci_info + state: query + register: query_all_qos_dscp_class + + - name: Query ansible_qos_dscp_class_1 + cisco.aci.aci_qos_dscp_class: + <<: *aci_qos_dscp_class_present + state: query + register: query_ansible_qos_dscp_class_1 + + - name: Asserts query tasks + ansible.builtin.assert: + that: + - query_all_qos_dscp_class is not changed + - query_all_qos_dscp_class.current|length >= 2 + - query_ansible_qos_dscp_class_1 is not changed + - query_ansible_qos_dscp_class_1.current.0.qosDscpClass.attributes.prio == "level1" + - query_ansible_qos_dscp_class_1.current.0.qosDscpClass.attributes.from == "AF11" + - query_ansible_qos_dscp_class_1.current.0.qosDscpClass.attributes.to == "AF21" + - query_ansible_qos_dscp_class_1.current.0.qosDscpClass.attributes.target == "AF31" + - query_ansible_qos_dscp_class_1.current.0.qosDscpClass.attributes.targetCos == "1" + - query_ansible_qos_dscp_class_1.current.0.qosDscpClass.attributes.dn == "uni/tn-ansible_tenant/qoscustom-ansible_qos_custom_policy_1/dcsp-AF11-AF21" + + # DELETE QOS DSCP Class + - name: Remove QoS DSCP Class (check_mode) + cisco.aci.aci_qos_dscp_class: &qos_dscp_class_absent + <<: *aci_qos_dscp_class_present + state: absent + check_mode: true + register: cm_remove_qos_dscp_class + + - name: Remove QoS DSCP Class (normal_mode) + cisco.aci.aci_qos_dscp_class: + <<: *qos_dscp_class_absent + register: nm_remove_qos_dscp_class + + - name: Remove QoS DSCP Class - testing idempotency + cisco.aci.aci_qos_dscp_class: + <<: *qos_dscp_class_absent + register: nm_remove_qos_dscp_class_idempotency + + - name: Asserts deletion tasks + ansible.builtin.assert: + that: + - cm_remove_qos_dscp_class is changed + - cm_remove_qos_dscp_class.proposed == {} + - nm_remove_qos_dscp_class is changed + - nm_remove_qos_dscp_class.previous != [] + - nm_remove_qos_dscp_class.current == [] + - nm_remove_qos_dscp_class_idempotency is not changed + - nm_remove_qos_dscp_class_idempotency.previous == [] + + # CLEAN ENVIRONMENT BEFORE ENDING TESTS + - name: Remove the ansible_tenant - cleanup before ending tests + cisco.aci.aci_tenant: + <<: *aci_tenant_present + state: absent diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_rest/tasks/error_handling.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_rest/tasks/error_handling.yml index 49c6fca53..2ea77b46f 100644 --- a/ansible_collections/cisco/aci/tests/integration/targets/aci_rest/tasks/error_handling.yml +++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_rest/tasks/error_handling.yml @@ -24,7 +24,7 @@ register: error_on_name_resolution - name: Verify error_on_name_resolution - assert: + ansible.builtin.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.") @@ -51,7 +51,7 @@ register: error_on_missing_required_param - name: Verify error_on_missing_required_param - assert: + ansible.builtin.assert: that: - error_on_missing_required_param is failed - 'error_on_missing_required_param.msg == "missing required arguments: path"' @@ -78,7 +78,7 @@ register: error_on_missing_attributes - name: Verify error_on_missing_attributes - assert: + ansible.builtin.assert: that: - error_on_missing_attributes is failed - error_on_missing_attributes.method == 'POST' @@ -110,11 +110,11 @@ register: error_on_input_validation - name: Verify error_on_input_validation - assert: + ansible.builtin.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.msg is ansible.builtin.regex('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" @@ -142,7 +142,7 @@ register: error_on_invalid_attributes - name: Verify error_on_invalid_attributes - assert: + ansible.builtin.assert: that: - error_on_invalid_attributes is failed - error_on_invalid_attributes.method == 'POST' @@ -173,7 +173,7 @@ register: error_on_invalid_object - name: Verify error_on_invalid_object - assert: + ansible.builtin.assert: that: - error_on_invalid_object is failed - error_on_invalid_object.method == 'POST' @@ -314,7 +314,7 @@ register: err_fail_parse_json - name: Assertions checks for import error handling, invalid src, invalid path extension and parse failures - assert: + ansible.builtin.assert: that: - err_missing_lxml.msg == "The lxml python library is missing, or lacks etree support." - err_missing_xmljson.msg == "The xmljson python library is missing, or lacks cobra support." diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_rest/tasks/json_inline.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_rest/tasks/json_inline.yml index 3d5c9be48..74711ffed 100644 --- a/ansible_collections/cisco/aci/tests/integration/targets/aci_rest/tasks/json_inline.yml +++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_rest/tasks/json_inline.yml @@ -54,10 +54,11 @@ register: cm_verify_checkmode_tenant - name: Verify checkmode POST operation - assert: + ansible.builtin.assert: that: - cm_add_tenant is changed - cm_add_tenant.proposed.fvTenant.attributes.name == "ansible_test" + - cm_add_tenant.proposed.fvTenant.attributes.annotation == "orchestrator:ansible" - cm_verify_checkmode_tenant.current == [] - name: Add tenant (normal mode) @@ -69,9 +70,10 @@ register: nm_add_tenant_again - name: Verify add_tenant - assert: + ansible.builtin.assert: that: - nm_add_tenant is changed + - nm_add_tenant.imdata.0.fvTenant.attributes.annotation == "orchestrator:ansible" - nm_add_tenant_again is not changed # CHANGE TENANT @@ -102,7 +104,7 @@ register: nm_add_tenant_descr_again - name: Verify add_tenant_descr - assert: + ansible.builtin.assert: that: - nm_add_tenant_descr is changed - nm_add_tenant_descr_again is not changed @@ -113,7 +115,7 @@ register: nm_add_tenant_again_no_descr - name: Verify add_tenant_again_no_descr - assert: + ansible.builtin.assert: that: - nm_add_tenant_again_no_descr is not changed @@ -132,7 +134,7 @@ register: nm_query_all_tenants - name: Verify query_all_tenants - assert: + ansible.builtin.assert: that: - nm_query_all_tenants is not changed @@ -151,7 +153,7 @@ register: nm_query_tenant - name: Verify query_tenant - assert: + ansible.builtin.assert: that: - nm_query_tenant is not changed @@ -165,7 +167,7 @@ register: nm_remove_tenant_again - name: Verify remove_tenant - assert: + ansible.builtin.assert: that: - nm_remove_tenant is changed - nm_remove_tenant_again is not changed @@ -176,6 +178,163 @@ register: nm_query_non_tenant - name: Verify query_non_tenant - assert: + ansible.builtin.assert: that: - nm_query_non_tenant is not changed + +# VERIFY ANNOTATION SUPPORT +- name: Add tenant with annotation option + cisco.aci.aci_rest: + host: '{{ aci_hostname }}' + username: '{{ aci_username }}' + password: '{{ aci_password }}' + validate_certs: '{{ aci_validate_certs | default(false) }}' + use_ssl: '{{ aci_use_ssl | default(true) }}' + use_proxy: '{{ aci_use_proxy | default(true) }}' + output_level: '{{ aci_output_level | default("info") }}' + path: /api/mo/uni.json + method: post + annotation: test:inoption + content: + { + "fvTenant": { + "attributes": { + "descr": "Ansible test tenant", + "name": "ansible_test" + } + } + } + register: nm_add_tenant_annotation_option + +- name: Add tenant with annotation in content + cisco.aci.aci_rest: + host: '{{ aci_hostname }}' + username: '{{ aci_username }}' + password: '{{ aci_password }}' + validate_certs: '{{ aci_validate_certs | default(false) }}' + use_ssl: '{{ aci_use_ssl | default(true) }}' + use_proxy: '{{ aci_use_proxy | default(true) }}' + output_level: '{{ aci_output_level | default("info") }}' + path: /api/mo/uni.json + method: post + content: + { + "fvTenant": { + "attributes": { + "descr": "Ansible test tenant", + "name": "ansible_test", + "annotation": "test:incontent" + } + } + } + register: nm_add_tenant_annotation_content + +- name: Add tenant with annotation in content and option + cisco.aci.aci_rest: + host: '{{ aci_hostname }}' + username: '{{ aci_username }}' + password: '{{ aci_password }}' + validate_certs: '{{ aci_validate_certs | default(false) }}' + use_ssl: '{{ aci_use_ssl | default(true) }}' + use_proxy: '{{ aci_use_proxy | default(true) }}' + output_level: '{{ aci_output_level | default("info") }}' + path: /api/mo/uni.json + method: post + annotation: test:inoption + content: + { + "fvTenant": { + "attributes": { + "descr": "Ansible test tenant", + "name": "ansible_test", + "annotation": "test:optionincontent" + } + } + } + register: nm_add_tenant_annotation_option_content + +- name: Add tag to tenant with annotation unsupported + cisco.aci.aci_rest: + host: '{{ aci_hostname }}' + username: '{{ aci_username }}' + password: '{{ aci_password }}' + validate_certs: '{{ aci_validate_certs | default(false) }}' + use_ssl: '{{ aci_use_ssl | default(true) }}' + use_proxy: '{{ aci_use_proxy | default(true) }}' + output_level: '{{ aci_output_level | default("info") }}' + path: /api/mo/uni/tn-ansible_test/tagKey-foo.json + method: post + annotation: test:inoption + content: + { + "tagTag": { + "attributes": { + "value": "bar" + } + } + } + register: nm_add_tag_no_annotation + +- name: Remove tenant + cisco.aci.aci_rest: *tenant_absent + +- name: Add tenant with children objects including annotation + cisco.aci.aci_rest: + host: '{{ aci_hostname }}' + username: '{{ aci_username }}' + password: '{{ aci_password }}' + validate_certs: '{{ aci_validate_certs | default(false) }}' + use_ssl: '{{ aci_use_ssl | default(true) }}' + use_proxy: '{{ aci_use_proxy | default(true) }}' + output_level: '{{ aci_output_level | default("info") }}' + path: /api/mo/uni.json + method: post + annotation: test:inoption + content: + { + "fvTenant": { + "attributes": { + "descr": "Ansible test tenant", + "name": "ansible_test" + }, + "children": [ + { + "fvCtx": { + "attributes": { + "name": "VRF1" + } + } + }, + { + "fvAp": { + "attributes": { + "name": "Application1" + }, + "children": [ + { + "fvAEPg": { + "attributes": { + "name": "WebTier", + "annotation": "test:inchild" + } + } + } + ] + } + } + ] + } + } + register: nm_add_tenant_annotation_children + +- name: Verify annotation support + assert: + that: + - nm_add_tenant_annotation_option.imdata.0.fvTenant.attributes.annotation == "test:inoption" + - nm_add_tenant_annotation_content.imdata.0.fvTenant.attributes.annotation == "test:incontent" + - nm_add_tenant_annotation_option_content.imdata.0.fvTenant.attributes.annotation == "test:optionincontent" + - nm_add_tag_no_annotation.imdata.0.tagTag.attributes.annotation is undefined + - nm_add_tenant_annotation_children.imdata.0.fvTenant.attributes.annotation == "test:inoption" + - nm_add_tenant_annotation_children.imdata.0.fvTenant.children.0.fvAp.attributes.annotation == "test:inoption" + - nm_add_tenant_annotation_children.imdata.0.fvTenant.children.0.fvAp.children.0.fvAEPg.attributes.annotation == "test:inchild" + - nm_add_tenant_annotation_children.imdata.0.fvTenant.children.2.fvCtx.attributes.annotation == "test:inoption" \ No newline at end of file diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_rest/tasks/json_string.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_rest/tasks/json_string.yml index 7a1dfd8ce..9efa19c71 100644 --- a/ansible_collections/cisco/aci/tests/integration/targets/aci_rest/tasks/json_string.yml +++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_rest/tasks/json_string.yml @@ -55,10 +55,11 @@ register: cm_verify_checkmode_tenant - name: Verify checkmode POST operation - assert: + ansible.builtin.assert: that: - cm_add_tenant is changed - cm_add_tenant.proposed.fvTenant.attributes.name == "ansible_test" + - cm_add_tenant.proposed.fvTenant.attributes.annotation == "orchestrator:ansible" - cm_verify_checkmode_tenant.current == [] - name: Add tenant (normal mode) @@ -70,9 +71,10 @@ register: nm_add_tenant_again - name: Verify add_tenant - assert: + ansible.builtin.assert: that: - nm_add_tenant is changed + - nm_add_tenant.imdata.0.fvTenant.attributes.annotation == "orchestrator:ansible" - nm_add_tenant_again is not changed # CHANGE TENANT @@ -103,7 +105,7 @@ register: nm_add_tenant_descr_again - name: Verify add_tenant_descr - assert: + ansible.builtin.assert: that: - nm_add_tenant_descr is changed - nm_add_tenant_descr_again is not changed @@ -114,7 +116,7 @@ register: nm_add_tenant_again_no_descr - name: Verify add_tenant_again_no_descr - assert: + ansible.builtin.assert: that: - nm_add_tenant_again_no_descr is not changed @@ -133,7 +135,7 @@ register: nm_query_all_tenants - name: Verify query_all_tenants - assert: + ansible.builtin.assert: that: - nm_query_all_tenants is not changed @@ -152,7 +154,7 @@ register: nm_query_tenant - name: Verify query_tenant - assert: + ansible.builtin.assert: that: - nm_query_tenant is not changed @@ -166,7 +168,7 @@ register: nm_remove_tenant_again - name: Verify remove_tenant - assert: + ansible.builtin.assert: that: - nm_remove_tenant is changed - nm_remove_tenant_again is not changed @@ -177,6 +179,163 @@ register: nm_query_non_tenant - name: Verify query_non_tenant - assert: + ansible.builtin.assert: that: - nm_query_non_tenant is not changed + +# VERIFY ANNOTATION SUPPORT +- name: Add tenant with annotation option + cisco.aci.aci_rest: + host: '{{ aci_hostname }}' + username: '{{ aci_username }}' + password: '{{ aci_password }}' + validate_certs: '{{ aci_validate_certs | default(false) }}' + use_ssl: '{{ aci_use_ssl | default(true) }}' + use_proxy: '{{ aci_use_proxy | default(true) }}' + output_level: '{{ aci_output_level | default("info") }}' + path: /api/mo/uni.json + method: post + annotation: test:inoption + content: | + { + "fvTenant": { + "attributes": { + "descr": "Ansible test tenant", + "name": "ansible_test" + } + } + } + register: nm_add_tenant_annotation_option + +- name: Add tenant with annotation in content + cisco.aci.aci_rest: + host: '{{ aci_hostname }}' + username: '{{ aci_username }}' + password: '{{ aci_password }}' + validate_certs: '{{ aci_validate_certs | default(false) }}' + use_ssl: '{{ aci_use_ssl | default(true) }}' + use_proxy: '{{ aci_use_proxy | default(true) }}' + output_level: '{{ aci_output_level | default("info") }}' + path: /api/mo/uni.json + method: post + content: | + { + "fvTenant": { + "attributes": { + "descr": "Ansible test tenant", + "name": "ansible_test", + "annotation": "test:incontent" + } + } + } + register: nm_add_tenant_annotation_content + +- name: Add tenant with annotation in content and option + cisco.aci.aci_rest: + host: '{{ aci_hostname }}' + username: '{{ aci_username }}' + password: '{{ aci_password }}' + validate_certs: '{{ aci_validate_certs | default(false) }}' + use_ssl: '{{ aci_use_ssl | default(true) }}' + use_proxy: '{{ aci_use_proxy | default(true) }}' + output_level: '{{ aci_output_level | default("info") }}' + path: /api/mo/uni.json + method: post + annotation: test:inoption + content: | + { + "fvTenant": { + "attributes": { + "descr": "Ansible test tenant", + "name": "ansible_test", + "annotation": "test:optionincontent" + } + } + } + register: nm_add_tenant_annotation_option_content + +- name: Add tag to tenant with annotation unsupported + cisco.aci.aci_rest: + host: '{{ aci_hostname }}' + username: '{{ aci_username }}' + password: '{{ aci_password }}' + validate_certs: '{{ aci_validate_certs | default(false) }}' + use_ssl: '{{ aci_use_ssl | default(true) }}' + use_proxy: '{{ aci_use_proxy | default(true) }}' + output_level: '{{ aci_output_level | default("info") }}' + path: /api/mo/uni/tn-ansible_test/tagKey-foo.json + method: post + annotation: test:inoption + content: | + { + "tagTag": { + "attributes": { + "value": "bar" + } + } + } + register: nm_add_tag_no_annotation + +- name: Remove tenant + cisco.aci.aci_rest: *tenant_absent + +- name: Add tenant with children objects including annotation + cisco.aci.aci_rest: + host: '{{ aci_hostname }}' + username: '{{ aci_username }}' + password: '{{ aci_password }}' + validate_certs: '{{ aci_validate_certs | default(false) }}' + use_ssl: '{{ aci_use_ssl | default(true) }}' + use_proxy: '{{ aci_use_proxy | default(true) }}' + output_level: '{{ aci_output_level | default("info") }}' + path: /api/mo/uni.json + method: post + annotation: test:inoption + content: | + { + "fvTenant": { + "attributes": { + "descr": "Ansible test tenant", + "name": "ansible_test" + }, + "children": [ + { + "fvCtx": { + "attributes": { + "name": "VRF1" + } + } + }, + { + "fvAp": { + "attributes": { + "name": "Application1" + }, + "children": [ + { + "fvAEPg": { + "attributes": { + "name": "WebTier", + "annotation": "test:inchild" + } + } + } + ] + } + } + ] + } + } + register: nm_add_tenant_annotation_children + +- name: Verify annotation support + assert: + that: + - nm_add_tenant_annotation_option.imdata.0.fvTenant.attributes.annotation == "test:inoption" + - nm_add_tenant_annotation_content.imdata.0.fvTenant.attributes.annotation == "test:incontent" + - nm_add_tenant_annotation_option_content.imdata.0.fvTenant.attributes.annotation == "test:optionincontent" + - nm_add_tag_no_annotation.imdata.0.tagTag.attributes.annotation is undefined + - nm_add_tenant_annotation_children.imdata.0.fvTenant.attributes.annotation == "test:inoption" + - nm_add_tenant_annotation_children.imdata.0.fvTenant.children.0.fvAp.attributes.annotation == "test:inoption" + - nm_add_tenant_annotation_children.imdata.0.fvTenant.children.0.fvAp.children.0.fvAEPg.attributes.annotation == "test:inchild" + - nm_add_tenant_annotation_children.imdata.0.fvTenant.children.2.fvCtx.attributes.annotation == "test:inoption" \ No newline at end of file diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_rest/tasks/main.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_rest/tasks/main.yml index c06f0cee2..c0055bbd3 100644 --- a/ansible_collections/cisco/aci/tests/integration/targets/aci_rest/tasks/main.yml +++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_rest/tasks/main.yml @@ -5,7 +5,7 @@ # GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) - name: Test that we have an ACI APIC host, ACI username and ACI password - fail: + ansible.builtin.fail: msg: 'Please define the following variables: aci_hostname, aci_username and aci_password.' when: aci_hostname is not defined or aci_username is not defined or aci_password is not defined diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_rest/tasks/xml_file.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_rest/tasks/xml_file.yml index fea63112b..6b3ffc841 100644 --- a/ansible_collections/cisco/aci/tests/integration/targets/aci_rest/tasks/xml_file.yml +++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_rest/tasks/xml_file.yml @@ -5,7 +5,7 @@ # SET VARS - name: Set vars - set_fact: + ansible.builtin.set_fact: aci_info: &aci_info host: '{{ aci_hostname }}' username: '{{ aci_username }}' @@ -17,7 +17,7 @@ output_path: "/tmp/ansible_output_file.log" - name: Ensure tenant does not exists using ans_test_delete xml template - cisco.aci.aci_rest: + cisco.aci.aci_rest: &tenant_delete <<: *aci_info path: /api/mo/uni.xml src: "./targets/aci_rest/tasks/xml_files/tn-ans_test_delete.xml" @@ -46,10 +46,11 @@ register: cm_verify_checkmode_tenant - name: Assertions check for add tenant using ans_test_create xml template file with check mode - assert: + ansible.builtin.assert: that: - cm_add_tenant is changed - '"ans_test_create" in cm_add_tenant.proposed' + - '"orchestrator:ansible" in cm_add_tenant.proposed' - cm_verify_checkmode_tenant.current == [] - name: Add tenant using ans_test_create xml template file with normal mode @@ -61,12 +62,13 @@ register: nm_add_tenant - name: Assertions check for add tenant using ans_test_create xml template file with normal mode - assert: + ansible.builtin.assert: that: - nm_add_tenant is changed - nm_add_tenant.imdata.0.fvTenant.attributes.name == "ans_test_create" - nm_add_tenant.imdata.0.fvTenant.attributes.descr == "ans_test_create tenant created successfully" - nm_add_tenant.imdata.0.fvTenant.attributes.dn == "uni/tn-ans_test_create" + - nm_add_tenant.imdata.0.fvTenant.attributes.annotation == "orchestrator:ansible" - nm_add_tenant.imdata.0.fvTenant.children != [] - name: Add tenant using ans_test_create xml template file with normal mode - idempotency works @@ -78,7 +80,7 @@ register: idempotency_nm_add_tenant - name: Idempotency assertions check for add tenant using ans_test_create xml template file with normal mode - assert: + ansible.builtin.assert: that: - idempotency_nm_add_tenant is not changed @@ -90,7 +92,7 @@ register: query_ans_test_create - name: Assertions check for querying ans_test_create tenant using query string after the create - assert: + ansible.builtin.assert: that: - query_ans_test_create is not changed - query_ans_test_create.imdata != [] @@ -108,7 +110,7 @@ register: cm_update_tenant - name: Assertions check for update tenant description using ans_test_update xml template file with check mode - assert: + ansible.builtin.assert: that: - cm_update_tenant is changed @@ -121,7 +123,7 @@ register: nm_update_tenant - name: Assertions check for update tenant description using ans_test_update xml template file with normal mode - assert: + ansible.builtin.assert: that: - nm_update_tenant is changed - nm_update_tenant.imdata.0.fvTenant.attributes.name == "ans_test_create" @@ -137,7 +139,7 @@ register: idempotency_nm_update_tenant - name: Idempotency assertions check for update tenant description using ans_test_update xml template file with normal mode - assert: + ansible.builtin.assert: that: - idempotency_nm_update_tenant is not changed @@ -149,7 +151,7 @@ register: query_ans_test_update - name: Assertions check for querying ans_test_create tenant using query string after the update - assert: + ansible.builtin.assert: that: - query_ans_test_update is not changed - query_ans_test_update.imdata != [] @@ -167,7 +169,7 @@ ignore_errors: true - name: Assertions check for update tenant name using ans_test_negative_update_check xml template file with normal mode - assert: + ansible.builtin.assert: that: - negative_update_tenant_check is failed @@ -181,7 +183,7 @@ register: cm_delete_tenant - name: Assertions check for delete tenant using ans_test_delete xml template file with check mode - assert: + ansible.builtin.assert: that: - cm_delete_tenant is changed @@ -194,7 +196,7 @@ register: nm_delete_tenant - name: Assertions check for delete tenant using ans_test_delete xml template file with normal mode - assert: + ansible.builtin.assert: that: - nm_delete_tenant is changed - nm_delete_tenant.imdata.0.fvTenant.attributes.name == "ans_test_create" @@ -210,7 +212,7 @@ register: idempotency_nm_delete_tenant - name: Idempotency assertions check for delete tenant using ans_test_delete xml template file with normal mode - assert: + ansible.builtin.assert: that: - idempotency_nm_delete_tenant is not changed - idempotency_nm_delete_tenant.imdata == {} @@ -223,7 +225,100 @@ register: query_ans_test_delete - name: Assertions check for querying ans_test_create tenant using query string after the delete - assert: + ansible.builtin.assert: that: - query_ans_test_delete is not changed - query_ans_test_delete.imdata == [] + +# VERIFY ANNOTATION SUPPORT +- name: Add tenant with annotation option + cisco.aci.aci_rest: + host: '{{ aci_hostname }}' + username: '{{ aci_username }}' + password: '{{ aci_password }}' + validate_certs: '{{ aci_validate_certs | default(false) }}' + use_ssl: '{{ aci_use_ssl | default(true) }}' + use_proxy: '{{ aci_use_proxy | default(true) }}' + output_level: '{{ aci_output_level | default("info") }}' + path: /api/mo/uni.xml + method: post + annotation: test:inoption + src: "./targets/aci_rest/tasks/xml_files/tn-ans_test_create.xml" + register: nm_add_tenant_annotation_option + +- name: Add tenant with annotation in content + cisco.aci.aci_rest: + host: '{{ aci_hostname }}' + username: '{{ aci_username }}' + password: '{{ aci_password }}' + validate_certs: '{{ aci_validate_certs | default(false) }}' + use_ssl: '{{ aci_use_ssl | default(true) }}' + use_proxy: '{{ aci_use_proxy | default(true) }}' + output_level: '{{ aci_output_level | default("info") }}' + path: /api/mo/uni.xml + method: post + src: "./targets/aci_rest/tasks/xml_files/tn-ans_test_annotation.xml" + register: nm_add_tenant_annotation_content + +- name: Remove tenant + cisco.aci.aci_rest: *tenant_delete + +- name: Add tenant with annotation in content and option + cisco.aci.aci_rest: + host: '{{ aci_hostname }}' + username: '{{ aci_username }}' + password: '{{ aci_password }}' + validate_certs: '{{ aci_validate_certs | default(false) }}' + use_ssl: '{{ aci_use_ssl | default(true) }}' + use_proxy: '{{ aci_use_proxy | default(true) }}' + output_level: '{{ aci_output_level | default("info") }}' + path: /api/mo/uni.xml + method: post + annotation: test:inoption + src: "./targets/aci_rest/tasks/xml_files/tn-ans_test_annotation.xml" + register: nm_add_tenant_annotation_option_content + +- name: Add tag to tenant with annotation unsupported + cisco.aci.aci_rest: + host: '{{ aci_hostname }}' + username: '{{ aci_username }}' + password: '{{ aci_password }}' + validate_certs: '{{ aci_validate_certs | default(false) }}' + use_ssl: '{{ aci_use_ssl | default(true) }}' + use_proxy: '{{ aci_use_proxy | default(true) }}' + output_level: '{{ aci_output_level | default("info") }}' + path: /api/mo/uni/tn-ans_test_create/tagKey-foo.xml + method: post + annotation: test:inoption + src: "./targets/aci_rest/tasks/xml_files/tag.xml" + register: nm_add_tag_no_annotation + +- name: Remove tenant + cisco.aci.aci_rest: *tenant_delete + +- name: Add tenant with children objects including annotation + cisco.aci.aci_rest: + host: '{{ aci_hostname }}' + username: '{{ aci_username }}' + password: '{{ aci_password }}' + validate_certs: '{{ aci_validate_certs | default(false) }}' + use_ssl: '{{ aci_use_ssl | default(true) }}' + use_proxy: '{{ aci_use_proxy | default(true) }}' + output_level: '{{ aci_output_level | default("info") }}' + path: /api/mo/uni.xml + method: post + annotation: test:inoption + src: "./targets/aci_rest/tasks/xml_files/tn-ans_test_annotation_children.xml" + register: nm_add_tenant_annotation_children + +- name: Verify annotation support + assert: + that: + - nm_add_tenant_annotation_option.imdata.0.fvTenant.attributes.annotation == "test:inoption" + - nm_add_tenant_annotation_content.imdata.0.fvTenant.attributes.annotation == "test:optionincontent" + - nm_add_tenant_annotation_option_content.imdata.0.fvTenant.attributes.annotation == "test:optionincontent" + - nm_add_tag_no_annotation.imdata.0.tagTag.attributes.annotation is undefined + - nm_add_tenant_annotation_children.imdata.0.fvTenant.attributes.annotation == "test:inoption" + - nm_add_tenant_annotation_children.imdata.0.fvTenant.children.0.fvAp.attributes.annotation == "test:inoption" + - nm_add_tenant_annotation_children.imdata.0.fvTenant.children.0.fvAp.children.0.fvAEPg.attributes.annotation == "test:inchild" + - nm_add_tenant_annotation_children.imdata.0.fvTenant.children.1.fvCtx.attributes.annotation == "test:inoption" \ No newline at end of file diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_rest/tasks/xml_files/tag.xml b/ansible_collections/cisco/aci/tests/integration/targets/aci_rest/tasks/xml_files/tag.xml new file mode 100644 index 000000000..f5918f0e3 --- /dev/null +++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_rest/tasks/xml_files/tag.xml @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_rest/tasks/xml_files/tn-ans_test_annotation.xml b/ansible_collections/cisco/aci/tests/integration/targets/aci_rest/tasks/xml_files/tn-ans_test_annotation.xml new file mode 100644 index 000000000..281e6e282 --- /dev/null +++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_rest/tasks/xml_files/tn-ans_test_annotation.xml @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_rest/tasks/xml_files/tn-ans_test_annotation_children.xml b/ansible_collections/cisco/aci/tests/integration/targets/aci_rest/tasks/xml_files/tn-ans_test_annotation_children.xml new file mode 100644 index 000000000..448998bf6 --- /dev/null +++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_rest/tasks/xml_files/tn-ans_test_annotation_children.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_rest/tasks/xml_string.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_rest/tasks/xml_string.yml index d1424bafa..e3e627e3e 100644 --- a/ansible_collections/cisco/aci/tests/integration/targets/aci_rest/tasks/xml_string.yml +++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_rest/tasks/xml_string.yml @@ -70,12 +70,14 @@ register: cm_verify_checkmode_tenant - name: Verify checkmode POST operation - assert: + ansible.builtin.assert: that: - cm_add_tenant is changed - '"ansible_test" in cm_add_tenant.proposed' + - '"orchestrator:ansible" in cm_add_tenant.proposed' - cm_add_tenant_2 is changed - - '"ansible_test" in cm_add_tenant.proposed' + - '"ansible_test" in cm_add_tenant_2.proposed' + - '"orchestrator:ansible" in cm_add_tenant_2.proposed' - cm_verify_checkmode_tenant.current == [] - name: Add tenant (normal mode) @@ -108,7 +110,7 @@ register: nm_add_tenant_again - name: Verify add_tenant - assert: + ansible.builtin.assert: that: - nm_add_tenant is changed - nm_add_tenant_again is not changed @@ -144,7 +146,7 @@ register: nm_add_tenant_descr_again - name: Verify add_tenant_descr - assert: + ansible.builtin.assert: that: - nm_add_tenant_descr is changed - nm_add_tenant_descr_again is not changed @@ -159,7 +161,7 @@ register: nm_add_tenant_again_no_descr - name: Verify add_tenant_again_no_descr - assert: + ansible.builtin.assert: that: - nm_add_tenant_again_no_descr is not changed @@ -178,7 +180,7 @@ register: nm_query_all_tenants - name: Verify query_all_tenants - assert: + ansible.builtin.assert: that: - nm_query_all_tenants is not changed @@ -197,7 +199,7 @@ register: nm_query_tenant - name: Verify query_tenant - assert: + ansible.builtin.assert: that: - nm_query_tenant is not changed @@ -211,7 +213,7 @@ register: nm_remove_tenant_again - name: Verify remove_tenant - assert: + ansible.builtin.assert: that: - nm_remove_tenant is changed - nm_remove_tenant_again is not changed @@ -222,6 +224,123 @@ register: nm_query_non_tenant - name: Verify query_non_tenant - assert: + ansible.builtin.assert: that: - nm_query_non_tenant is not changed + +# VERIFY ANNOTATION +- name: Add tenant with annotation (normal mode) + cisco.aci.aci_rest: &tenant_annotation + host: '{{ aci_hostname }}' + username: '{{ aci_username }}' + password: '{{ aci_password }}' + validate_certs: '{{ aci_validate_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 + annotation: test:label + content: + + register: nm_add_tenant_annotation + +# VERIFY ANNOTATION SUPPORT +- name: Add tenant with annotation option + cisco.aci.aci_rest: + host: '{{ aci_hostname }}' + username: '{{ aci_username }}' + password: '{{ aci_password }}' + validate_certs: '{{ aci_validate_certs | default(false) }}' + use_ssl: '{{ aci_use_ssl | default(true) }}' + use_proxy: '{{ aci_use_proxy | default(true) }}' + output_level: '{{ aci_output_level | default("info") }}' + path: /api/mo/uni.xml + method: post + annotation: test:inoption + content: + + register: nm_add_tenant_annotation_option + +- name: Add tenant with annotation in content + cisco.aci.aci_rest: + host: '{{ aci_hostname }}' + username: '{{ aci_username }}' + password: '{{ aci_password }}' + validate_certs: '{{ aci_validate_certs | default(false) }}' + use_ssl: '{{ aci_use_ssl | default(true) }}' + use_proxy: '{{ aci_use_proxy | default(true) }}' + output_level: '{{ aci_output_level | default("info") }}' + path: /api/mo/uni.xml + method: post + content: + + register: nm_add_tenant_annotation_content + +- name: Add tenant with annotation in content and option + cisco.aci.aci_rest: + host: '{{ aci_hostname }}' + username: '{{ aci_username }}' + password: '{{ aci_password }}' + validate_certs: '{{ aci_validate_certs | default(false) }}' + use_ssl: '{{ aci_use_ssl | default(true) }}' + use_proxy: '{{ aci_use_proxy | default(true) }}' + output_level: '{{ aci_output_level | default("info") }}' + path: /api/mo/uni.xml + method: post + annotation: test:inoption + content: + + register: nm_add_tenant_annotation_option_content + +- name: Add tag to tenant with annotation unsupported + cisco.aci.aci_rest: + host: '{{ aci_hostname }}' + username: '{{ aci_username }}' + password: '{{ aci_password }}' + validate_certs: '{{ aci_validate_certs | default(false) }}' + use_ssl: '{{ aci_use_ssl | default(true) }}' + use_proxy: '{{ aci_use_proxy | default(true) }}' + output_level: '{{ aci_output_level | default("info") }}' + path: /api/mo/uni/tn-ansible_test/tagKey-foo.xml + method: post + annotation: test:inoption + content: + + register: nm_add_tag_no_annotation + +- name: Remove tenant + cisco.aci.aci_rest: *tenant_absent + +- name: Add tenant with children objects including annotation + cisco.aci.aci_rest: + host: '{{ aci_hostname }}' + username: '{{ aci_username }}' + password: '{{ aci_password }}' + validate_certs: '{{ aci_validate_certs | default(false) }}' + use_ssl: '{{ aci_use_ssl | default(true) }}' + use_proxy: '{{ aci_use_proxy | default(true) }}' + output_level: '{{ aci_output_level | default("info") }}' + path: /api/mo/uni.xml + method: post + annotation: test:inoption + content: + + + + + + + register: nm_add_tenant_annotation_children + +- name: Verify annotation support + assert: + that: + - nm_add_tenant_annotation_option.imdata.0.fvTenant.attributes.annotation == "test:inoption" + - nm_add_tenant_annotation_content.imdata.0.fvTenant.attributes.annotation == "test:incontent" + - nm_add_tenant_annotation_option_content.imdata.0.fvTenant.attributes.annotation == "test:optionincontent" + - nm_add_tag_no_annotation.imdata.0.tagTag.attributes.annotation is undefined + - nm_add_tenant_annotation_children.imdata.0.fvTenant.attributes.annotation == "test:inoption" + - nm_add_tenant_annotation_children.imdata.0.fvTenant.children.0.fvAp.attributes.annotation == "test:inoption" + - nm_add_tenant_annotation_children.imdata.0.fvTenant.children.0.fvAp.children.0.fvAEPg.attributes.annotation == "test:inchild" + - nm_add_tenant_annotation_children.imdata.0.fvTenant.children.1.fvCtx.attributes.annotation == "test:inoption" \ No newline at end of file diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_rest/tasks/yaml_inline.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_rest/tasks/yaml_inline.yml index 6cd06afcd..3d0ca07d8 100644 --- a/ansible_collections/cisco/aci/tests/integration/targets/aci_rest/tasks/yaml_inline.yml +++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_rest/tasks/yaml_inline.yml @@ -50,10 +50,11 @@ register: cm_verify_checkmode_tenant - name: Verify checkmode POST operation - assert: + ansible.builtin.assert: that: - cm_add_tenant is changed - cm_add_tenant.proposed.fvTenant.attributes.name == "ansible_test" + - cm_add_tenant.proposed.fvTenant.attributes.annotation == "orchestrator:ansible" - cm_verify_checkmode_tenant.current == [] - name: Add tenant (normal mode) @@ -65,7 +66,7 @@ register: nm_add_tenant_again - name: Verify add_tenant - assert: + ansible.builtin.assert: that: - nm_add_tenant is changed - nm_add_tenant_again is not changed @@ -94,9 +95,10 @@ register: nm_add_tenant_descr_again - name: Verify add_tenant_descr - assert: + ansible.builtin.assert: that: - nm_add_tenant_descr is changed + - nm_add_tenant.imdata.0.fvTenant.attributes.annotation == "orchestrator:ansible" - nm_add_tenant_descr_again is not changed # ADD TENANT AGAIN @@ -105,7 +107,7 @@ register: nm_add_tenant_again_no_descr - name: Verify add_tenant_again_no_descr - assert: + ansible.builtin.assert: that: - nm_add_tenant_again_no_descr is not changed @@ -124,7 +126,7 @@ register: nm_query_all_tenants - name: Verify query_all_tenants - assert: + ansible.builtin.assert: that: - nm_query_all_tenants is not changed @@ -143,7 +145,7 @@ register: nm_query_tenant - name: Verify query_tenant - assert: + ansible.builtin.assert: that: - nm_query_tenant is not changed @@ -157,7 +159,7 @@ register: nm_remove_tenant_again - name: Verify remove_tenant - assert: + ansible.builtin.assert: that: - nm_remove_tenant is changed - nm_remove_tenant_again is not changed @@ -168,6 +170,129 @@ register: nm_query_non_tenant - name: Verify query_non_tenant - assert: + ansible.builtin.assert: that: - nm_query_non_tenant is not changed + +# VERIFY ANNOTATION SUPPORT +- name: Add tenant with annotation option + cisco.aci.aci_rest: + host: '{{ aci_hostname }}' + username: '{{ aci_username }}' + password: '{{ aci_password }}' + validate_certs: '{{ aci_validate_certs | default(false) }}' + use_ssl: '{{ aci_use_ssl | default(true) }}' + use_proxy: '{{ aci_use_proxy | default(true) }}' + output_level: '{{ aci_output_level | default("info") }}' + path: /api/mo/uni.json + method: post + annotation: test:inoption + content: + fvTenant: + attributes: + descr: Ansible test tenant + name: ansible_test + register: nm_add_tenant_annotation_option + +- name: Add tenant with annotation in content + cisco.aci.aci_rest: + host: '{{ aci_hostname }}' + username: '{{ aci_username }}' + password: '{{ aci_password }}' + validate_certs: '{{ aci_validate_certs | default(false) }}' + use_ssl: '{{ aci_use_ssl | default(true) }}' + use_proxy: '{{ aci_use_proxy | default(true) }}' + output_level: '{{ aci_output_level | default("info") }}' + path: /api/mo/uni.json + method: post + content: + fvTenant: + attributes: + descr: Ansible test tenant + name: ansible_test + annotation: test:incontent + register: nm_add_tenant_annotation_content + +- name: Add tenant with annotation in content and option + cisco.aci.aci_rest: + host: '{{ aci_hostname }}' + username: '{{ aci_username }}' + password: '{{ aci_password }}' + validate_certs: '{{ aci_validate_certs | default(false) }}' + use_ssl: '{{ aci_use_ssl | default(true) }}' + use_proxy: '{{ aci_use_proxy | default(true) }}' + output_level: '{{ aci_output_level | default("info") }}' + path: /api/mo/uni.json + method: post + annotation: test:inoption + content: + fvTenant: + attributes: + descr: Ansible test tenant + name: ansible_test + annotation: test:optionincontent + register: nm_add_tenant_annotation_option_content + +- name: Add tag to tenant with annotation unsupported + cisco.aci.aci_rest: + host: '{{ aci_hostname }}' + username: '{{ aci_username }}' + password: '{{ aci_password }}' + validate_certs: '{{ aci_validate_certs | default(false) }}' + use_ssl: '{{ aci_use_ssl | default(true) }}' + use_proxy: '{{ aci_use_proxy | default(true) }}' + output_level: '{{ aci_output_level | default("info") }}' + path: /api/mo/uni/tn-ansible_test/tagKey-foo.json + method: post + annotation: test:inoption + content: + tagTag: + attributes: + value: bar + register: nm_add_tag_no_annotation + +- name: Remove tenant + cisco.aci.aci_rest: *tenant_absent + +- name: Add tenant with children objects including annotation + cisco.aci.aci_rest: + host: '{{ aci_hostname }}' + username: '{{ aci_username }}' + password: '{{ aci_password }}' + validate_certs: '{{ aci_validate_certs | default(false) }}' + use_ssl: '{{ aci_use_ssl | default(true) }}' + use_proxy: '{{ aci_use_proxy | default(true) }}' + output_level: '{{ aci_output_level | default("info") }}' + path: /api/mo/uni.json + method: post + annotation: test:inoption + content: + fvTenant: + attributes: + descr: Ansible test tenant + name: ansible_test + children: + - fvCtx: + attributes: + name: VRF1 + - fvAp: + attributes: + name: Application1 + children: + - fvAEPg: + attributes: + name: WebTier + annotation: test:inchild + register: nm_add_tenant_annotation_children + +- name: Verify annotation support + assert: + that: + - nm_add_tenant_annotation_option.imdata.0.fvTenant.attributes.annotation == "test:inoption" + - nm_add_tenant_annotation_content.imdata.0.fvTenant.attributes.annotation == "test:incontent" + - nm_add_tenant_annotation_option_content.imdata.0.fvTenant.attributes.annotation == "test:optionincontent" + - nm_add_tag_no_annotation.imdata.0.tagTag.attributes.annotation is undefined + - nm_add_tenant_annotation_children.imdata.0.fvTenant.attributes.annotation == "test:inoption" + - nm_add_tenant_annotation_children.imdata.0.fvTenant.children.0.fvAp.attributes.annotation == "test:inoption" + - nm_add_tenant_annotation_children.imdata.0.fvTenant.children.0.fvAp.children.0.fvAEPg.attributes.annotation == "test:inchild" + - nm_add_tenant_annotation_children.imdata.0.fvTenant.children.2.fvCtx.attributes.annotation == "test:inoption" diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_rest/tasks/yaml_string.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_rest/tasks/yaml_string.yml index 895045474..982235c9a 100644 --- a/ansible_collections/cisco/aci/tests/integration/targets/aci_rest/tasks/yaml_string.yml +++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_rest/tasks/yaml_string.yml @@ -50,10 +50,11 @@ register: cm_verify_checkmode_tenant - name: Verify checkmode POST operation - assert: + ansible.builtin.assert: that: - cm_add_tenant is changed - cm_add_tenant.proposed.fvTenant.attributes.name == "ansible_test" + - cm_add_tenant.proposed.fvTenant.attributes.annotation == "orchestrator:ansible" - cm_verify_checkmode_tenant.current == [] - name: Add tenant (normal mode) @@ -65,9 +66,10 @@ register: nm_add_tenant_again - name: Verify add_tenant - assert: + ansible.builtin.assert: that: - nm_add_tenant is changed + - nm_add_tenant.imdata.0.fvTenant.attributes.annotation == "orchestrator:ansible" - nm_add_tenant_again is not changed # CHANGE TENANT @@ -94,7 +96,7 @@ register: nm_add_tenant_descr_again - name: Verify add_tenant_descr - assert: + ansible.builtin.assert: that: - nm_add_tenant_descr is changed - nm_add_tenant_descr_again is not changed @@ -105,7 +107,7 @@ register: nm_add_tenant_again_no_descr - name: Verify add_tenant_again_no_descr - assert: + ansible.builtin.assert: that: - nm_add_tenant_again_no_descr is not changed @@ -124,7 +126,7 @@ register: nm_query_all_tenants - name: Verify query_all_tenants - assert: + ansible.builtin.assert: that: - nm_query_all_tenants is not changed @@ -143,7 +145,7 @@ register: nm_query_tenant - name: Verify query_tenant - assert: + ansible.builtin.assert: that: - nm_query_tenant is not changed @@ -157,7 +159,7 @@ register: nm_remove_tenant_again - name: Verify remove_tenant - assert: + ansible.builtin.assert: that: - nm_remove_tenant is changed - nm_remove_tenant_again is not changed @@ -168,6 +170,129 @@ register: nm_query_non_tenant - name: Verify query_non_tenant - assert: + ansible.builtin.assert: that: - nm_query_non_tenant is not changed + +# VERIFY ANNOTATION SUPPORT +- name: Add tenant with annotation option + cisco.aci.aci_rest: + host: '{{ aci_hostname }}' + username: '{{ aci_username }}' + password: '{{ aci_password }}' + validate_certs: '{{ aci_validate_certs | default(false) }}' + use_ssl: '{{ aci_use_ssl | default(true) }}' + use_proxy: '{{ aci_use_proxy | default(true) }}' + output_level: '{{ aci_output_level | default("info") }}' + path: /api/mo/uni.json + method: post + annotation: test:inoption + content: | + fvTenant: + attributes: + descr: Ansible test tenant + name: ansible_test + register: nm_add_tenant_annotation_option + +- name: Add tenant with annotation in content + cisco.aci.aci_rest: + host: '{{ aci_hostname }}' + username: '{{ aci_username }}' + password: '{{ aci_password }}' + validate_certs: '{{ aci_validate_certs | default(false) }}' + use_ssl: '{{ aci_use_ssl | default(true) }}' + use_proxy: '{{ aci_use_proxy | default(true) }}' + output_level: '{{ aci_output_level | default("info") }}' + path: /api/mo/uni.json + method: post + content: | + fvTenant: + attributes: + descr: Ansible test tenant + name: ansible_test + annotation: test:incontent + register: nm_add_tenant_annotation_content + +- name: Add tenant with annotation in content and option + cisco.aci.aci_rest: + host: '{{ aci_hostname }}' + username: '{{ aci_username }}' + password: '{{ aci_password }}' + validate_certs: '{{ aci_validate_certs | default(false) }}' + use_ssl: '{{ aci_use_ssl | default(true) }}' + use_proxy: '{{ aci_use_proxy | default(true) }}' + output_level: '{{ aci_output_level | default("info") }}' + path: /api/mo/uni.json + method: post + annotation: test:inoption + content: | + fvTenant: + attributes: + descr: Ansible test tenant + name: ansible_test + annotation: test:optionincontent + register: nm_add_tenant_annotation_option_content + +- name: Add tag to tenant with annotation unsupported + cisco.aci.aci_rest: + host: '{{ aci_hostname }}' + username: '{{ aci_username }}' + password: '{{ aci_password }}' + validate_certs: '{{ aci_validate_certs | default(false) }}' + use_ssl: '{{ aci_use_ssl | default(true) }}' + use_proxy: '{{ aci_use_proxy | default(true) }}' + output_level: '{{ aci_output_level | default("info") }}' + path: /api/mo/uni/tn-ansible_test/tagKey-foo.json + method: post + annotation: test:inoption + content: | + tagTag: + attributes: + value: bar + register: nm_add_tag_no_annotation + +- name: Remove tenant + cisco.aci.aci_rest: *tenant_absent + +- name: Add tenant with children objects including annotation + cisco.aci.aci_rest: + host: '{{ aci_hostname }}' + username: '{{ aci_username }}' + password: '{{ aci_password }}' + validate_certs: '{{ aci_validate_certs | default(false) }}' + use_ssl: '{{ aci_use_ssl | default(true) }}' + use_proxy: '{{ aci_use_proxy | default(true) }}' + output_level: '{{ aci_output_level | default("info") }}' + path: /api/mo/uni.json + method: post + annotation: test:inoption + content: | + fvTenant: + attributes: + descr: Ansible test tenant + name: ansible_test + children: + - fvCtx: + attributes: + name: VRF1 + - fvAp: + attributes: + name: Application1 + children: + - fvAEPg: + attributes: + name: WebTier + annotation: test:inchild + register: nm_add_tenant_annotation_children + +- name: Verify annotation support + assert: + that: + - nm_add_tenant_annotation_option.imdata.0.fvTenant.attributes.annotation == "test:inoption" + - nm_add_tenant_annotation_content.imdata.0.fvTenant.attributes.annotation == "test:incontent" + - nm_add_tenant_annotation_option_content.imdata.0.fvTenant.attributes.annotation == "test:optionincontent" + - nm_add_tag_no_annotation.imdata.0.tagTag.attributes.annotation is undefined + - nm_add_tenant_annotation_children.imdata.0.fvTenant.attributes.annotation == "test:inoption" + - nm_add_tenant_annotation_children.imdata.0.fvTenant.children.0.fvAp.attributes.annotation == "test:inoption" + - nm_add_tenant_annotation_children.imdata.0.fvTenant.children.0.fvAp.children.0.fvAEPg.attributes.annotation == "test:inchild" + - nm_add_tenant_annotation_children.imdata.0.fvTenant.children.2.fvCtx.attributes.annotation == "test:inoption" \ No newline at end of file diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_route_control_context/tasks/main.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_route_control_context/tasks/main.yml index 83f46e4b8..31eef79a6 100644 --- a/ansible_collections/cisco/aci/tests/integration/targets/aci_route_control_context/tasks/main.yml +++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_route_control_context/tasks/main.yml @@ -5,12 +5,12 @@ # GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) - name: Test that we have an ACI APIC host, ACI username and ACI password - fail: + ansible.builtin.fail: msg: 'Please define the following variables: aci_hostname, aci_username and aci_password.' when: aci_hostname is not defined or aci_username is not defined or aci_password is not defined - name: Set vars - set_fact: + ansible.builtin.set_fact: aci_info: &aci_info host: "{{ aci_hostname }}" username: "{{ aci_username }}" @@ -22,26 +22,26 @@ # CLEAN ENVIRONMENT - name: Remove the ansible_tenant - aci_tenant: &aci_tenant_absent + cisco.aci.aci_tenant: &aci_tenant_absent <<: *aci_info tenant: ansible_tenant state: absent - name: Verify Cloud and Non-Cloud Sites in use. - include_tasks: ../../../../../../integration/targets/aci_cloud_provider/tasks/main.yml + ansible.builtin.include_tasks: ../../../../../../integration/targets/aci_cloud_provider/tasks/main.yml - name: Execute tasks only for non-cloud sites when: query_cloud.current == [] # This condition will execute only non-cloud sites block: # block specifies execution of tasks within, based on conditions - name: Add a new tenant - aci_tenant: &aci_tenant_present + cisco.aci.aci_tenant: &aci_tenant_present <<: *aci_info tenant: ansible_tenant description: Ansible tenant state: present - name: Add a new action rule profile - aci_tenant_action_rule_profile: &aci_action_rule_present + cisco.aci.aci_tenant_action_rule_profile: &aci_action_rule_present <<: *aci_info tenant: ansible_tenant action_rule: ansible_action_rule @@ -49,7 +49,7 @@ state: present - name: Add a new L3Out - aci_l3out: + cisco.aci.aci_l3out: <<: *aci_info tenant: ansible_tenant l3out: ansible_l3out @@ -59,7 +59,7 @@ state: present - name: Add a route control profile for l3out - aci_route_control_profile: + cisco.aci.aci_route_control_profile: <<: *aci_info tenant: ansible_tenant l3out: ansible_l3out @@ -68,7 +68,7 @@ state: present - name: Add a subject profile - aci_match_rule: &aci_match_rule_present + cisco.aci.aci_match_rule: &aci_match_rule_present <<: *aci_info tenant: ansible_tenant match_rule: ansible_match_rule @@ -76,7 +76,7 @@ state: present - name: Add a route control context policy for l3out (check_mode) - aci_route_control_context: &aci_route_control_context_present + cisco.aci.aci_route_control_context: &aci_route_control_context_present <<: *aci_info tenant: ansible_tenant l3out: ansible_l3out @@ -92,17 +92,17 @@ register: cm_add_route_control_context_l3out - name: Add a route control context policy again (normal_mode) - aci_route_control_context: + cisco.aci.aci_route_control_context: <<: *aci_route_control_context_present register: nm_add_route_control_context_l3out - name: Add a route control context policy again - testing idempotency - aci_route_control_context: + cisco.aci.aci_route_control_context: <<: *aci_route_control_context_present register: nm_add_route_control_context_l3out_idempotency - name: Add a route control profile for tenant - aci_route_control_profile: + cisco.aci.aci_route_control_profile: <<: *aci_info tenant: ansible_tenant route_control_profile: ansible_rtctrl_profile_tenant @@ -110,7 +110,7 @@ state: present - name: Add a route control context policy for tenant - aci_route_control_context: + cisco.aci.aci_route_control_context: <<: *aci_info tenant: ansible_tenant route_control_profile: ansible_rtctrl_profile_tenant @@ -120,7 +120,7 @@ register: nm_add_route_control_context_tenant - name: Asserts for route control profiles creation tasks - assert: + ansible.builtin.assert: that: - cm_add_route_control_context_l3out is changed - cm_add_route_control_context_l3out.previous == [] @@ -139,20 +139,20 @@ - nm_add_route_control_context_tenant.current.0.rtctrlCtxP.attributes.order == "0" - name: Query all route control context policies - aci_route_control_context: + cisco.aci.aci_route_control_context: <<: *aci_info state: query register: query_all_route_control_context - name: Query ansible_route_control_context_l3out route control context policy - aci_route_control_context: + cisco.aci.aci_route_control_context: <<: *aci_info route_control_context: ansible_route_control_context_l3out state: query register: query_route_control_context_l3out - name: Asserts query tasks - assert: + ansible.builtin.assert: that: - query_all_route_control_context is not changed - query_all_route_control_context.current|length >= 2 @@ -164,24 +164,24 @@ - query_route_control_context_l3out.current.0.rtctrlCtxP.children.1.rtctrlRsCtxPToSubjP.attributes.tDn == "uni/tn-ansible_tenant/subj-ansible_match_rule" - name: Remove route control context policy for l3out (check_mode) - aci_route_control_context: &aci_route_control_context_absent + cisco.aci.aci_route_control_context: &aci_route_control_context_absent <<: *aci_route_control_context_present state: absent check_mode: true register: cm_remove_route_control_context - name: Remove route control context policy for l3out (normal_mode) - aci_route_control_context: + cisco.aci.aci_route_control_context: <<: *aci_route_control_context_absent register: nm_remove_remove_route_control_context - name: Remove route control profile for l3out again - testing previous Removal - aci_route_control_context: + cisco.aci.aci_route_control_context: <<: *aci_route_control_context_absent register: nm_remove_route_control_context_idempotency - name: Asserts deletion tasks - assert: + ansible.builtin.assert: that: - cm_remove_route_control_context is changed - cm_remove_route_control_context.proposed == {} @@ -192,6 +192,6 @@ - nm_remove_route_control_context_idempotency.previous == [] - name: Remove the ansible_tenant - cleanup before ending tests - aci_tenant: + cisco.aci.aci_tenant: <<: *aci_tenant_present state: absent diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_route_control_profile/tasks/main.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_route_control_profile/tasks/main.yml index db0022100..d0c044472 100644 --- a/ansible_collections/cisco/aci/tests/integration/targets/aci_route_control_profile/tasks/main.yml +++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_route_control_profile/tasks/main.yml @@ -5,12 +5,12 @@ # GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) - name: Test that we have an ACI APIC host, ACI username and ACI password - fail: + ansible.builtin.fail: msg: 'Please define the following variables: aci_hostname, aci_username and aci_password.' when: aci_hostname is not defined or aci_username is not defined or aci_password is not defined - name: Set vars - set_fact: + ansible.builtin.set_fact: aci_info: &aci_info host: "{{ aci_hostname }}" username: "{{ aci_username }}" @@ -22,26 +22,26 @@ # CLEAN ENVIRONMENT - name: Remove the ansible_tenant - aci_tenant: &aci_tenant_absent + cisco.aci.aci_tenant: &aci_tenant_absent <<: *aci_info tenant: ansible_tenant state: absent - name: Verify Cloud and Non-Cloud Sites in use. - include_tasks: ../../../../../../integration/targets/aci_cloud_provider/tasks/main.yml + ansible.builtin.include_tasks: ../../../../../../integration/targets/aci_cloud_provider/tasks/main.yml - name: Execute tasks only for non-cloud sites when: query_cloud.current == [] # This condition will execute only non-cloud sites block: # block specifies execution of tasks within, based on conditions - name: Add a new tenant - aci_tenant: &aci_tenant_present + cisco.aci.aci_tenant: &aci_tenant_present <<: *aci_info tenant: ansible_tenant description: Ansible tenant state: present - name: Add a new L3Out - aci_l3out: + cisco.aci.aci_l3out: <<: *aci_info tenant: ansible_tenant l3out: ansible_l3out @@ -51,7 +51,7 @@ state: present - name: Add route control profile for l3out (check_mode) - aci_route_control_profile: &aci_route_control_profile_present + cisco.aci.aci_route_control_profile: &aci_route_control_profile_present <<: *aci_info tenant: ansible_tenant l3out: ansible_l3out @@ -64,17 +64,17 @@ register: cm_add_route_control_profile - name: Add route control profile for l3out (normal_mode) - aci_route_control_profile: + cisco.aci.aci_route_control_profile: <<: *aci_route_control_profile_present register: nm_add_route_control_profile - name: Add route control profile for l3out again - testing idempotency - aci_route_control_profile: + cisco.aci.aci_route_control_profile: <<: *aci_route_control_profile_present register: nm_add_route_control_profile_idempotency - name: Add route control profile for tenant (normal_mode) - aci_route_control_profile: + cisco.aci.aci_route_control_profile: <<: *aci_info tenant: ansible_tenant route_control_profile: ansible_rtctrl_profile_tenant @@ -83,7 +83,7 @@ register: nm_add_route_control_profile_2 - name: Asserts for route control profiles creation tasks - assert: + ansible.builtin.assert: that: - cm_add_route_control_profile is changed - cm_add_route_control_profile.previous == [] @@ -94,42 +94,42 @@ - nm_add_route_control_profile_2.previous == [] - name: Query all route control profiles - aci_route_control_profile: + cisco.aci.aci_route_control_profile: <<: *aci_info state: query register: query_all_route_control_profile - name: Query ansible_rtctrl_profile_l3out - aci_route_control_profile: + cisco.aci.aci_route_control_profile: <<: *aci_route_control_profile_present state: query register: query_ansible_rtctrl_profile_l3out - name: Asserts query tasks - assert: + ansible.builtin.assert: that: - query_all_route_control_profile is not changed - query_all_route_control_profile.current|length >= 2 - name: Remove route control profile for l3out (check_mode) - aci_route_control_profile: &route_control_profile_absent + cisco.aci.aci_route_control_profile: &route_control_profile_absent <<: *aci_route_control_profile_present state: absent check_mode: true register: cm_remove_route_control_profile - name: Remove route control profile for l3out (normal_mode) - aci_route_control_profile: + cisco.aci.aci_route_control_profile: <<: *route_control_profile_absent register: nm_remove_route_control_profile - name: Remove route control profile for l3out again - testing previous Removal - aci_route_control_profile: + cisco.aci.aci_route_control_profile: <<: *route_control_profile_absent register: nm_remove_route_control_profile_idempotency - name: Asserts deletion tasks - assert: + ansible.builtin.assert: that: - cm_remove_route_control_profile is changed - cm_remove_route_control_profile.proposed == {} @@ -140,6 +140,6 @@ - nm_remove_route_control_profile_idempotency.previous == [] - name: Remove the ansible_tenant - cleanup before ending tests - aci_tenant: + cisco.aci.aci_tenant: <<: *aci_tenant_present state: absent diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_snmp_client/tasks/main.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_snmp_client/tasks/main.yml index e5c0ce185..5e6f44ceb 100644 --- a/ansible_collections/cisco/aci/tests/integration/targets/aci_snmp_client/tasks/main.yml +++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_snmp_client/tasks/main.yml @@ -4,13 +4,13 @@ # GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) - name: Test that we have an ACI APIC host, ACI username and ACI password - fail: + ansible.builtin.fail: msg: 'Please define the following variables: aci_hostname, aci_username and aci_password.' when: aci_hostname is not defined or aci_username is not defined or aci_password is not defined # GET Credentials from the inventory - name: Set vars - set_fact: + ansible.builtin.set_fact: aci_info: &aci_info host: "{{ aci_hostname }}" username: "{{ aci_username }}" @@ -22,14 +22,14 @@ # CLEAN ENVIRONMENT - name: Remove ansible_snmp_client_group if it already exists - aci_snmp_policy: + cisco.aci.aci_snmp_policy: <<: *aci_info name: ansible_snmp_policy state: absent # ADD snmp policy - name: Add snmp policy - aci_snmp_policy: + cisco.aci.aci_snmp_policy: <<: *aci_info name: ansible_snmp_policy admin_state: enabled @@ -37,7 +37,7 @@ # ADD snmp client group - name: Add snmp client group - aci_snmp_client_group: + cisco.aci.aci_snmp_client_group: <<: *aci_info policy: ansible_snmp_policy client_group: ansible_snmp_client_group @@ -46,7 +46,7 @@ # ADD snmp client - name: Add snmp client - aci_snmp_client: + cisco.aci.aci_snmp_client: <<: *aci_info policy: ansible_snmp_policy client_group: ansible_snmp_client_group @@ -56,7 +56,7 @@ register: add_snmp_client - name: Verify that ansible_snmp_client has been created with correct attributes - assert: + ansible.builtin.assert: that: - add_snmp_client.current.0.snmpClientP.attributes.dn == "uni/fabric/snmppol-ansible_snmp_policy/clgrp-ansible_snmp_client_group/client-[10.20.30.0/24]" - add_snmp_client.current.0.snmpClientP.attributes.addr == "10.20.30.0/24" @@ -65,7 +65,7 @@ # ADD snmp client again to check idempotency - name: Add snmp client again - aci_snmp_client: + cisco.aci.aci_snmp_client: <<: *aci_info policy: ansible_snmp_policy client_group: ansible_snmp_client_group @@ -75,13 +75,13 @@ register: add_snmp_client_again - name: Verify that add_snmp_client_group_again stays the same - assert: + ansible.builtin.assert: that: - add_snmp_client_again is not changed # MODIFY snmp client - name: Update snmp client - aci_snmp_client: + cisco.aci.aci_snmp_client: <<: *aci_info policy: ansible_snmp_policy client_group: ansible_snmp_client_group @@ -91,7 +91,7 @@ register: update_snmp_client - name: Verify that ansible_snmp_client_group has been updated with correct attributes - assert: + ansible.builtin.assert: that: - update_snmp_client is changed - update_snmp_client.current.0.snmpClientP.attributes.dn == "uni/fabric/snmppol-ansible_snmp_policy/clgrp-ansible_snmp_client_group/client-[10.20.30.0/24]" @@ -100,7 +100,7 @@ # QUERY snmp client - name: Query snmp client - aci_snmp_client: + cisco.aci.aci_snmp_client: <<: *aci_info policy: ansible_snmp_policy client_group: ansible_snmp_client_group @@ -109,7 +109,7 @@ register: query_snmp_client - name: Verify the attributes under query_snmp_client - assert: + ansible.builtin.assert: that: - query_snmp_client is not changed - query_snmp_client.current.0.snmpClientP.attributes.dn == "uni/fabric/snmppol-ansible_snmp_policy/clgrp-ansible_snmp_client_group/client-[10.20.30.0/24]" @@ -117,19 +117,19 @@ - query_snmp_client.current.0.snmpClientP.attributes.name == "new_snmp_client_name" - name: Query all snmp client - aci_snmp_client: + cisco.aci.aci_snmp_client: <<: *aci_info state: query register: query_snmp_client_all - name: Verify query_snmp_client_all - assert: + ansible.builtin.assert: that: - query_snmp_client_all is not changed # DELETE snmp client group - name: Remove the snmp client - aci_snmp_client: + cisco.aci.aci_snmp_client: <<: *aci_info policy: ansible_snmp_policy client_group: ansible_snmp_client_group @@ -138,7 +138,7 @@ register: remove_snmp_client - name: Verify remove_snmp_client - assert: + ansible.builtin.assert: that: - remove_snmp_client is changed - remove_snmp_client.previous.0.snmpClientP.attributes.dn == "uni/fabric/snmppol-ansible_snmp_policy/clgrp-ansible_snmp_client_group/client-[10.20.30.0/24]" @@ -146,14 +146,14 @@ # DELETE snmp policy - name: Remove the snmp policy - aci_snmp_policy: + cisco.aci.aci_snmp_policy: <<: *aci_info name: ansible_snmp_policy state: absent # DELETE snmp client group - name: Remove the snmp client group - aci_snmp_client_group: + cisco.aci.aci_snmp_client_group: <<: *aci_info policy: ansible_snmp_policy client_group: ansible_snmp_client_group diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_snmp_client_group/tasks/main.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_snmp_client_group/tasks/main.yml index f54a7841a..b93d3f2fb 100644 --- a/ansible_collections/cisco/aci/tests/integration/targets/aci_snmp_client_group/tasks/main.yml +++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_snmp_client_group/tasks/main.yml @@ -4,13 +4,13 @@ # GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) - name: Test that we have an ACI APIC host, ACI username and ACI password - fail: + ansible.builtin.fail: msg: 'Please define the following variables: aci_hostname, aci_username and aci_password.' when: aci_hostname is not defined or aci_username is not defined or aci_password is not defined # GET Credentials from the inventory - name: Set vars - set_fact: + ansible.builtin.set_fact: aci_info: &aci_info host: "{{ aci_hostname }}" username: "{{ aci_username }}" @@ -22,14 +22,14 @@ # CLEAN ENVIRONMENT - name: Remove ansible_snmp_client_group if it already exists - aci_snmp_policy: + cisco.aci.aci_snmp_policy: <<: *aci_info name: ansible_snmp_policy state: absent # ADD snmp policy - name: Add snmp policy - aci_snmp_policy: + cisco.aci.aci_snmp_policy: <<: *aci_info name: ansible_snmp_policy admin_state: enabled @@ -37,7 +37,7 @@ # ADD snmp client group - name: Add snmp client group - aci_snmp_client_group: + cisco.aci.aci_snmp_client_group: <<: *aci_info policy: ansible_snmp_policy client_group: ansible_snmp_client_group @@ -47,7 +47,7 @@ register: add_snmp_client_group - name: Add snmp client group on default mgmt_epg - aci_snmp_client_group: + cisco.aci.aci_snmp_client_group: <<: *aci_info policy: ansible_snmp_policy client_group: ansible_snmp_client_group_no_epg @@ -56,7 +56,7 @@ register: add_snmp_client_group_no_epg - name: Verify that ansible_snmp_client_group has been created with correct attributes - assert: + ansible.builtin.assert: that: - add_snmp_client_group.current.0.snmpClientGrpP.attributes.dn == "uni/fabric/snmppol-ansible_snmp_policy/clgrp-ansible_snmp_client_group" - add_snmp_client_group.current.0.snmpClientGrpP.attributes.name == "ansible_snmp_client_group" @@ -64,20 +64,20 @@ - add_snmp_client_group.current.0.snmpClientGrpP.attributes.annotation == 'orchestrator:ansible' - name: Verify that ansible_snmp_client_group_no_epg has been created with correct attributes - assert: + ansible.builtin.assert: that: - add_snmp_client_group_no_epg.current.0.snmpClientGrpP.attributes.dn == "uni/fabric/snmppol-ansible_snmp_policy/clgrp-ansible_snmp_client_group_no_epg" - add_snmp_client_group_no_epg.current.0.snmpClientGrpP.attributes.name == "ansible_snmp_client_group_no_epg" - add_snmp_client_group_no_epg.current.0.snmpClientGrpP.attributes.descr == "client group descr" - name: Verify that children of ansible_snmp_client_group have been created with correct values - assert: + ansible.builtin.assert: that: - add_snmp_client_group.current.0.snmpClientGrpP.children.0.snmpRsEpg.attributes.tDn == "uni/tn-mgmt/mgmtp-default/oob-default" # ADD snmp client group again to check idempotency - name: Add snmp client group again - aci_snmp_client_group: + cisco.aci.aci_snmp_client_group: <<: *aci_info policy: ansible_snmp_policy client_group: ansible_snmp_client_group @@ -87,13 +87,13 @@ register: add_snmp_client_group_again - name: Verify that add_snmp_client_group_again stays the same - assert: + ansible.builtin.assert: that: - add_snmp_client_group_again is not changed # MODIFY snmp client group - name: Update snmp client group - aci_snmp_client_group: + cisco.aci.aci_snmp_client_group: <<: *aci_info policy: ansible_snmp_policy client_group: ansible_snmp_client_group @@ -103,7 +103,7 @@ register: update_snmp_client_group - name: Verify that ansible_snmp_client_group has been updated with correct attributes - assert: + ansible.builtin.assert: that: - update_snmp_client_group is changed - update_snmp_client_group.current.0.snmpClientGrpP.attributes.dn == "uni/fabric/snmppol-ansible_snmp_policy/clgrp-ansible_snmp_client_group" @@ -112,7 +112,7 @@ # QUERY snmp client group - name: Query snmp client group - aci_snmp_client_group: + cisco.aci.aci_snmp_client_group: <<: *aci_info policy: ansible_snmp_policy client_group: ansible_snmp_client_group @@ -120,7 +120,7 @@ register: query_snmp_client_group - name: Verify the attributes under query_snmp_client_group - assert: + ansible.builtin.assert: that: - query_snmp_client_group is not changed - query_snmp_client_group.current.0.snmpClientGrpP.attributes.dn == "uni/fabric/snmppol-ansible_snmp_policy/clgrp-ansible_snmp_client_group" @@ -128,19 +128,19 @@ - query_snmp_client_group.current.0.snmpClientGrpP.attributes.descr == "new client group descr" - name: Query all snmp client groups - aci_snmp_client_group: + cisco.aci.aci_snmp_client_group: <<: *aci_info state: query register: query_snmp_client_group_all - name: Verify query_snmp_client_group_all - assert: + ansible.builtin.assert: that: - query_snmp_client_group_all is not changed # DELETE snmp client group - name: Remove the snmp client group - aci_snmp_client_group: + cisco.aci.aci_snmp_client_group: <<: *aci_info policy: ansible_snmp_policy client_group: ansible_snmp_client_group @@ -148,7 +148,7 @@ register: remove_snmp_client_group - name: Verify remove_snmp_client_group - assert: + ansible.builtin.assert: that: - remove_snmp_client_group is changed - remove_snmp_client_group.previous.0.snmpClientGrpP.attributes.dn == "uni/fabric/snmppol-ansible_snmp_policy/clgrp-ansible_snmp_client_group" @@ -156,7 +156,7 @@ # DELETE snmp policy - name: Remove the snmp policy - aci_snmp_policy: + cisco.aci.aci_snmp_policy: <<: *aci_info name: ansible_snmp_policy state: absent diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_snmp_community_policy/tasks/main.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_snmp_community_policy/tasks/main.yml index 570476d37..53538a09f 100644 --- a/ansible_collections/cisco/aci/tests/integration/targets/aci_snmp_community_policy/tasks/main.yml +++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_snmp_community_policy/tasks/main.yml @@ -4,13 +4,13 @@ # GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) - name: Test that we have an ACI APIC host, ACI username and ACI password - fail: + ansible.builtin.fail: msg: 'Please define the following variables: aci_hostname, aci_username and aci_password.' when: aci_hostname is not defined or aci_username is not defined or aci_password is not defined # GET Credentials from the inventory - name: Set vars - set_fact: + ansible.builtin.set_fact: aci_info: &aci_info host: "{{ aci_hostname }}" username: "{{ aci_username }}" @@ -22,14 +22,14 @@ # CLEAN ENVIRONMENT - name: Remove ansible_snmp_policy if it already exists - aci_snmp_policy: + cisco.aci.aci_snmp_policy: <<: *aci_info name: ansible_snmp_policy state: absent # ADD snmp policy - name: Add snmp policy - aci_snmp_policy: + cisco.aci.aci_snmp_policy: <<: *aci_info name: ansible_snmp_policy admin_state: enabled @@ -37,7 +37,7 @@ # ADD snmp community - name: Add snmp community - aci_snmp_community_policy: + cisco.aci.aci_snmp_community_policy: <<: *aci_info policy: ansible_snmp_policy community: ansible_snmp_community @@ -45,7 +45,7 @@ register: add_snmp_community - name: Verify that ansible_snmp_community has been created with correct attributes - assert: + ansible.builtin.assert: that: - add_snmp_community.current.0.snmpCommunityP.attributes.dn == "uni/fabric/snmppol-ansible_snmp_policy/community-ansible_snmp_community" - add_snmp_community.current.0.snmpCommunityP.attributes.name == "ansible_snmp_community" @@ -54,7 +54,7 @@ # ADD snmp community again to check idempotency - name: Add snmp client group again - aci_snmp_community_policy: + cisco.aci.aci_snmp_community_policy: <<: *aci_info policy: ansible_snmp_policy community: ansible_snmp_community @@ -62,13 +62,13 @@ register: add_snmp_community_again - name: Verify that add_snmp_community_again stays the same - assert: + ansible.builtin.assert: that: - add_snmp_community_again is not changed # MODIFY snmp client community - name: Update snmp community - aci_snmp_community_policy: + cisco.aci.aci_snmp_community_policy: <<: *aci_info policy: ansible_snmp_policy community: ansible_snmp_community @@ -76,7 +76,7 @@ register: update_snmp_community - name: Verify that ansible_snmp_community has been updated with correct attributes - assert: + ansible.builtin.assert: that: - update_snmp_community is changed - update_snmp_community.current.0.snmpCommunityP.attributes.dn == "uni/fabric/snmppol-ansible_snmp_policy/community-ansible_snmp_community" @@ -85,7 +85,7 @@ # QUERY snmp community - name: Query snmp community - aci_snmp_community_policy: + cisco.aci.aci_snmp_community_policy: <<: *aci_info policy: ansible_snmp_policy community: ansible_snmp_community @@ -93,7 +93,7 @@ register: query_snmp_community - name: Verify the attributes under query_snmp_client_group - assert: + ansible.builtin.assert: that: - query_snmp_community is not changed - query_snmp_community.current.0.snmpCommunityP.attributes.dn == "uni/fabric/snmppol-ansible_snmp_policy/community-ansible_snmp_community" @@ -101,19 +101,19 @@ - query_snmp_community.current.0.snmpCommunityP.attributes.descr == "new community description" - name: Query all snmp communities - aci_snmp_community_policy: + cisco.aci.aci_snmp_community_policy: <<: *aci_info state: query register: query_snmp_community_all - name: Verify query_snmp_community_all - assert: + ansible.builtin.assert: that: - query_snmp_community_all is not changed # DELETE snmp community - name: Remove the snmp community - aci_snmp_community_policy: + cisco.aci.aci_snmp_community_policy: <<: *aci_info policy: ansible_snmp_policy community: ansible_snmp_community @@ -121,7 +121,7 @@ register: remove_snmp_community - name: Verify remove_snmp_community - assert: + ansible.builtin.assert: that: - remove_snmp_community is changed - remove_snmp_community.current == [] @@ -130,7 +130,7 @@ # DELETE snmp policy - name: Remove the snmp policy - aci_snmp_policy: + cisco.aci.aci_snmp_policy: <<: *aci_info name: ansible_snmp_policy state: absent diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_snmp_policy/tasks/main.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_snmp_policy/tasks/main.yml index 823ea8f30..70f60f5be 100644 --- a/ansible_collections/cisco/aci/tests/integration/targets/aci_snmp_policy/tasks/main.yml +++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_snmp_policy/tasks/main.yml @@ -4,13 +4,13 @@ # GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) - name: Test that we have an ACI APIC host, ACI username and ACI password - fail: + ansible.builtin.fail: msg: 'Please define the following variables: aci_hostname, aci_username and aci_password.' when: aci_hostname is not defined or aci_username is not defined or aci_password is not defined # GET Credentials from the inventory - name: Set vars - set_fact: + ansible.builtin.set_fact: aci_info: &aci_info host: "{{ aci_hostname }}" username: "{{ aci_username }}" @@ -22,14 +22,14 @@ # CLEAN ENVIRONMENT - name: Remove ansible_snmp_policy if it already exists - aci_snmp_policy: + cisco.aci.aci_snmp_policy: <<: *aci_info name: ansible_snmp_policy state: absent # ADD snmp policy - name: Add snmp policy - aci_snmp_policy: + cisco.aci.aci_snmp_policy: <<: *aci_info name: ansible_snmp_policy admin_state: enabled @@ -40,7 +40,7 @@ register: add_snmp_policy - name: Verify that ansible_snmp_policy has been created with correct attributes - assert: + ansible.builtin.assert: that: - add_snmp_policy.current.0.snmpPol.attributes.dn == "uni/fabric/snmppol-ansible_snmp_policy" - add_snmp_policy.current.0.snmpPol.attributes.name == "ansible_snmp_policy" @@ -52,7 +52,7 @@ # ADD snmp policy again to check idempotency - name: Add snmp policy - aci_snmp_policy: + cisco.aci.aci_snmp_policy: <<: *aci_info name: ansible_snmp_policy admin_state: enabled @@ -63,13 +63,13 @@ register: add_snmp_policy_again - name: Verify that ansible_snmp_policy stays the same - assert: + ansible.builtin.assert: that: - add_snmp_policy_again is not changed # MODIFY snmp policy - name: Update snmp policy - aci_snmp_policy: + cisco.aci.aci_snmp_policy: <<: *aci_info name: ansible_snmp_policy admin_state: disabled @@ -80,7 +80,7 @@ register: update_snmp_policy - name: Verify that ansible_snmp_policy has been updated with correct attributes - assert: + ansible.builtin.assert: that: - update_snmp_policy.current.0.snmpPol.attributes.dn == "uni/fabric/snmppol-ansible_snmp_policy" - update_snmp_policy.current.0.snmpPol.attributes.name == "ansible_snmp_policy" @@ -91,14 +91,14 @@ # QUERY snmp policy - name: Query snmp policy - aci_snmp_policy: + cisco.aci.aci_snmp_policy: <<: *aci_info name: ansible_snmp_policy state: query register: query_snmp_policy - name: Verify the attributes under query_snmp_policy - assert: + ansible.builtin.assert: that: - query_snmp_policy is not changed - query_snmp_policy.current.0.snmpPol.attributes.dn == "uni/fabric/snmppol-ansible_snmp_policy" @@ -109,26 +109,26 @@ - query_snmp_policy.current.0.snmpPol.attributes.descr == "new policy description" - name: Query all snmp policies - aci_snmp_policy: + cisco.aci.aci_snmp_policy: <<: *aci_info state: query register: query_snmp_policy_all - name: Verify query_snmp_policy_all - assert: + ansible.builtin.assert: that: - query_snmp_policy_all is not changed # DELETE snmp policy - name: Remove the snmp policy - aci_snmp_policy: + cisco.aci.aci_snmp_policy: <<: *aci_info name: ansible_snmp_policy state: absent register: remove_snmp_policy - name: Verify remove_snmp_policy - assert: + ansible.builtin.assert: that: - remove_snmp_policy is changed - remove_snmp_policy.previous.0.snmpPol.attributes.dn == "uni/fabric/snmppol-ansible_snmp_policy" diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_static_binding_to_epg/tasks/main.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_static_binding_to_epg/tasks/main.yml index 0e9096b85..7917551ad 100644 --- a/ansible_collections/cisco/aci/tests/integration/targets/aci_static_binding_to_epg/tasks/main.yml +++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_static_binding_to_epg/tasks/main.yml @@ -5,12 +5,12 @@ # GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) - name: Test that we have an ACI APIC host, ACI username and ACI password - fail: + ansible.builtin.fail: msg: 'Please define the following variables: aci_hostname, aci_username and aci_password.' when: aci_hostname is not defined or aci_username is not defined or aci_password is not defined - name: Set vars - set_fact: + ansible.builtin.set_fact: aci_info: &aci_info host: "{{ aci_hostname }}" username: "{{ aci_username }}" @@ -21,7 +21,7 @@ output_level: debug - name: Verify Cloud and Non-Cloud Sites in use. - include_tasks: ../../../../../../integration/targets/aci_cloud_provider/tasks/main.yml + ansible.builtin.include_tasks: ../../../../../../integration/targets/aci_cloud_provider/tasks/main.yml - name: Execute tasks only for non-cloud sites when: query_cloud.current == [] # This condition will execute only non-cloud sites @@ -163,7 +163,7 @@ register: missing_required_present - name: Present assertions - assert: + ansible.builtin.assert: that: - provide_present_check_mode is changed - provide_present_check_mode.sent.fvRsPathAtt.attributes.encap == 'vlan-222' @@ -198,7 +198,7 @@ register: query_all - name: Query assertions - assert: + ansible.builtin.assert: that: - query_static_binding is not changed - query_static_binding.current != [] @@ -234,7 +234,7 @@ register: encap_id_range - name: primary_ecap_id assertions - assert: + ansible.builtin.assert: that: - primary_ecap_id_unknown is changed - primary_ecap_id_unknown.sent.fvRsPathAtt.attributes.primaryEncap == 'unknown' @@ -330,7 +330,7 @@ register: nm_multiple_extpaths - name: Verify interface type and extpaths - assert: + ansible.builtin.assert: that: - cm_fex_port_channel is changed - nm_fex_port_channel is changed @@ -361,7 +361,7 @@ register: missing_param_absent - name: Absent assertions - assert: + ansible.builtin.assert: that: - provide_absent is changed - provide_absent.previous.0.fvRsPathAtt is defined diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_static_node_mgmt_address/tasks/main.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_static_node_mgmt_address/tasks/main.yml index ce1553a45..ed86fd5fe 100644 --- a/ansible_collections/cisco/aci/tests/integration/targets/aci_static_node_mgmt_address/tasks/main.yml +++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_static_node_mgmt_address/tasks/main.yml @@ -4,12 +4,12 @@ # GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) - name: Test that we have an ACI APIC host, ACI username and ACI password - fail: + ansible.builtin.fail: msg: 'Please define the following variables: aci_hostname, aci_username and aci_password.' when: aci_hostname is not defined or aci_username is not defined or aci_password is not defined - name: Set vars - set_fact: + ansible.builtin.set_fact: aci_info: &aci_info host: "{{ aci_hostname }}" username: "{{ aci_username }}" @@ -20,14 +20,14 @@ output_level: debug - name: Verify Cloud and Non-Cloud Sites in use. - include_tasks: ../../../../../../integration/targets/aci_cloud_provider/tasks/main.yml + ansible.builtin.include_tasks: ../../../../../../integration/targets/aci_cloud_provider/tasks/main.yml - name: Execute tasks only for non-cloud sites when: query_cloud.current == [] # This condition will execute only non-cloud sites block: # block specifies execution of tasks within, based on conditions # Clean Environment - name: Remove node mgmt in_band epg - aci_node_mgmt_epg: + cisco.aci.aci_node_mgmt_epg: <<: *aci_info type: in_band epg: ansible-inband @@ -36,7 +36,7 @@ state: absent - name: Remove node mgmt out_of_band epg - aci_node_mgmt_epg: + cisco.aci.aci_node_mgmt_epg: <<: *aci_info type: out_of_band epg: ansible-outofband @@ -44,7 +44,7 @@ # Add operations - name: Add node mgmt in_band epg - aci_node_mgmt_epg: + cisco.aci.aci_node_mgmt_epg: <<: *aci_info type: in_band epg: ansible-inband @@ -53,14 +53,14 @@ state: present - name: Add node mgmt out_of_band epg - aci_node_mgmt_epg: + cisco.aci.aci_node_mgmt_epg: <<: *aci_info type: out_of_band epg: ansible-outofband state: present - name: Add ipv4 address to mgmt interface in band in check mode - aci_static_node_mgmt_address: + cisco.aci.aci_static_node_mgmt_address: <<: *aci_info epg: ansible-inband pod_id: 1 @@ -73,7 +73,7 @@ register: cm_add_inb - name: Add ipv4 address to mgmt interface out of band in check mode - aci_static_node_mgmt_address: + cisco.aci.aci_static_node_mgmt_address: <<: *aci_info epg: ansible-outofband pod_id: 1 @@ -86,7 +86,7 @@ register: cm_add_oob - name: Add ipv4 address to mgmt interface in band in normal mode - aci_static_node_mgmt_address: + cisco.aci.aci_static_node_mgmt_address: <<: *aci_info epg: ansible-inband pod_id: 1 @@ -98,7 +98,7 @@ register: nm_add_inb - name: Add ipv4 address to mgmt interface out of band in normal mode - aci_static_node_mgmt_address: + cisco.aci.aci_static_node_mgmt_address: <<: *aci_info epg: ansible-outofband pod_id: 1 @@ -110,7 +110,7 @@ register: nm_add_oob - name: Add ipv4 address to mgmt interface in band in normal mode again - aci_static_node_mgmt_address: + cisco.aci.aci_static_node_mgmt_address: <<: *aci_info epg: ansible-inband pod_id: 1 @@ -122,7 +122,7 @@ register: nm_add_inb_again - name: Add ipv4 address to mgmt interface out of band in normal mode again - aci_static_node_mgmt_address: + cisco.aci.aci_static_node_mgmt_address: <<: *aci_info epg: ansible-outofband pod_id: 1 @@ -134,7 +134,7 @@ register: nm_add_oob_again - name: Add another ipv4 address to mgmt interface in band in normal mode - aci_static_node_mgmt_address: + cisco.aci.aci_static_node_mgmt_address: <<: *aci_info epg: ansible-inband pod_id: 1 @@ -146,7 +146,7 @@ register: nm_add_inb_2 - name: Add another ipv4 address to mgmt interface out of band in normal mode - aci_static_node_mgmt_address: + cisco.aci.aci_static_node_mgmt_address: <<: *aci_info epg: ansible-outofband pod_id: 1 @@ -158,7 +158,7 @@ register: nm_add_oob_2 - name: Verify add operations - assert: + ansible.builtin.assert: that: - cm_add_inb is changed - cm_add_inb.sent.mgmtRsInBStNode.attributes.addr == '3.1.1.2/24' @@ -177,7 +177,7 @@ - nm_add_oob_again is not changed - name: Query ipv4 address to mgmt interface in band in normal mode - aci_static_node_mgmt_address: + cisco.aci.aci_static_node_mgmt_address: <<: *aci_info epg: ansible-inband pod_id: 1 @@ -189,7 +189,7 @@ register: nm_query_inb - name: Query ipv4 address to mgmt interface out_of_band in normal mode - aci_static_node_mgmt_address: + cisco.aci.aci_static_node_mgmt_address: <<: *aci_info epg: ansible-outofband pod_id: 1 @@ -201,7 +201,7 @@ register: nm_query_oob - name: Query all addresses in epg in band - aci_static_node_mgmt_address: + cisco.aci.aci_static_node_mgmt_address: <<: *aci_info epg: ansible-inband type: in_band @@ -209,7 +209,7 @@ register: query_all_epg_inb - name: Query all addresses in epg out of band - aci_static_node_mgmt_address: + cisco.aci.aci_static_node_mgmt_address: <<: *aci_info epg: ansible-outofband type: out_of_band @@ -217,21 +217,21 @@ register: query_all_epg_oob - name: Query all in band addresses - aci_static_node_mgmt_address: + cisco.aci.aci_static_node_mgmt_address: <<: *aci_info type: in_band state: query register: query_all_inb - name: Query all out_of_band addresses - aci_static_node_mgmt_address: + cisco.aci.aci_static_node_mgmt_address: <<: *aci_info type: out_of_band state: query register: query_all_oob - name: Verify query operations - assert: + ansible.builtin.assert: that: - nm_query_inb is not changed - nm_query_oob is not changed @@ -245,7 +245,7 @@ - query_all_oob.current.0.mgmtMgmtP.children.0.mgmtOoB.children | length == 2 - name: Remove ipv4 address to mgmt interface in-band - aci_static_node_mgmt_address: + cisco.aci.aci_static_node_mgmt_address: <<: *aci_info epg: ansible-inband pod_id: 1 @@ -257,7 +257,7 @@ register: remove_in_band - name: Remove ipv4 address to mgmt interface out of band - aci_static_node_mgmt_address: + cisco.aci.aci_static_node_mgmt_address: <<: *aci_info epg: ansible-outofband pod_id: 1 @@ -269,7 +269,7 @@ register: remove_out_of_band - name: Remove ipv4 address to mgmt interface in-band again - aci_static_node_mgmt_address: + cisco.aci.aci_static_node_mgmt_address: <<: *aci_info epg: ansible-inband pod_id: 1 @@ -281,7 +281,7 @@ register: remove_in_band_again - name: Remove ipv4 address to mgmt interface out of band again - aci_static_node_mgmt_address: + cisco.aci.aci_static_node_mgmt_address: <<: *aci_info epg: ansible-outofband pod_id: 1 @@ -293,7 +293,7 @@ register: remove_out_of_band_again - name: Verify remove operations - assert: + ansible.builtin.assert: that: - remove_in_band is changed - remove_in_band.previous.0.mgmtRsInBStNode.attributes.addr == '2.1.1.4/24' @@ -306,7 +306,7 @@ # Clean environment for other ci test cases - name: Remove node mgmt in_band epg - aci_node_mgmt_epg: + cisco.aci.aci_node_mgmt_epg: <<: *aci_info type: in_band epg: ansible-inband @@ -315,7 +315,7 @@ state: absent - name: Remove node mgmt out_of_band epg - aci_node_mgmt_epg: + cisco.aci.aci_node_mgmt_epg: <<: *aci_info type: out_of_band epg: ansible-outofband diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_subject_label/aliases b/ansible_collections/cisco/aci/tests/integration/targets/aci_subject_label/aliases new file mode 100644 index 000000000..209b793f9 --- /dev/null +++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_subject_label/aliases @@ -0,0 +1,2 @@ +# No ACI simulator yet, so not enabled +# unsupported diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_subject_label/tasks/main.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_subject_label/tasks/main.yml new file mode 100644 index 000000000..eb39aabf5 --- /dev/null +++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_subject_label/tasks/main.yml @@ -0,0 +1,253 @@ +# Test code for the ACI modules + +# Copyright: (c) 2022, Mark Ciecior (@markciecior) +# Copyright: (c) 2024, Akini Ross (akinross@cisco.com) + +# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) + +- name: Test that we have an ACI APIC host, ACI username and ACI password + ansible.builtin.fail: + msg: 'Please define the following variables: aci_hostname, aci_username and aci_password.' + when: aci_hostname is not defined or aci_username is not defined or aci_password is not defined + +- name: Set vars + ansible.builtin.set_fact: + aci_info: &aci_info + host: "{{ aci_hostname }}" + username: "{{ aci_username }}" + password: "{{ aci_password }}" + validate_certs: '{{ aci_validate_certs | default(false) }}' + use_ssl: '{{ aci_use_ssl | default(true) }}' + use_proxy: '{{ aci_use_proxy | default(true) }}' + output_level: '{{ aci_output_level | default("info") }}' + +- name: Query system information + cisco.aci.aci_system: + <<: *aci_info + id: 1 + state: query + register: version + +- name: Verify Cloud and Non-Cloud Sites in use. + ansible.builtin.include_tasks: ../../../../../../integration/targets/aci_cloud_provider/tasks/main.yml + +- name: Execute tasks only for non-cloud sites + when: + - query_cloud.current == [] + block: + + # CLEAN TEST ENVIRONMENT + - name: Ensure tenant removed + cisco.aci.aci_tenant: &aci_tenant_absent + <<: *aci_info + state: absent + tenant: ansible_test + + # SETUP TEST ENVIRONMENT + - name: Create tenant + cisco.aci.aci_tenant: &aci_tenant_present + <<: *aci_tenant_absent + state: present + + - name: Create BD + cisco.aci.aci_bd: + <<: *aci_tenant_present + bd: ansible_test_bd + + - name: Create VRF + cisco.aci.aci_vrf: + <<: *aci_tenant_present + vrf: ansible_test_vrf + + - name: Create AP + cisco.aci.aci_ap: &aci_ap + <<: *aci_tenant_present + ap: ansible_test_ap + + - name: Create EPG + cisco.aci.aci_epg: + <<: *aci_ap + epg: ansible_test_epg + bd: ansible_test_bd + + - name: Bind End Point Group to Provider Contract + cisco.aci.aci_epg_to_contract: + <<: *aci_tenant_present + ap: ansible_test_ap + epg: ansible_test_epg + contract_type: provider + contract: ansible_test_contract + + - name: Bind End Point Group to Consumer Contract + cisco.aci.aci_epg_to_contract: + <<: *aci_tenant_present + ap: ansible_test_ap + epg: ansible_test_epg + contract_type: consumer + contract: ansible_test_contract + + - name: Create ESG + cisco.aci.aci_esg: + <<: *aci_ap + esg: ansible_test_esg + vrf: ansible_test_vrf + when: version.current.0.topSystem.attributes.version is version('5', '>=') + + - name: Create L2Out + cisco.aci.aci_l2out: + <<: *aci_tenant_present + l2out: ansible_test_l2out + bd: ansible_test_bd + domain: l2Dom + vlan: 3200 + + - name: Create L2Out External End Point Group + cisco.aci.aci_l2out_extepg: + <<: *aci_tenant_present + l2out: ansible_test_l2out + extepg: ansible_test_external_epg + + - name: Create L2Out + cisco.aci.aci_l3out: + <<: *aci_tenant_present + l3out: ansible_test_l3out + vrf: ansible_test_vrf + domain: l3dom + + - name: Create L3Out External End Point Group + cisco.aci.aci_l3out_extepg: + <<: *aci_tenant_present + l3out: ansible_test_l3out + extepg: ansible_test_external_epg + + - name: Bind L3out External End Point Group to Provider Contract + cisco.aci.aci_l3out_extepg_to_contract: + <<: *aci_tenant_present + tenant: ansible_test + l3out: ansible_test_l3out + extepg: ansible_test_external_epg + contract: ansible_test_contract + contract_type: provider + + - name: Bind L3out External End Point Group to Consumer Contract + cisco.aci.aci_l3out_extepg_to_contract: + <<: *aci_tenant_present + tenant: ansible_test + l3out: ansible_test_l3out + extepg: ansible_test_external_epg + contract: ansible_test_contract + contract_type: consumer + + - name: Create Contract + cisco.aci.aci_contract: &aci_contract_present + <<: *aci_tenant_present + contract: ansible_test_contract + + - name: Create Subject + cisco.aci.aci_contract_subject: + <<: *aci_contract_present + subject: ansible_test_subject + + # TESTS THAT ALL PARENT CLASS COMBINATIONS ARE CONFIGURABLE + - name: Execute tests for each parent class + ansible.builtin.include_tasks: subject_label.yml + loop: + - { l2out: "{{ fake_var | default(omit) }}", l3out: "{{ fake_var | default(omit) }}", external_epg: "{{ fake_var | default(omit) }}", contract: "ansible_test_contract", subject: "ansible_test_subject", ap: "{{ fake_var | default(omit) }}", epg: "{{ fake_var | default(omit) }}", esg: "{{ fake_var | default(omit) }}"} + - { l2out: "ansible_test_l2out", l3out: "{{ fake_var | default(omit) }}", external_epg: "ansible_test_external_epg", contract: "{{ fake_var | default(omit) }}", subject: "{{ fake_var | default(omit) }}", ap: "{{ fake_var | default(omit) }}", epg: "{{ fake_var | default(omit) }}", esg: "{{ fake_var | default(omit) }}"} + - { l2out: "{{ fake_var | default(omit) }}", l3out: "ansible_test_l3out", external_epg: "ansible_test_external_epg", contract: "{{ fake_var | default(omit) }}", subject: "{{ fake_var | default(omit) }}", ap: "{{ fake_var | default(omit) }}", epg: "{{ fake_var | default(omit) }}", esg: "{{ fake_var | default(omit) }}"} + - { l2out: "{{ fake_var | default(omit) }}", l3out: "ansible_test_l3out", external_epg: "ansible_test_external_epg", contract: "ansible_test_contract", subject: "{{ fake_var | default(omit) }}", ap: "{{ fake_var | default(omit) }}", epg: "{{ fake_var | default(omit) }}", esg: "{{ fake_var | default(omit) }}"} + - { l2out: "{{ fake_var | default(omit) }}", l3out: "{{ fake_var | default(omit) }}", external_epg: "{{ fake_var | default(omit) }}", contract: "{{ fake_var | default(omit) }}", subject: "{{ fake_var | default(omit) }}", ap: "ansible_test_ap", epg: "ansible_test_epg", esg: "{{ fake_var | default(omit) }}"} + - { l2out: "{{ fake_var | default(omit) }}", l3out: "{{ fake_var | default(omit) }}", external_epg: "{{ fake_var | default(omit) }}", contract: "ansible_test_contract", subject: "{{ fake_var | default(omit) }}", ap: "ansible_test_ap", epg: "ansible_test_epg", esg: "{{ fake_var | default(omit) }}"} + loop_control: + loop_var: parent_class + + - name: Execute tests for esg class which is only supported in 5+ + ansible.builtin.include_tasks: subject_label.yml + loop: + - { l2out: "{{ fake_var | default(omit) }}", l3out: "{{ fake_var | default(omit) }}", external_epg: "{{ fake_var | default(omit) }}", contract: "{{ fake_var | default(omit) }}", subject: "{{ fake_var | default(omit) }}", ap: "ansible_test_ap", epg: "{{ fake_var | default(omit) }}", esg: "ansible_test_esg"} + loop_control: + loop_var: parent_class + when: version.current.0.topSystem.attributes.version is version('5', '>=') + + # ERROR TESTS + - name: Mutually exclusive all provided (error) + cisco.aci.aci_subject_label: + <<: *aci_tenant_present + l2out: ansible_test_l2out + l3out: ansible_test_l3out + subject: ansible_test_subject + epg: ansible_test_epg + esg: ansible_test_esg + register: err_mutually_exclusive_all + ignore_errors: true + + - name: Mutually exclusive two provided (error) + cisco.aci.aci_subject_label: + <<: *aci_tenant_present + l2out: ansible_test_l2out + l3out: ansible_test_l3out + register: err_mutually_exclusive_two + ignore_errors: true + + - name: Mutually exclusive esg with contract provided (error) + cisco.aci.aci_subject_label: + <<: *aci_tenant_present + esg: ansible_test_esg + contract: ansible_test_contract + register: err_mutually_exclusive_esg + ignore_errors: true + + - name: Missing required input one of L2Out, L3Out, EPG, ESG, subject (error) + cisco.aci.aci_subject_label: + <<: *aci_tenant_present + subject_label: ansible_test_l2out + subject_label_type: consumer + register: err_missing_required_input_missing_one_of + ignore_errors: true + + - name: Missing required input subject_type (error) + cisco.aci.aci_subject_label: + <<: *aci_tenant_present + l2out: ansible_test_l2out + register: err_missing_required_input_subject_type + ignore_errors: true + + - name: Missing required input subject_label (error) + cisco.aci.aci_subject_label: + <<: *aci_tenant_present + l2out: ansible_test_l2out + subject_label_type: consumer + register: err_missing_required_input_subject_label + ignore_errors: true + + - name: Missing required input external_epg (error) + cisco.aci.aci_subject_label: + <<: *aci_tenant_present + l2out: ansible_test_l2out + subject_label_type: consumer + subject_label: ansible_test_subject_label + register: err_missing_required_input_external_epg + ignore_errors: true + + - name: Assert input errors + ansible.builtin.assert: + that: + - err_mutually_exclusive_all is failed + - err_mutually_exclusive_all.msg == "parameters are mutually exclusive{{":"}} l2out|l3out|epg|esg|subject" + - err_mutually_exclusive_two is failed + - err_mutually_exclusive_two.msg == "parameters are mutually exclusive{{":"}} l2out|l3out|epg|esg|subject" + - err_mutually_exclusive_esg is failed + - err_mutually_exclusive_esg.msg == "parameters are mutually exclusive{{":"}} esg|contract" + - err_missing_required_input_missing_one_of is failed + - err_missing_required_input_missing_one_of.msg == "state is present but any of the following are missing{{":"}} l2out, l3out, epg, esg, subject" + - err_missing_required_input_subject_type is failed + - err_missing_required_input_subject_type.msg == "missing required arguments{{":"}} subject_label_type" + - err_missing_required_input_subject_label is failed + - err_missing_required_input_subject_label.msg == "state is present but all of the following are missing{{":"}} subject_label" + - err_missing_required_input_external_epg is failed + - err_missing_required_input_external_epg.msg == "missing parameter(s) required by 'l2out'{{":"}} external_epg" + + # CLEAN TEST ENVIRONMENT + - name: Remove tenant + cisco.aci.aci_tenant: + <<: *aci_tenant_absent diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_subject_label/tasks/subject_label.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_subject_label/tasks/subject_label.yml new file mode 100644 index 000000000..bb15cc846 --- /dev/null +++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_subject_label/tasks/subject_label.yml @@ -0,0 +1,188 @@ +- name: Set vars + ansible.builtin.set_fact: + aci_info: &aci_info + host: "{{ aci_hostname }}" + username: "{{ aci_username }}" + password: "{{ aci_password }}" + validate_certs: '{{ aci_validate_certs | default(false) }}' + use_ssl: '{{ aci_use_ssl | default(true) }}' + use_proxy: '{{ aci_use_proxy | default(true) }}' + output_level: '{{ aci_output_level | default("debug") }}' + +# CREATE TESTS +- name: Create subject label (check mode) + cisco.aci.aci_subject_label: &subject_label_present + <<: *aci_info + tenant: ansible_test + l2out: "{{ parent_class.l2out }}" + l3out: "{{ parent_class.l3out }}" + external_epg: "{{ parent_class.external_epg }}" + contract: "{{ parent_class.contract }}" + subject: "{{ parent_class.subject }}" + ap: "{{ parent_class.ap }}" + epg: "{{ parent_class.epg }}" + esg: "{{ parent_class.esg }}" + subject_label_type: consumer + subject_label: ansible_test_subject_label_1 + check_mode: true + register: cm_create_subject_label + +- name: Create subject label + cisco.aci.aci_subject_label: + <<: *subject_label_present + register: nm_create_subject_label + +- name: Create subject label again + cisco.aci.aci_subject_label: + <<: *subject_label_present + register: nm_create_subject_label_again + +- name: Assert create subject label + ansible.builtin.assert: + that: + - cm_create_subject_label is changed + - cm_create_subject_label.previous == [] + - cm_create_subject_label.current == [] + - cm_create_subject_label.proposed.vzConsSubjLbl.attributes.name == "ansible_test_subject_label_1" + - nm_create_subject_label is changed + - nm_create_subject_label.previous == [] + - nm_create_subject_label.current.0.vzConsSubjLbl.attributes.name == "ansible_test_subject_label_1" + - nm_create_subject_label.current.0.vzConsSubjLbl.attributes.descr == "" + - nm_create_subject_label.current.0.vzConsSubjLbl.attributes.isComplement == "no" + - nm_create_subject_label.current.0.vzConsSubjLbl.attributes.tag == "yellow-green" + - nm_create_subject_label_again is not changed + - nm_create_subject_label_again.previous.0.vzConsSubjLbl.attributes.name == "ansible_test_subject_label_1" + - nm_create_subject_label_again.previous.0.vzConsSubjLbl.attributes.descr == "" + - nm_create_subject_label_again.previous.0.vzConsSubjLbl.attributes.isComplement == "no" + - nm_create_subject_label_again.previous.0.vzConsSubjLbl.attributes.tag == "yellow-green" + - nm_create_subject_label_again.current.0.vzConsSubjLbl.attributes.name == "ansible_test_subject_label_1" + - nm_create_subject_label_again.current.0.vzConsSubjLbl.attributes.descr == "" + - nm_create_subject_label_again.current.0.vzConsSubjLbl.attributes.isComplement == "no" + - nm_create_subject_label_again.current.0.vzConsSubjLbl.attributes.tag == "yellow-green" + +# UPDATE TESTS +- name: Update subject label + cisco.aci.aci_subject_label: + <<: *subject_label_present + description: changed_description + complement: true + tag: chartreuse + register: nm_update_subject_label + +- name: Assert update subject label + ansible.builtin.assert: + that: + - nm_update_subject_label is changed + - nm_update_subject_label.previous.0.vzConsSubjLbl.attributes.name == "ansible_test_subject_label_1" + - nm_update_subject_label.previous.0.vzConsSubjLbl.attributes.descr == "" + - nm_update_subject_label.previous.0.vzConsSubjLbl.attributes.isComplement == "no" + - nm_update_subject_label.previous.0.vzConsSubjLbl.attributes.tag == "yellow-green" + - nm_update_subject_label.current.0.vzConsSubjLbl.attributes.name == "ansible_test_subject_label_1" + - nm_update_subject_label.current.0.vzConsSubjLbl.attributes.descr == "changed_description" + - nm_update_subject_label.current.0.vzConsSubjLbl.attributes.isComplement == "yes" + - nm_update_subject_label.current.0.vzConsSubjLbl.attributes.tag == "chartreuse" + +# QUERY TESTS +- name: Create subject label 2 + cisco.aci.aci_subject_label: + <<: *subject_label_present + subject_label: ansible_test_subject_label_2 + tag: cadet_blue + +- name: Create provider subject label 3, 4 and 5 + cisco.aci.aci_subject_label: + <<: *subject_label_present + subject_label: "{{ item }}" + subject_label_type: provider + loop: + - ansible_test_subject_label_3 + - ansible_test_subject_label_4 + - ansible_test_subject_label_5 + register: create_provider_subject_labels + +- name: Assert create of provider subject label + ansible.builtin.assert: + that: + - create_provider_subject_labels.results.0.current.0.vzProvSubjLbl.attributes.name == "ansible_test_subject_label_3" + - create_provider_subject_labels.results.1.current.0.vzProvSubjLbl.attributes.name == "ansible_test_subject_label_4" + - create_provider_subject_labels.results.2.current.0.vzProvSubjLbl.attributes.name == "ansible_test_subject_label_5" + +- name: Query subject label + cisco.aci.aci_subject_label: + <<: *subject_label_present + register: query_one + +- name: Query all consumer subject labels + cisco.aci.aci_subject_label: + <<: *aci_info + subject_label_type: consumer + state: query + register: query_all_consumer + +- name: Query all provider subject labels + cisco.aci.aci_subject_label: + <<: *aci_info + subject_label_type: provider + state: query + register: query_all_provider + +- name: Assert query subject label + ansible.builtin.assert: + that: + - query_one is not changed + - query_one.current.0.vzConsSubjLbl.attributes.name == "ansible_test_subject_label_1" + - query_one.current.0.vzConsSubjLbl.attributes.descr == "changed_description" + - query_one.current.0.vzConsSubjLbl.attributes.isComplement == "yes" + - query_one.current.0.vzConsSubjLbl.attributes.tag == "chartreuse" + - query_all_consumer is not changed + - query_all_consumer.current | length >= 2 + - query_all_provider is not changed + - query_all_provider.current | length >= 3 + +# DELETE TESTS +- name: Delete subject label (check mode) + cisco.aci.aci_subject_label: &subject_label_absent + <<: *subject_label_present + state: absent + check_mode: true + register: cm_delete_subject_label + +- name: Delete subject label + cisco.aci.aci_subject_label: + <<: *subject_label_absent + register: nm_delete_subject_label + +- name: Delete subject label again + cisco.aci.aci_subject_label: + <<: *subject_label_absent + register: nm_delete_subject_label_again + +- name: Assert delete subject label + ansible.builtin.assert: + that: + - cm_delete_subject_label is changed + - cm_delete_subject_label.previous.0.vzConsSubjLbl.attributes.name == "ansible_test_subject_label_1" + - cm_delete_subject_label.current.0.vzConsSubjLbl.attributes.name == "ansible_test_subject_label_1" + - cm_delete_subject_label.proposed == {} + - nm_delete_subject_label is changed + - nm_delete_subject_label.previous.0.vzConsSubjLbl.attributes.name == "ansible_test_subject_label_1" + - nm_delete_subject_label.current == [] + - nm_delete_subject_label_again is not changed + - nm_delete_subject_label_again.previous == [] + - nm_delete_subject_label_again.current == [] + +# CLEAN TEST ENVIRONMENT +- name: Delete consumer subject label 2 + cisco.aci.aci_subject_label: + <<: *subject_label_absent + subject_label: ansible_test_subject_label_2 + +- name: Delete provider subject labels 3, 4 and 5 + cisco.aci.aci_subject_label: + <<: *subject_label_absent + subject_label: "{{ item }}" + subject_label_type: provider + loop: + - ansible_test_subject_label_3 + - ansible_test_subject_label_4 + - ansible_test_subject_label_5 diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_switch_leaf_selector/tasks/main.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_switch_leaf_selector/tasks/main.yml index d57239e49..da683c852 100644 --- a/ansible_collections/cisco/aci/tests/integration/targets/aci_switch_leaf_selector/tasks/main.yml +++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_switch_leaf_selector/tasks/main.yml @@ -4,12 +4,12 @@ # GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) - name: Test that we have an ACI APIC host, ACI username and ACI password - fail: + ansible.builtin.fail: msg: 'Please define the following variables: aci_hostname, aci_username and aci_password.' when: aci_hostname is not defined or aci_username is not defined or aci_password is not defined - name: Verify Cloud and Non-Cloud Sites in use. - include_tasks: ../../../../../../integration/targets/aci_cloud_provider/tasks/main.yml + ansible.builtin.include_tasks: ../../../../../../integration/targets/aci_cloud_provider/tasks/main.yml - name: Execute tasks only for non-cloud sites when: query_cloud.current == [] # This condition will execute only non-cloud sites @@ -69,7 +69,7 @@ # TODO: also test for errors - name: present assertions - assert: + ansible.builtin.assert: that: - sw_leaf_selec_check_mode_present is changed - sw_leaf_selec_present is changed @@ -93,7 +93,7 @@ register: binding_query - name: present assertions - assert: + ansible.builtin.assert: that: - binding_query is not changed - binding_query.current | length >= 1 @@ -126,7 +126,7 @@ register: sw_leaf_selec_absent_missing_param - name: absent assertions - assert: + ansible.builtin.assert: that: - sw_leaf_selec_check_mode_absent is changed - sw_leaf_selec_check_mode_absent.previous != [] diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_switch_policy_leaf_profile/tasks/main.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_switch_policy_leaf_profile/tasks/main.yml index 2bed3b67c..022013c67 100644 --- a/ansible_collections/cisco/aci/tests/integration/targets/aci_switch_policy_leaf_profile/tasks/main.yml +++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_switch_policy_leaf_profile/tasks/main.yml @@ -4,12 +4,12 @@ # GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) - name: Test that we have an ACI APIC host, ACI username and ACI password - fail: + ansible.builtin.fail: msg: 'Please define the following variables: aci_hostname, aci_username and aci_password.' when: aci_hostname is not defined or aci_username is not defined or aci_password is not defined - name: Verify Cloud and Non-Cloud Sites in use. - include_tasks: ../../../../../../integration/targets/aci_cloud_provider/tasks/main.yml + ansible.builtin.include_tasks: ../../../../../../integration/targets/aci_cloud_provider/tasks/main.yml - name: Execute tasks only for non-cloud sites when: query_cloud.current == [] # This condition will execute only non-cloud sites @@ -57,7 +57,7 @@ register: nm_add_switch_leaf_profile_again - name: Verify add_switch_leaf_profile - assert: + ansible.builtin.assert: that: - cm_add_switch_leaf_profile is changed - nm_add_switch_leaf_profile is changed @@ -94,7 +94,7 @@ register: nm_add_switch_leaf_profile_descr_again - name: Verify add_switch_leaf_profile_descr - assert: + ansible.builtin.assert: that: - cm_add_switch_leaf_profile_descr is changed - nm_add_switch_leaf_profile_descr is changed @@ -113,7 +113,7 @@ register: nm_add_switch_leaf_profile_again_no_descr - name: Verify add_switch_leaf_profile_again_no_descr - assert: + ansible.builtin.assert: that: - cm_add_switch_leaf_profile_again_no_descr is not changed - nm_add_switch_leaf_profile_again_no_descr is not changed @@ -138,7 +138,7 @@ register: nm_query_all_switch_leaf_profiles - name: Verify query_all_switch_leaf_profiles - assert: + ansible.builtin.assert: that: - cm_query_all_switch_leaf_profiles is not changed - nm_query_all_switch_leaf_profiles is not changed @@ -161,7 +161,7 @@ register: nm_query_switch_leaf_profile - name: Verify query_switch_leaf_profile - assert: + ansible.builtin.assert: that: - cm_query_switch_leaf_profile is not changed - nm_query_switch_leaf_profile is not changed @@ -188,7 +188,7 @@ register: nm_remove_switch_leaf_profile_again - name: Verify remove_switch_leaf_profile - assert: + ansible.builtin.assert: that: - cm_remove_switch_leaf_profile is changed - nm_remove_switch_leaf_profile is changed @@ -212,7 +212,7 @@ # TODO: Implement more tests - name: Verify query_non_switch_leaf_profile - assert: + ansible.builtin.assert: that: - cm_query_non_switch_leaf_profile is not changed - nm_query_non_switch_leaf_profile is not changed diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_switch_policy_vpc_protection_group/tasks/main.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_switch_policy_vpc_protection_group/tasks/main.yml index c0ef39cfe..a161025a1 100644 --- a/ansible_collections/cisco/aci/tests/integration/targets/aci_switch_policy_vpc_protection_group/tasks/main.yml +++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_switch_policy_vpc_protection_group/tasks/main.yml @@ -4,7 +4,7 @@ # GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) - name: Test that we have an ACI APIC host, ACI username and ACI password - fail: + ansible.builtin.fail: msg: 'Please define the following variables: aci_hostname, aci_username and aci_password.' when: aci_hostname is not defined or aci_username is not defined or aci_password is not defined @@ -54,7 +54,7 @@ register: nm_add_vpc_prot_grp_again - name: Verify add_vpc_prot_grp_again - assert: + ansible.builtin.assert: that: - cm_add_vpc_prot_grp is changed - nm_add_vpc_prot_grp is changed @@ -91,7 +91,7 @@ register: nm_add_vpc_prot_grp_pol_again - name: Verify add_vpc_prot_grp_pol - assert: + ansible.builtin.assert: that: - cm_add_vpc_prot_grp_pol is changed - nm_add_vpc_prot_grp_pol is changed @@ -110,7 +110,7 @@ register: nm_add_vpc_prot_grp_again_no_pol - name: Verify add_vpc_prot_grp_again_no_pol - assert: + ansible.builtin.assert: that: - cm_add_vpc_prot_grp_again_no_pol is not changed - nm_add_vpc_prot_grp_again_no_pol is not changed @@ -135,7 +135,7 @@ register: nm_query_all_vpc_prot_grps - name: Verify query_all_vpc_prot_grps - assert: + ansible.builtin.assert: that: - cm_query_all_vpc_prot_grps is not changed - nm_query_all_vpc_prot_grps is not changed @@ -157,7 +157,7 @@ register: nm_query_vpc_prot_grp - name: Verify query_vpc_prot_grp - assert: + ansible.builtin.assert: that: - cm_query_vpc_prot_grp is not changed - nm_query_vpc_prot_grp is not changed @@ -184,7 +184,7 @@ register: nm_remove_vpc_prot_grp_again - name: Verify remove_vpc_prot_grp - assert: + ansible.builtin.assert: that: - cm_remove_vpc_prot_grp is changed - nm_remove_vpc_prot_grp is changed @@ -207,7 +207,7 @@ register: nm_query_non_vpc_prot_grp - name: Verify query_non_vpc_prot_grp - assert: + ansible.builtin.assert: that: - cm_query_non_vpc_prot_grp is not changed - nm_query_non_vpc_prot_grp is not changed diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_syslog_group/tasks/main.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_syslog_group/tasks/main.yml index f80ca35d2..34a2ddf63 100644 --- a/ansible_collections/cisco/aci/tests/integration/targets/aci_syslog_group/tasks/main.yml +++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_syslog_group/tasks/main.yml @@ -4,13 +4,13 @@ # GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) - name: Test that we have an ACI APIC host, ACI username and ACI password - fail: + ansible.builtin.fail: msg: 'Please define the following variables: aci_hostname, aci_username and aci_password.' when: aci_hostname is not defined or aci_username is not defined or aci_password is not defined # GET Credentials from the inventory - name: Set vars - set_fact: + ansible.builtin.set_fact: aci_info: &aci_info host: "{{ aci_hostname }}" username: "{{ aci_username }}" @@ -67,7 +67,7 @@ when: version.current.0.topSystem.attributes.version is version('4', '<') - name: Verify that ansible_syslog_group has been created with correct attributes (version > 4) - assert: + ansible.builtin.assert: that: - add_syslog_group.current.0.syslogGroup.attributes.dn == "uni/fabric/slgroup-ansible_syslog_group" - add_syslog_group.current.0.syslogGroup.attributes.name == "ansible_syslog_group" @@ -78,7 +78,7 @@ when: version.current.0.topSystem.attributes.version is version('4', '>=') - name: Verify that ansible_syslog_group has been created with correct attributes (version < 4) - assert: + ansible.builtin.assert: that: - add_syslog_group_32.current.0.syslogGroup.attributes.dn == "uni/fabric/slgroup-ansible_syslog_group" - add_syslog_group_32.current.0.syslogGroup.attributes.name == "ansible_syslog_group" @@ -88,7 +88,7 @@ when: version.current.0.topSystem.attributes.version is version('4', '<') - name: Verify that ansible_syslog_group children have correct attributes (version >= 4) - assert: + ansible.builtin.assert: that: - add_syslog_group.current.0.syslogGroup.children.0.syslogConsole.attributes.adminState == "enabled" - add_syslog_group.current.0.syslogGroup.children.0.syslogConsole.attributes.severity == "critical" @@ -98,7 +98,7 @@ when: version.current.0.topSystem.attributes.version is version('4', '>=') - name: Verify that ansible_syslog_group children have correct attributes (version < 4) - assert: + ansible.builtin.assert: that: - add_syslog_group_32.current.0.syslogGroup.children.0.syslogConsole.attributes.adminState == "enabled" - add_syslog_group_32.current.0.syslogGroup.children.0.syslogConsole.attributes.severity == "critical" @@ -121,13 +121,13 @@ when: version.current.0.topSystem.attributes.version is version('4', '<') - name: Verify that ansible_syslog_group stays the same (version >= 4) - assert: + ansible.builtin.assert: that: - add_syslog_group_again is not changed when: version.current.0.topSystem.attributes.version is version('4', '>=') - name: Verify that ansible_syslog_group stays the same (version < 4) - assert: + ansible.builtin.assert: that: - add_syslog_group_again_32 is not changed when: version.current.0.topSystem.attributes.version is version('4', '<') @@ -165,7 +165,7 @@ when: version.current.0.topSystem.attributes.version is version('4', '<') - name: Verify that ansible_syslog_group has been updated with correct attributes (version >= 4) - assert: + ansible.builtin.assert: that: - update_syslog_group.current.0.syslogGroup.attributes.dn == "uni/fabric/slgroup-ansible_syslog_group" - update_syslog_group.current.0.syslogGroup.attributes.name == "ansible_syslog_group" @@ -175,7 +175,7 @@ when: version.current.0.topSystem.attributes.version is version('4', '>=') - name: Verify that ansible_syslog_group has been updated with correct attributes (version < 4) - assert: + ansible.builtin.assert: that: - update_syslog_group_32.current.0.syslogGroup.attributes.dn == "uni/fabric/slgroup-ansible_syslog_group" - update_syslog_group_32.current.0.syslogGroup.attributes.name == "ansible_syslog_group" @@ -184,7 +184,7 @@ when: version.current.0.topSystem.attributes.version is version('4', '<') - name: Verify that ansible_syslog_group children have correct attributes (version >= 4) - assert: + ansible.builtin.assert: that: - update_syslog_group.current.0.syslogGroup.children.0.syslogConsole.attributes.adminState == "disabled" - update_syslog_group.current.0.syslogGroup.children.0.syslogConsole.attributes.severity == "emergencies" @@ -194,7 +194,7 @@ when: version.current.0.topSystem.attributes.version is version('4', '>=') - name: Verify that ansible_syslog_group children have correct attributes (version < 4) - assert: + ansible.builtin.assert: that: - update_syslog_group_32.current.0.syslogGroup.children.0.syslogConsole.attributes.adminState == "disabled" - update_syslog_group_32.current.0.syslogGroup.children.0.syslogConsole.attributes.severity == "emergencies" @@ -212,7 +212,7 @@ register: query_syslog_group - name: Verify the attributes under query_syslog_group - assert: + ansible.builtin.assert: that: - query_syslog_group is not changed - query_syslog_group.current.0.syslogGroup.attributes.dn == "uni/fabric/slgroup-ansible_syslog_group" @@ -225,7 +225,7 @@ register: query_syslog_group_all - name: Verify query_syslog_group_all - assert: + ansible.builtin.assert: that: - query_syslog_group_all is not changed @@ -238,7 +238,7 @@ register: remove_syslog_group - name: Verify remove_syslog_group - assert: + ansible.builtin.assert: that: - remove_syslog_group is changed - remove_syslog_group.previous.0.syslogGroup.attributes.dn == "uni/fabric/slgroup-ansible_syslog_group" diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_syslog_remote_dest/tasks/main.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_syslog_remote_dest/tasks/main.yml index 82839ddf7..73fddc6f7 100644 --- a/ansible_collections/cisco/aci/tests/integration/targets/aci_syslog_remote_dest/tasks/main.yml +++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_syslog_remote_dest/tasks/main.yml @@ -4,13 +4,13 @@ # GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) - name: Test that we have an ACI APIC host, ACI username and ACI password - fail: + ansible.builtin.fail: msg: 'Please define the following variables: aci_hostname, aci_username and aci_password.' when: aci_hostname is not defined or aci_username is not defined or aci_password is not defined # GET Credentials from the inventory - name: Set vars - set_fact: + ansible.builtin.set_fact: aci_info: &aci_info host: "{{ aci_hostname }}" username: "{{ aci_username }}" @@ -22,7 +22,7 @@ # CLEAN ENVIRONMENT - name: Remove ansible_syslog_src if it already exists - aci_syslog_remote_dest: + cisco.aci.aci_syslog_remote_dest: <<: *aci_info group: ansible_syslog_group destination: "10.20.30.40" @@ -30,7 +30,7 @@ # ADD syslog group - name: Add syslog group - aci_syslog_group: + cisco.aci.aci_syslog_group: <<: *aci_info name: ansible_syslog_group admin_state: enabled @@ -38,7 +38,7 @@ # ADD syslog remote destination - name: Add syslog remote destination - aci_syslog_remote_dest: + cisco.aci.aci_syslog_remote_dest: <<: *aci_info group: ansible_syslog_group destination: "10.20.30.40" @@ -53,7 +53,7 @@ register: add_syslog_remote_dest - name: Verify that ansible_syslog_src has been created with correct attributes - assert: + ansible.builtin.assert: that: - add_syslog_remote_dest.current.0.syslogRemoteDest.attributes.dn == "uni/fabric/slgroup-ansible_syslog_group/rdst-10.20.30.40" - add_syslog_remote_dest.current.0.syslogRemoteDest.attributes.name == "remote_destination_name" @@ -69,7 +69,7 @@ # ADD syslog remote dest again to check idempotency - name: Add syslog remote dest - aci_syslog_remote_dest: + cisco.aci.aci_syslog_remote_dest: <<: *aci_info group: ansible_syslog_group destination: "10.20.30.40" @@ -84,13 +84,13 @@ register: add_syslog_remote_dest_again - name: Verify that ansible_syslog_remote_dest stays the same - assert: + ansible.builtin.assert: that: - add_syslog_remote_dest_again is not changed # MODIFY syslog remote destination - name: Update the syslog remote destination - aci_syslog_remote_dest: + cisco.aci.aci_syslog_remote_dest: <<: *aci_info group: ansible_syslog_group destination: "10.20.30.40" @@ -106,7 +106,7 @@ register: update_syslog_remote_dest - name: Verify that ansible_syslog_src has been updated with correct attributes - assert: + ansible.builtin.assert: that: - update_syslog_remote_dest.current.0.syslogRemoteDest.attributes.dn == "uni/fabric/slgroup-ansible_syslog_group/rdst-10.20.30.40" - update_syslog_remote_dest.current.0.syslogRemoteDest.attributes.name == "new_remote_destination_name" @@ -119,13 +119,13 @@ - update_syslog_remote_dest.current.0.syslogRemoteDest.attributes.severity == "information" - name: Verify that ansible_syslog_remote_dest children have correct attributes - assert: + ansible.builtin.assert: that: - update_syslog_remote_dest.current.0.syslogRemoteDest.children.0.fileRsARemoteHostToEpg.attributes.tDn == "uni/tn-mgmt/mgmtp-default/oob-default" # QUERY syslog source - name: Query the syslog source - aci_syslog_remote_dest: + cisco.aci.aci_syslog_remote_dest: <<: *aci_info group: ansible_syslog_group destination: "10.20.30.40" @@ -133,7 +133,7 @@ register: query_syslog_remote_dest - name: Verify the attributes under query_syslog_src - assert: + ansible.builtin.assert: that: - query_syslog_remote_dest is not changed - query_syslog_remote_dest.current.0.syslogRemoteDest.attributes.dn == "uni/fabric/slgroup-ansible_syslog_group/rdst-10.20.30.40" @@ -147,19 +147,19 @@ - query_syslog_remote_dest.current.0.syslogRemoteDest.attributes.severity == "information" - name: Query all syslog remote destinations - aci_syslog_remote_dest: + cisco.aci.aci_syslog_remote_dest: <<: *aci_info state: query register: query_syslog_remote_dest_all - name: Verify query_syslog_remote_dest_all - assert: + ansible.builtin.assert: that: - query_syslog_remote_dest_all is not changed # DELETE syslog remote destination - name: Remove the syslog remote dest - aci_syslog_remote_dest: + cisco.aci.aci_syslog_remote_dest: <<: *aci_info group: ansible_syslog_group destination: "10.20.30.40" @@ -167,7 +167,7 @@ register: remove_syslog_remote_dest - name: Verify remove_syslog_remote_dest - assert: + ansible.builtin.assert: that: - remove_syslog_remote_dest is changed - remove_syslog_remote_dest.current == [] @@ -175,7 +175,7 @@ # DELETE syslog remote destination again to test idempotence - name: Remove the syslog remote dest again - aci_syslog_remote_dest: + cisco.aci.aci_syslog_remote_dest: <<: *aci_info group: ansible_syslog_group destination: "10.20.30.40" @@ -183,13 +183,13 @@ register: remove_syslog_remote_dest_again - name: Verify remove_syslog_remote_dest idempotence - assert: + ansible.builtin.assert: that: - remove_syslog_remote_dest_again is not changed # DELETE syslog group - name: Remove syslog group - aci_syslog_group: + cisco.aci.aci_syslog_group: <<: *aci_info name: ansible_syslog_group admin_state: enabled diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_syslog_source/tasks/main.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_syslog_source/tasks/main.yml index a7180649f..b2c7bd866 100644 --- a/ansible_collections/cisco/aci/tests/integration/targets/aci_syslog_source/tasks/main.yml +++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_syslog_source/tasks/main.yml @@ -4,13 +4,13 @@ # GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) - name: Test that we have an ACI APIC host, ACI username and ACI password - fail: + ansible.builtin.fail: msg: 'Please define the following variables: aci_hostname, aci_username and aci_password.' when: aci_hostname is not defined or aci_username is not defined or aci_password is not defined # GET Credentials from the inventory - name: Set vars - set_fact: + ansible.builtin.set_fact: aci_info: &aci_info host: "{{ aci_hostname }}" username: "{{ aci_username }}" @@ -22,14 +22,14 @@ # CLEAN ENVIRONMENT - name: Remove ansible_syslog_src if it already exists - aci_syslog_source: + cisco.aci.aci_syslog_source: <<: *aci_info name: ansible_syslog_src state: absent # ADD syslog group - name: Add syslog group - aci_syslog_group: + cisco.aci.aci_syslog_group: <<: *aci_info name: ansible_syslog_group admin_state: enabled @@ -37,7 +37,7 @@ # ADD syslog source - name: Add syslog source - aci_syslog_source: + cisco.aci.aci_syslog_source: <<: *aci_info name: ansible_syslog_src min_severity: errors @@ -46,7 +46,7 @@ register: add_syslog_src - name: Verify that ansible_syslog_src has been created with correct attributes - assert: + ansible.builtin.assert: that: - add_syslog_src.current.0.syslogSrc.attributes.dn == "uni/fabric/moncommon/slsrc-ansible_syslog_src" - add_syslog_src.current.0.syslogSrc.attributes.name == "ansible_syslog_src" @@ -55,13 +55,13 @@ - add_syslog_src.current.0.syslogSrc.attributes.annotation == 'orchestrator:ansible' - name: Verify that ansible_syslog_src children have correct attributes - assert: + ansible.builtin.assert: that: - add_syslog_src.current.0.syslogSrc.children.0.syslogRsDestGroup.attributes.tDn == "uni/fabric/slgroup-ansible_syslog_group" # ADD syslog source again to check idempotency - name: Add syslog source - aci_syslog_source: + cisco.aci.aci_syslog_source: <<: *aci_info name: ansible_syslog_src min_severity: errors @@ -70,13 +70,13 @@ register: add_syslog_src_again - name: Verify that ansible_syslog_src stays the same - assert: + ansible.builtin.assert: that: - add_syslog_src_again is not changed # MODIFY syslog source - name: Update the syslog source - aci_syslog_source: + cisco.aci.aci_syslog_source: <<: *aci_info name: ansible_syslog_src include: @@ -89,7 +89,7 @@ register: update_syslog_src - name: Verify that ansible_syslog_src has been updated with correct attributes - assert: + ansible.builtin.assert: that: - update_syslog_src.current.0.syslogSrc.attributes.dn == "uni/fabric/moncommon/slsrc-ansible_syslog_src" - update_syslog_src.current.0.syslogSrc.attributes.name == "ansible_syslog_src" @@ -98,14 +98,14 @@ # QUERY syslog source - name: Query the syslog source - aci_syslog_source: + cisco.aci.aci_syslog_source: <<: *aci_info name: ansible_syslog_src state: query register: query_syslog_src - name: Verify the attributes under query_syslog_src - assert: + ansible.builtin.assert: that: - query_syslog_src is not changed - query_syslog_src.current.0.syslogSrc.attributes.dn == "uni/fabric/moncommon/slsrc-ansible_syslog_src" @@ -114,26 +114,26 @@ - query_syslog_src.current.0.syslogSrc.attributes.minSev == "information" - name: Query all syslog sources - aci_syslog_source: + cisco.aci.aci_syslog_source: <<: *aci_info state: query register: query_syslog_src_all - name: Verify query_syslog_src_all - assert: + ansible.builtin.assert: that: - query_syslog_src_all is not changed # DELETE syslog source - name: Remove the syslog source - aci_syslog_source: + cisco.aci.aci_syslog_source: <<: *aci_info name: ansible_syslog_src state: absent register: remove_syslog_src - name: Verify remove_syslog_src - assert: + ansible.builtin.assert: that: - remove_syslog_src is changed - remove_syslog_src.current == [] @@ -142,20 +142,20 @@ # DELETE syslog source again to test idempotence - name: Remove the syslog source - aci_syslog_source: + cisco.aci.aci_syslog_source: <<: *aci_info name: ansible_syslog_src state: absent register: remove_syslog_src_again - name: Verify remove_syslog_src idempotence - assert: + ansible.builtin.assert: that: - remove_syslog_src_again is not changed # DELETE syslog group - name: Remove syslog group - aci_syslog_group: + cisco.aci.aci_syslog_group: <<: *aci_info name: ansible_syslog_group admin_state: enabled diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_system/tasks/main.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_system/tasks/main.yml index 6be69c245..21555c224 100644 --- a/ansible_collections/cisco/aci/tests/integration/targets/aci_system/tasks/main.yml +++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_system/tasks/main.yml @@ -4,13 +4,13 @@ # GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) - name: Test that we have an ACI APIC host, ACI username and ACI password - fail: + ansible.builtin.fail: msg: 'Please define the following variables: aci_hostname, aci_username and aci_password.' when: aci_hostname is not defined or aci_username is not defined or aci_password is not defined # CLEAN ENVIRONMENT - name: Set vars - set_fact: + ansible.builtin.set_fact: aci_info: &aci_info host: "{{ aci_hostname }}" username: "{{ aci_username }}" @@ -22,13 +22,13 @@ # QUERY OBJECTS - name: Query all controllers system information - aci_system: + cisco.aci.aci_system: <<: *aci_info state: query register: query_all - name: Verify query_all - assert: + ansible.builtin.assert: that: - query_all is not changed - query_all.current.0.topSystem.attributes.id == "1" @@ -36,28 +36,28 @@ - name: Query a specific controller system information - aci_system: + cisco.aci.aci_system: <<: *aci_info id: 1 state: query register: query_controller - name: Verify query_controller - assert: + ansible.builtin.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: + cisco.aci.aci_system: <<: *aci_info id: 99 state: query register: query_non_existing - name: Verify query_non_existing - assert: + ansible.builtin.assert: that: - query_non_existing is not changed - query_non_existing.current == [] \ No newline at end of file diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_system_banner/tasks/main.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_system_banner/tasks/main.yml index 5b9cb96f0..7e750af42 100644 --- a/ansible_collections/cisco/aci/tests/integration/targets/aci_system_banner/tasks/main.yml +++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_system_banner/tasks/main.yml @@ -5,12 +5,12 @@ # GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) - name: Test that we have an ACI APIC host, ACI username and ACI password - fail: + ansible.builtin.fail: msg: 'Please define the following variables: aci_hostname, aci_username and aci_password.' when: aci_hostname is not defined or aci_username is not defined or aci_password is not defined - name: Set vars - set_fact: + ansible.builtin.set_fact: aci_info: &aci_info host: "{{ aci_hostname }}" username: "{{ aci_username }}" diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_system_endpoint_controls/tasks/main.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_system_endpoint_controls/tasks/main.yml index fa98657f6..8b480175d 100644 --- a/ansible_collections/cisco/aci/tests/integration/targets/aci_system_endpoint_controls/tasks/main.yml +++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_system_endpoint_controls/tasks/main.yml @@ -4,12 +4,12 @@ # GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) - name: Test that we have an ACI APIC host, ACI username and ACI password - fail: + ansible.builtin.fail: msg: 'Please define the following variables: aci_hostname, aci_username and aci_password.' when: aci_hostname is not defined or aci_username is not defined or aci_password is not defined - name: Set vars - set_fact: + ansible.builtin.set_fact: aci_info: &aci_info host: "{{ aci_hostname }}" username: "{{ aci_username }}" @@ -20,7 +20,7 @@ output_level: '{{ aci_output_level | default("info") }}' - name: Verify Cloud and Non-Cloud Sites in use. - include_tasks: ../../../../../../integration/targets/aci_cloud_provider/tasks/main.yml + ansible.builtin.include_tasks: ../../../../../../integration/targets/aci_cloud_provider/tasks/main.yml - name: Execute tasks only for non-cloud sites when: query_cloud.current == [] # This condition will skip execution for cloud sites diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_system_global_aes_passphrase_encryption/tasks/main.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_system_global_aes_passphrase_encryption/tasks/main.yml index 732a4d4f3..2fdebe23b 100644 --- a/ansible_collections/cisco/aci/tests/integration/targets/aci_system_global_aes_passphrase_encryption/tasks/main.yml +++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_system_global_aes_passphrase_encryption/tasks/main.yml @@ -5,13 +5,13 @@ # GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) - name: Test that we have an ACI APIC host, ACI username and ACI password - fail: + ansible.builtin.fail: msg: 'Please define the following variables: aci_hostname, aci_username and aci_password.' when: aci_hostname is not defined or aci_username is not defined or aci_password is not defined # SET VARS - name: Set vars - set_fact: + ansible.builtin.set_fact: aci_info: &aci_info host: '{{ aci_hostname }}' username: '{{ aci_username }}' @@ -22,7 +22,7 @@ output_level: '{{ aci_output_level | default("info") }}' - name: Verify Cloud and Non-Cloud Sites in use. - include_tasks: ../../../../../../integration/targets/aci_cloud_provider/tasks/main.yml + ansible.builtin.include_tasks: ../../../../../../integration/targets/aci_cloud_provider/tasks/main.yml - name: Execute tasks only for non-cloud sites when: query_cloud.current == [] # This condition will skip execution for cloud sites diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_taboo_contract/tasks/main.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_taboo_contract/tasks/main.yml index 8a5bb5911..19304b8fe 100644 --- a/ansible_collections/cisco/aci/tests/integration/targets/aci_taboo_contract/tasks/main.yml +++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_taboo_contract/tasks/main.yml @@ -52,7 +52,7 @@ register: nm_add_taboo_contract - name: Verify add_taboo_contract - assert: + ansible.builtin.assert: that: - cm_add_taboo_contract is changed - nm_add_taboo_contract is changed @@ -76,7 +76,7 @@ register: nm_add_taboo_contract_again - name: Verify add_taboo_contract_again - assert: + ansible.builtin.assert: that: - cm_add_taboo_contract_again is not changed - nm_add_taboo_contract_again is not changed @@ -98,7 +98,7 @@ register: nm_add_taboo_contract_descr - name: Verify add_taboo_contract_descr - assert: + ansible.builtin.assert: that: - cm_add_taboo_contract_descr is changed - nm_add_taboo_contract_descr is changed @@ -124,7 +124,7 @@ register: nm_add_taboo_contract_descr_again - name: Verify add_taboo_contract_descr_again - assert: + ansible.builtin.assert: that: - cm_add_taboo_contract_descr_again is not changed - nm_add_taboo_contract_descr_again is not changed @@ -142,7 +142,7 @@ register: nm_add_taboo_contract_again_no_descr - name: Verify add_taboo_contract_again_no_descr - assert: + ansible.builtin.assert: that: - cm_add_taboo_contract_again_no_descr is not changed - nm_add_taboo_contract_again_no_descr is not changed @@ -168,7 +168,7 @@ register: nm_query_all_taboo_contracts - name: Verify query_all_taboo_contracts - assert: + ansible.builtin.assert: that: - cm_query_all_taboo_contracts is not changed - nm_query_all_taboo_contracts is not changed @@ -193,7 +193,7 @@ register: nm_query_taboo_contract - name: Verify query_taboo_contract - assert: + ansible.builtin.assert: that: - cm_query_taboo_contract is not changed - nm_query_taboo_contract is not changed @@ -214,7 +214,7 @@ register: nm_remove_taboo_contract - name: Verify remove_taboo_contract - assert: + ansible.builtin.assert: that: - cm_remove_taboo_contract is changed - nm_remove_taboo_contract is changed @@ -233,7 +233,7 @@ register: nm_remove_taboo_contract_again - name: Verify remove_taboo_contract_again - assert: + ansible.builtin.assert: that: - cm_remove_taboo_contract_again is not changed - nm_remove_taboo_contract_again is not changed @@ -261,7 +261,7 @@ # TODO: Implement more tests - name: Verify query_non_taboo_contract - assert: + ansible.builtin.assert: that: - cm_query_non_taboo_contract is not changed - nm_query_non_taboo_contract is not changed @@ -284,7 +284,7 @@ register: error_on_missing_required_param - name: Verify error_on_missing_required_param - assert: + ansible.builtin.assert: that: - error_on_missing_required_param is failed - 'error_on_missing_required_param.msg == "state is present but all of the following are missing: tenant, taboo_contract"' diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_tag/tasks/main.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_tag/tasks/main.yml index e5a13ba7b..14d145dcf 100644 --- a/ansible_collections/cisco/aci/tests/integration/targets/aci_tag/tasks/main.yml +++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_tag/tasks/main.yml @@ -4,12 +4,12 @@ # GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) - name: Test that we have an ACI APIC host, ACI username and ACI password - fail: + ansible.builtin.fail: msg: 'Please define the following variables: aci_hostname, aci_username and aci_password.' when: aci_hostname is not defined or aci_username is not defined or aci_password is not defined - name: Set vars - set_fact: + ansible.builtin.set_fact: aci_info: &aci_info host: "{{ aci_hostname }}" username: "{{ aci_username }}" @@ -20,7 +20,7 @@ output_level: debug - name: Verify Cloud and Non-Cloud Sites in use. - include_tasks: ../../../../../../integration/targets/aci_cloud_provider/tasks/main.yml + ansible.builtin.include_tasks: ../../../../../../integration/targets/aci_cloud_provider/tasks/main.yml - name: Remove tenant to cleanup cisco.aci.aci_tenant: @@ -36,7 +36,7 @@ register: query_result - name: Get DN - set_fact: + ansible.builtin.set_fact: dn: "{{ query_result.current[0].fvTenant.attributes.dn }}" - name: Annotation Create tag (check_mode) @@ -57,7 +57,7 @@ register: nm_annotation_create - name: Annotation tag created - assert: + ansible.builtin.assert: that: - cm_annotation_create is changed - cm_annotation_create.proposed.tagAnnotation.attributes.value == "bar" @@ -79,7 +79,7 @@ register: nm_annotation_create_again - name: Annotation tag create again - assert: + ansible.builtin.assert: that: - cm_annotation_create_again is not changed - cm_annotation_create_again.current.0.tagAnnotation.attributes.key == "foo" @@ -95,7 +95,7 @@ register: annotation_query_result - name: Annotation tag query verification - assert: + ansible.builtin.assert: that: - annotation_query_result is not changed - annotation_query_result.current.0.tagAnnotation.attributes.key == "foo" @@ -110,12 +110,12 @@ register: annotation_query_all - name: Annotation tag query verification - assert: + ansible.builtin.assert: that: - annotation_query_all is not changed - name: Annotation tag query verification (continued) - assert: + ansible.builtin.assert: that: - annotation_query_all.current.0.tagAnnotation.attributes.key == "foo" - annotation_query_all.current.0.tagAnnotation.attributes.value == "bar" @@ -136,7 +136,7 @@ register: nm_annotation_delete - name: Annotation tag deleted - assert: + ansible.builtin.assert: that: - cm_annotation_delete is changed - nm_annotation_delete is changed @@ -161,7 +161,7 @@ register: nm_annotation_delete_again - name: Annotation tag deleted again - assert: + ansible.builtin.assert: that: - cm_annotation_delete_again is not changed - nm_annotation_delete_again is not changed @@ -187,7 +187,7 @@ register: nm_instance_create - name: Instance tag created - assert: + ansible.builtin.assert: that: - cm_instance_create is changed - nm_instance_create is changed @@ -207,7 +207,7 @@ register: nm_instance_create_again - name: Instance tag create again - assert: + ansible.builtin.assert: that: - cm_instance_create_again is not changed - cm_instance_create_again.current.0.tagInst.attributes.name == "foo" @@ -221,7 +221,7 @@ register: instance_query_result - name: Instance tag query verification - assert: + ansible.builtin.assert: that: - instance_query_result is not changed - instance_query_result.current.0.tagInst.attributes.name == "foo" @@ -235,12 +235,12 @@ register: instance_query_all - name: Instance tag query verification - assert: + ansible.builtin.assert: that: - instance_query_all is not changed - name: Instance tag query verification (continued) - assert: + ansible.builtin.assert: that: - instance_query_all.current.0.tagInst.attributes.name == "foo" when: query_cloud.current == [] # This condition will skip execution for cloud sites @@ -260,7 +260,7 @@ register: nm_instance_delete - name: Instance tag deleted - assert: + ansible.builtin.assert: that: - cm_instance_delete is changed - nm_instance_delete is changed @@ -283,7 +283,7 @@ register: nm_instance_delete_again - name: Instance tag deleted again - assert: + ansible.builtin.assert: that: - cm_instance_delete_again is not changed - nm_instance_delete_again is not changed @@ -310,7 +310,7 @@ register: nm_tag_create - name: Tag tag created - assert: + ansible.builtin.assert: that: - cm_tag_create is changed - cm_tag_create.proposed.tagTag.attributes.value == "bar" @@ -332,7 +332,7 @@ register: nm_tag_create_again - name: Tag tag create again - assert: + ansible.builtin.assert: that: - cm_tag_create_again is not changed - cm_tag_create_again.current.0.tagTag.attributes.key == "foo" @@ -348,7 +348,7 @@ register: tag_query_result - name: Tag tag query verification - assert: + ansible.builtin.assert: that: - tag_query_result is not changed - tag_query_result.current.0.tagTag.attributes.key == "foo" @@ -363,12 +363,12 @@ register: tag_query_all - name: Tag tag query verification - assert: + ansible.builtin.assert: that: - tag_query_all is not changed - name: Tag tag query verification (continued) - assert: + ansible.builtin.assert: that: - tag_query_all.current.0.tagTag.attributes.key == "foo" - tag_query_all.current.0.tagTag.attributes.value == "bar" @@ -389,7 +389,7 @@ register: nm_tag_delete - name: Tag tag deleted - assert: + ansible.builtin.assert: that: - cm_tag_delete is changed - nm_tag_delete is changed @@ -414,7 +414,7 @@ register: nm_tag_delete_again - name: Tag tag deleted again - assert: + ansible.builtin.assert: that: - cm_tag_delete_again is not changed - nm_tag_delete_again is not changed diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_tenant/tasks/httpapi_connection.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_tenant/tasks/httpapi_connection.yml index 214f55fe2..885ff3f9a 100644 --- a/ansible_collections/cisco/aci/tests/integration/targets/aci_tenant/tasks/httpapi_connection.yml +++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_tenant/tasks/httpapi_connection.yml @@ -1,7 +1,7 @@ ## Tests HTTTP Connection when a list of host are provided - name: Set vars - set_fact: + ansible.builtin.set_fact: aci_info: &aci_info host: "{{ aci_hostname }}" username: "{{ aci_username }}" @@ -35,7 +35,7 @@ ansible_command_timeout: 5 - name: Run aci_aaa_user_certificate through the plugin - include_tasks: ../../../../../../integration/targets/aci_aaa_user_certificate/tasks/main.yml + ansible.builtin.include_tasks: ../../../../../../integration/targets/aci_aaa_user_certificate/tasks/main.yml - name: Add user certificate to be used later in the test cisco.aci.aci_aaa_user_certificate: @@ -103,7 +103,7 @@ no_username_flattened: "{{ no_username.httpapi_logs | flatten }}" - name: Verify XML operation and HTTP error returned by APIC - assert: + ansible.builtin.assert: that: - tenant_xml_plugin.status == 200 - '"Received response from {{ aci_hostname }} for POST operation with HTTP: 400" in ap_non_existent_tenant_flattened' @@ -160,7 +160,7 @@ op18_flattened_task_pwd_add_ap: "{{ op18_task_pwd_add_ap.httpapi_logs | flatten }}" - name: Verify forbidden error 403 - assert: + ansible.builtin.assert: that: - op17_task_pwd_add_tenant is changed - op18_task_pwd_add_ap is changed @@ -169,7 +169,7 @@ - '"Connection to {{ aci_hostname }} was successful" in op18_flattened_task_pwd_add_ap' - name: reset connection to test other scenarios - meta: reset_connection + ansible.builtin.meta: reset_connection # Precedence test - name: Delete Tenant with password and private key in the task (private_key takes precedence) @@ -246,7 +246,7 @@ op4_flattened_inventory_pwd_add_tenant: "{{ op4_inventory_pwd_add_tenant.httpapi_logs | flatten }}" - name: Verify Precedence - assert: + ansible.builtin.assert: that: - '"Provided Hosts: [''{{ aci_hostname }}'']" in op1_flattened_task_private_key_delete_tenant' - '"Initializing operation on {{ aci_hostname }}" in op1_flattened_task_private_key_delete_tenant' @@ -270,7 +270,7 @@ - '"Connection to {{ aci_hostname }} was successful" not in op4_flattened_inventory_pwd_add_tenant' - name: reset connection to test other scenarios - meta: reset_connection + ansible.builtin.meta: reset_connection # Switching of hosts test with the password in the task - name: Delete Tenant with only password in the task (Check for successful operation on the last host) @@ -295,7 +295,7 @@ op5_flattened_task_pwd_add_tenant: "{{ op5_task_pwd_add_tenant.httpapi_logs | flatten }}" - name: Verify switching of hosts with the password in the task - assert: + ansible.builtin.assert: that: - op5_task_pwd_delete_tenant is changed - op5_flattened_task_pwd_delete_tenant | regex_search('Switching host from [0-9]+(?:\.[0-9]+){3} to {{ aci_hostname }}') is not none @@ -327,7 +327,7 @@ op6_flattened_task_pwd_add_tenant: "{{ op6_task_pwd_add_tenant.httpapi_logs | flatten }}" - name: Verify continuation of the operations on the connected host with the password in the task - assert: + ansible.builtin.assert: that: - op6_task_pwd_delete_tenant is changed - '"Connected host {{ aci_hostname }} found in the provided hosts. Continuing with it." in op6_flattened_task_pwd_delete_tenant' @@ -353,7 +353,7 @@ register: op7_task_pwd_add_tenant - name: Verify failure when no hosts are active - assert: + ansible.builtin.assert: that: - op7_task_pwd_delete_tenant.error.text | regex_search('No hosts left in the cluster to continue operation! Error on final host [0-9]+(?:\.[0-9]+){3}') is not none - op7_task_pwd_add_tenant is not changed @@ -383,7 +383,7 @@ op8_flattened_inventory_pwd_add_tenant: "{{ op8_inventory_pwd_add_tenant.httpapi_logs | flatten }}" - name: Verify switching of hosts with the password in the inventory - assert: + ansible.builtin.assert: that: - op8_inventory_pwd_delete_tenant is changed - op8_flattened_inventory_pwd_delete_tenant | regex_search('Switching host from [0-9]+(?:\.[0-9]+){3} to {{ aci_hostname }}') is not none @@ -417,7 +417,7 @@ op9_flattened_inventory_pwd_add_tenant: "{{ op9_inventory_pwd_add_tenant.httpapi_logs | flatten }}" - name: Verify switching of hosts with the password in the inventory - assert: + ansible.builtin.assert: that: - op9_inventory_pwd_delete_tenant is changed - op9_flattened_inventory_pwd_delete_tenant | regex_search('Switching host from [0-9]+(?:\.[0-9]+){3} to {{ aci_hostname }}') is not none @@ -440,7 +440,7 @@ ignore_errors: True - name: Verify failure when no hosts are active in the inventory - assert: + ansible.builtin.assert: that: - op10_inventory_pwd_delete_tenant.error.text | regex_search('No hosts left in the cluster to continue operation! Error on final host [0-9]+(?:\.[0-9]+){3}') is not none @@ -469,7 +469,7 @@ op11_flattened_task_private_key_add_tenant: "{{ op11_task_private_key_add_tenant.httpapi_logs | flatten }}" - name: Verify switching of hosts with the private key in the task - assert: + ansible.builtin.assert: that: - op11_task_private_key_delete_tenant is changed - op11_flattened_task_private_key_delete_tenant | regex_search('Switching host from [0-9]+(?:\.[0-9]+){3} to {{ aci_hostname }}') is not none @@ -503,7 +503,7 @@ op12_flattened_task_private_key_add_tenant: "{{ op12_task_private_key_add_tenant.httpapi_logs | flatten }}" - name: Verify continuation of the operations on the connected host with the password in the task - assert: + ansible.builtin.assert: that: - op12_task_private_key_delete_tenant is changed - '"Connected host {{ aci_hostname }} found in the provided hosts. Continuing with it." in op12_flattened_task_private_key_delete_tenant' @@ -531,7 +531,7 @@ register: op13_task_private_key_add_tenant - name: Verify failure when no hosts are active in the task - assert: + ansible.builtin.assert: that: - op13_task_private_key_delete_tenant.error.text | regex_search('No hosts left in the cluster to continue operation! Error on final host [0-9]+(?:\.[0-9]+){3}') is not none - op13_task_private_key_add_tenant is not changed @@ -562,7 +562,7 @@ op14_flattened_inventory_session_key_add_tenant: "{{ op14_inventory_session_key_add_tenant.httpapi_logs | flatten }}" - name: Verify switching of hosts with the session key in the inventory - assert: + ansible.builtin.assert: that: - op14_inventory_session_key_delete_tenant is changed - op14_flattened_inventory_session_key_delete_tenant | regex_search('Switching host from [0-9]+(?:\.[0-9]+){3} to {{ aci_hostname }}') is not none @@ -596,7 +596,7 @@ op15_flattened_inventory_session_key_add_tenant: "{{ op15_inventory_session_key_add_tenant.httpapi_logs | flatten }}" - name: Verify switching of hosts with the session key in the inventory - assert: + ansible.builtin.assert: that: - op15_inventory_session_key_delete_tenant is changed - op15_flattened_inventory_session_key_delete_tenant | regex_search('Switching host from [0-9]+(?:\.[0-9]+){3} to {{ aci_hostname }}') is not none @@ -619,7 +619,7 @@ ignore_errors: True - name: Verify failure when no hosts are active in the inventory - assert: + ansible.builtin.assert: that: - op16_inventory_session_key_delete_tenant.error.text | regex_search('No hosts left in the cluster to continue operation! Error on final host [0-9]+(?:\.[0-9]+){3}') is not none diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_tenant/tasks/main.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_tenant/tasks/main.yml index b8a7a310f..4208676ca 100644 --- a/ansible_collections/cisco/aci/tests/integration/targets/aci_tenant/tasks/main.yml +++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_tenant/tasks/main.yml @@ -1,11 +1,12 @@ # Test code for the ACI modules # Copyright: (c) 2017, Dag Wieers (@dagwieers) # Copyright: (c) 2020, Lionel Hercot (@lhercot) +# Copyright: (c) 2024, Samita Bhattacharjee (@samiib) # GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) - name: Test that we have an ACI APIC host, ACI username and ACI password - fail: + ansible.builtin.fail: msg: 'Please define the following variables: aci_hostname, aci_username and aci_password.' when: aci_hostname is not defined or aci_username is not defined or aci_password is not defined @@ -13,7 +14,7 @@ tags: httpapi_connection - name: Delete old log files to clean test directory - file: + ansible.builtin.file: path: "{{ item }}" state: absent with_items: @@ -63,7 +64,7 @@ register: cm_add_tenant - name: Dump content of files - debug: + ansible.builtin.debug: msg: "{{ lookup('file', aci_hostname +'_cm_add_tenant.json')}}" - name: Add tenant (normal mode) @@ -86,19 +87,19 @@ register: nm_add_tenant_again - name: Dump content of files - debug: + ansible.builtin.debug: msg: "{{ lookup('file', aci_hostname + '_cm_add_tenant.json')}}" - name: Store file content on variables for create object - set_fact: + ansible.builtin.set_fact: fc_cm_add_tenant: "{{ lookup('file', aci_hostname + '_cm_add_tenant.json') | from_json }}" fc_nm_add_tenant: "{{ lookup('file', aci_hostname + '_nm_add_tenant.json') | from_json }}" fc_cm_add_tenant_again: "{{ lookup('file', aci_hostname + '_cm_add_tenant_again.json') }}" fc_nm_add_tenant_again: "{{ lookup('file', aci_hostname + '_nm_add_tenant_again.json') }}" - name: Log file content verification for create object - assert: + ansible.builtin.assert: that: - fc_cm_add_tenant.0.fvTenant.attributes.name == 'ansible_test' - fc_cm_add_tenant.0.fvTenant.attributes.dn == 'uni/tn-ansible_test' @@ -108,7 +109,7 @@ - fc_nm_add_tenant_again == '' - name: Verify add_tenant - assert: + ansible.builtin.assert: that: - cm_add_tenant is changed - nm_add_tenant is changed @@ -165,14 +166,14 @@ register: nm_add_tenant_descr_again - name: Store file content on variables for update object - set_fact: + ansible.builtin.set_fact: fc_cm_add_tenant_descr: "{{ lookup('file', aci_hostname + '_cm_add_tenant_descr.json') | from_json }}" fc_nm_add_tenant_descr: "{{ lookup('file', aci_hostname + '_nm_add_tenant_descr.json') | from_json }}" fc_cm_add_tenant_descr_again: "{{ lookup('file', aci_hostname + '_cm_add_tenant_descr_again.json') }}" fc_nm_add_tenant_descr_again: "{{ lookup('file', aci_hostname + '_nm_add_tenant_descr_again.json') }}" - name: Log file content verification for update object - assert: + ansible.builtin.assert: that: - fc_cm_add_tenant_descr.0.fvTenant.attributes.descr == 'Ansible test tenant' - fc_nm_add_tenant_descr.0.fvTenant.attributes.descr == 'Ansible test tenant' @@ -180,7 +181,7 @@ - fc_nm_add_tenant_descr_again == '' - name: Verify add_tenant_descr - assert: + ansible.builtin.assert: that: - cm_add_tenant_descr is changed - nm_add_tenant_descr is changed @@ -219,11 +220,80 @@ register: nm_add_tenant_again_no_descr - name: Verify add_tenant_again_no_descr - assert: + ansible.builtin.assert: that: - cm_add_tenant_again_no_descr is not changed - nm_add_tenant_again_no_descr is not changed +# TEST NO VERIFICATION +- name: Create tenant with no verification (check mode) + cisco.aci.aci_tenant: &aci_tenant_no_verify + <<: *tenant_present + tenant: anstest-no-verify + description: Ansible Test + no_verification: true + check_mode: true + register: tenant_present_no_verify_cm + +- name: Create tenant with no verification + cisco.aci.aci_tenant: + <<: *aci_tenant_no_verify + register: tenant_present_no_verify + +- name: Create tenant with no verification again + cisco.aci.aci_tenant: + <<: *aci_tenant_no_verify + register: tenant_present_no_verify_again + +- name: Update tenant with no verification + cisco.aci.aci_tenant: + <<: *aci_tenant_no_verify + description: Ansible Test No Verify + register: update_tenant_present_no_verify + +- name: Delete tenant with no verification + cisco.aci.aci_tenant: + <<: *aci_tenant_no_verify + state: absent + register: delete_tenant_present_no_verify + +- name: Delete tenant with no verification again + cisco.aci.aci_tenant: + <<: *aci_tenant_no_verify + state: absent + register: delete_tenant_present_no_verify_again + +- name: No verification asserts + ansible.builtin.assert: + that: + - tenant_present_no_verify_cm is changed + - tenant_present_no_verify_cm.current_verified == false + - tenant_present_no_verify_cm.current.0 == tenant_present_no_verify_cm.proposed + - tenant_present_no_verify is changed + - tenant_present_no_verify.current_verified == false + - tenant_present_no_verify.current.0 == tenant_present_no_verify.proposed + - tenant_present_no_verify.previous == [] + - tenant_present_no_verify_again is not changed + - tenant_present_no_verify_again.current_verified == true + - tenant_present_no_verify_again.current.0.fvTenant.attributes.name == "anstest-no-verify" + - tenant_present_no_verify_again.current.0.fvTenant.attributes.descr == "Ansible Test" + - tenant_present_no_verify_again.previous.0.fvTenant.attributes.name == "anstest-no-verify" + - tenant_present_no_verify_again.previous.0.fvTenant.attributes.descr == "Ansible Test" + - update_tenant_present_no_verify is changed + - update_tenant_present_no_verify.current_verified == false + - update_tenant_present_no_verify.current.0 == update_tenant_present_no_verify.proposed + - update_tenant_present_no_verify.previous.0.fvTenant.attributes.name == "anstest-no-verify" + - update_tenant_present_no_verify.previous.0.fvTenant.attributes.descr == "Ansible Test" + - delete_tenant_present_no_verify is changed + - delete_tenant_present_no_verify.current_verified == false + - delete_tenant_present_no_verify.current.0 == delete_tenant_present_no_verify.proposed + - delete_tenant_present_no_verify.previous.0.fvTenant.attributes.name == "anstest-no-verify" + - delete_tenant_present_no_verify.previous.0.fvTenant.attributes.descr == "Ansible Test No Verify" + - delete_tenant_present_no_verify_again is not changed + - delete_tenant_present_no_verify_again.current_verified == true + - delete_tenant_present_no_verify_again.current == [] + - delete_tenant_present_no_verify_again.previous == [] + - delete_tenant_present_no_verify_again.proposed == {} # QUERY ALL TENANTS - name: Query all tenants (check_mode) @@ -244,7 +314,7 @@ register: nm_query_all_tenants - name: Verify query_all_tenants - assert: + ansible.builtin.assert: that: - cm_query_all_tenants is not changed - nm_query_all_tenants is not changed @@ -267,7 +337,7 @@ register: nm_query_tenant - name: Verify query_tenant - assert: + ansible.builtin.assert: that: - cm_query_tenant is not changed - nm_query_tenant is not changed @@ -287,7 +357,7 @@ register: default_annotation - name: Assertion check for update tenant with default annotation - assert: + ansible.builtin.assert: that: - default_annotation is changed - default_annotation.current.0.fvTenant.attributes.annotation == 'orchestrator:ansible' @@ -320,14 +390,14 @@ register: nm_remove_tenant_again - name: Store file content on variables for delete object - set_fact: + ansible.builtin.set_fact: fc_cm_remove_tenant: "{{ lookup('file', aci_hostname + '_cm_remove_tenant.json') | from_json }}" fc_nm_remove_tenant: "{{ lookup('file', aci_hostname + '_nm_remove_tenant.json') | from_json }}" fc_cm_remove_tenant_again: "{{ lookup('file', aci_hostname + '_cm_remove_tenant_again.json') }}" fc_nm_remove_tenant_again: "{{ lookup('file', aci_hostname + '_nm_remove_tenant_again.json') }}" - name: Log file content verification for delete object - assert: + ansible.builtin.assert: that: - fc_cm_remove_tenant.0.fvTenant.attributes.status == 'deleted' - fc_cm_remove_tenant.0.fvTenant.attributes.dn == 'uni/tn-ansible_test' @@ -336,7 +406,7 @@ - fc_nm_remove_tenant_again == '' - name: Verify remove_tenant - assert: + ansible.builtin.assert: that: - cm_remove_tenant is changed - nm_remove_tenant is changed @@ -360,7 +430,7 @@ # TODO: Implement more tests - name: Verify query_non_tenant - assert: + ansible.builtin.assert: that: - cm_query_non_tenant is not changed - nm_query_non_tenant is not changed diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_tenant_action_rule_profile/tasks/main.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_tenant_action_rule_profile/tasks/main.yml index b993b0e33..7531863e0 100644 --- a/ansible_collections/cisco/aci/tests/integration/targets/aci_tenant_action_rule_profile/tasks/main.yml +++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_tenant_action_rule_profile/tasks/main.yml @@ -1,15 +1,17 @@ # Test code for the ACI modules +# Copyright: (c) 2023, Dag Wieers (@dagwieers) +# Copyright: (c) 2023, Tim Cragg (@timcragg) # Copyright: (c) 2023, Gaspard Micol (@gmicol) # GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) - name: Test that we have an ACI APIC host, ACI username and ACI password - fail: + ansible.builtin.fail: msg: 'Please define the following variables: aci_hostname, aci_username and aci_password.' when: aci_hostname is not defined or aci_username is not defined or aci_password is not defined - name: Set vars - set_fact: + ansible.builtin.set_fact: aci_info: &aci_info host: "{{ aci_hostname }}" username: "{{ aci_username }}" @@ -19,115 +21,266 @@ use_proxy: '{{ aci_use_proxy | default(true) }}' output_level: debug +# CLEAN ENVIRONMENT +- name: Remove the ansible_tenant + cisco.aci.aci_tenant: &aci_tenant_absent + <<: *aci_info + tenant: ansible_tenant + state: absent + - name: Verify Cloud and Non-Cloud Sites in use. - include_tasks: ../../../../../../integration/targets/aci_cloud_provider/tasks/main.yml + ansible.builtin.include_tasks: ../../../../../../integration/targets/aci_cloud_provider/tasks/main.yml - name: Execute tasks only for non-cloud sites when: query_cloud.current == [] # This condition will execute only non-cloud sites block: # block specifies execution of tasks within, based on conditions - # Clean Environment - name: create tenant - aci_tenant: &aci_tenant_present + cisco.aci.aci_tenant: &aci_tenant_present <<: *aci_info tenant: ansible_test state: present - name: Ensure first action rule profile does not exist - aci_tenant_action_rule_profile: &aci_tenant_action_rule_profile_absent + cisco.aci.aci_tenant_action_rule_profile: &aci_tenant_action_rule_profile_absent <<: *aci_tenant_present name: anstest description: test for action rule profile + set_preference: 100 + set_route_tag: 100 + set_weight: 100 + set_metric: 100 + set_metric_type: ospf_type_1 + set_next_hop: 1.1.1.1 + set_community: + community: no-advertise + criteria: replace + set_dampening: + half_life: 10 + reuse: 1 + suppress: 10 + max_suppress_time: 100 state: absent - - name: Ensure second action rule profile does not exist - aci_tenant_action_rule_profile: &aci_tenant_action_rule_profile_2_absent + - name: Ensure second action rule profile does not exist - APIC version >= 5.0 + when: version.current.0.topSystem.attributes.version is version('5', '>=') + cisco.aci.aci_tenant_action_rule_profile: &aci_tenant_action_rule_profile_2_5_absent + <<: *aci_tenant_present + name: anstest_2 + set_next_hop: 1.1.1.2 + next_hop_propagation: true + multipath: true + state: absent + + - name: Ensure second action rule profile does not exist - APIC version < 5.0 + when: version.current.0.topSystem.attributes.version is version('5', '<') + cisco.aci.aci_tenant_action_rule_profile: &aci_tenant_action_rule_profile_2_absent <<: *aci_tenant_present name: anstest_2 + set_next_hop: 1.1.1.2 state: absent - name: Create first action rule profile (check_mode) - aci_tenant_action_rule_profile: &aci_tenant_action_rule_profile_present + cisco.aci.aci_tenant_action_rule_profile: &aci_tenant_action_rule_profile_present <<: *aci_tenant_action_rule_profile_absent state: present check_mode: true register: cm_add_tenant_action_rule_profile_1 - name: Create first action rule profile (normal_mode) - aci_tenant_action_rule_profile: + cisco.aci.aci_tenant_action_rule_profile: <<: *aci_tenant_action_rule_profile_present register: nm_add_tenant_action_rule_profile_1 - name: Create first action rule profile again - testing idempotency - aci_tenant_action_rule_profile: + cisco.aci.aci_tenant_action_rule_profile: <<: *aci_tenant_action_rule_profile_present register: idempotency_add_tenant_action_rule_profile_1 - - name: Create second action rule profile - aci_tenant_action_rule_profile: &aci_tenant_action_rule_profile_2_present + - name: Create second action rule profile - APIC version >= 5.0 + when: version.current.0.topSystem.attributes.version is version('5', '>=') + cisco.aci.aci_tenant_action_rule_profile: &aci_tenant_action_rule_profile_2_5_present + <<: *aci_tenant_action_rule_profile_2_5_absent + state: present + register: nm_add_tenant_action_rule_profile_2_5 + + - name: Create second action rule profile - APIC version < 5.0 + when: version.current.0.topSystem.attributes.version is version('5', '<') + cisco.aci.aci_tenant_action_rule_profile: &aci_tenant_action_rule_profile_2_present <<: *aci_tenant_action_rule_profile_2_absent state: present register: nm_add_tenant_action_rule_profile_2 - - name: Asserts for creation tasks - assert: + - name: Asserts for creation tasks for action rule profile 1 + ansible.builtin.assert: that: - cm_add_tenant_action_rule_profile_1 is changed - cm_add_tenant_action_rule_profile_1.previous == [] - cm_add_tenant_action_rule_profile_1.current == [] - nm_add_tenant_action_rule_profile_1 is changed - nm_add_tenant_action_rule_profile_1.current.0.rtctrlAttrP.attributes.name == "anstest" + - nm_add_tenant_action_rule_profile_1.current.0.rtctrlAttrP.children.0.rtctrlSetWeight.attributes.weight == "100" + - nm_add_tenant_action_rule_profile_1.current.0.rtctrlAttrP.children.1.rtctrlSetDamp.attributes.halfLife == "10" + - nm_add_tenant_action_rule_profile_1.current.0.rtctrlAttrP.children.1.rtctrlSetDamp.attributes.maxSuppressTime == "100" + - nm_add_tenant_action_rule_profile_1.current.0.rtctrlAttrP.children.1.rtctrlSetDamp.attributes.reuse == "1" + - nm_add_tenant_action_rule_profile_1.current.0.rtctrlAttrP.children.1.rtctrlSetDamp.attributes.suppress == "10" + - nm_add_tenant_action_rule_profile_1.current.0.rtctrlAttrP.children.2.rtctrlSetRtMetricType.attributes.metricType == "ospf-type1" + - nm_add_tenant_action_rule_profile_1.current.0.rtctrlAttrP.children.3.rtctrlSetNh.attributes.addr == "1.1.1.1" + - nm_add_tenant_action_rule_profile_1.current.0.rtctrlAttrP.children.4.rtctrlSetPref.attributes.localPref == "100" + - nm_add_tenant_action_rule_profile_1.current.0.rtctrlAttrP.children.5.rtctrlSetRtMetric.attributes.metric == "100" + - nm_add_tenant_action_rule_profile_1.current.0.rtctrlAttrP.children.6.rtctrlSetComm.attributes.community == "no-advertise" + - nm_add_tenant_action_rule_profile_1.current.0.rtctrlAttrP.children.6.rtctrlSetComm.attributes.setCriteria == "replace" + - nm_add_tenant_action_rule_profile_1.current.0.rtctrlAttrP.children.7.rtctrlSetTag.attributes.tag == "100" - idempotency_add_tenant_action_rule_profile_1 is not changed + + - name: Asserts for creation tasks for action rule profile 2 - APIC version >= 5.0 + when: version.current.0.topSystem.attributes.version is version('5', '>=') + ansible.builtin.assert: + that: + - nm_add_tenant_action_rule_profile_2_5 is changed + - nm_add_tenant_action_rule_profile_2_5.current.0.rtctrlAttrP.attributes.name == "anstest_2" + - nm_add_tenant_action_rule_profile_2_5.current.0.rtctrlAttrP.children.0.rtctrlSetRedistMultipath.attributes.descr == "" + - nm_add_tenant_action_rule_profile_2_5.current.0.rtctrlAttrP.children.1.rtctrlSetNhUnchanged.attributes.descr == "" + - nm_add_tenant_action_rule_profile_2_5.current.0.rtctrlAttrP.children.2.rtctrlSetNh.attributes.addr == "1.1.1.2" + + - name: Asserts for creation tasks for action rule profile 2 - APIC version < 5.0 + when: version.current.0.topSystem.attributes.version is version('5', '<') + ansible.builtin.assert: + that: - nm_add_tenant_action_rule_profile_2 is changed - nm_add_tenant_action_rule_profile_2.current.0.rtctrlAttrP.attributes.name == "anstest_2" + - nm_add_tenant_action_rule_profile_2.current.0.rtctrlAttrP.children.0.rtctrlSetNh.attributes.addr == "1.1.1.2" - name: Query all action rule profiles - aci_tenant_action_rule_profile: + cisco.aci.aci_tenant_action_rule_profile: <<: *aci_info state: query register: query_all_tenant_action_rule_profile - name: Query first action rule profile - aci_tenant_action_rule_profile: + cisco.aci.aci_tenant_action_rule_profile: <<: *aci_tenant_action_rule_profile_present state: query register: query_first_tenant_action_rule_profile - name: Asserts for query tasks - assert: + ansible.builtin.assert: that: - query_all_tenant_action_rule_profile is not changed - query_all_tenant_action_rule_profile.current | length >= 2 - '"class/rtctrlAttrP.json" in query_all_tenant_action_rule_profile.url' - query_first_tenant_action_rule_profile is not changed - query_first_tenant_action_rule_profile.current.0.rtctrlAttrP.attributes.name == "anstest" + - query_first_tenant_action_rule_profile.current.0.rtctrlAttrP.children.0.rtctrlSetWeight.attributes.weight == "100" + - query_first_tenant_action_rule_profile.current.0.rtctrlAttrP.children.1.rtctrlSetDamp.attributes.halfLife == "10" + - query_first_tenant_action_rule_profile.current.0.rtctrlAttrP.children.1.rtctrlSetDamp.attributes.maxSuppressTime == "100" + - query_first_tenant_action_rule_profile.current.0.rtctrlAttrP.children.1.rtctrlSetDamp.attributes.reuse == "1" + - query_first_tenant_action_rule_profile.current.0.rtctrlAttrP.children.1.rtctrlSetDamp.attributes.suppress == "10" + - query_first_tenant_action_rule_profile.current.0.rtctrlAttrP.children.2.rtctrlSetRtMetricType.attributes.metricType == "ospf-type1" + - query_first_tenant_action_rule_profile.current.0.rtctrlAttrP.children.3.rtctrlSetNh.attributes.addr == "1.1.1.1" + - query_first_tenant_action_rule_profile.current.0.rtctrlAttrP.children.4.rtctrlSetPref.attributes.localPref == "100" + - query_first_tenant_action_rule_profile.current.0.rtctrlAttrP.children.5.rtctrlSetRtMetric.attributes.metric == "100" + - query_first_tenant_action_rule_profile.current.0.rtctrlAttrP.children.6.rtctrlSetComm.attributes.community == "no-advertise" + - query_first_tenant_action_rule_profile.current.0.rtctrlAttrP.children.6.rtctrlSetComm.attributes.setCriteria == "replace" + - query_first_tenant_action_rule_profile.current.0.rtctrlAttrP.children.7.rtctrlSetTag.attributes.tag == "100" + + - name: Delete children for first action rule profile (check_mode) + cisco.aci.aci_tenant_action_rule_profile: &aci_tenant_action_rule_profile_children_deleted + <<: *aci_tenant_action_rule_profile_present + set_preference: "" + set_route_tag: "" + set_weight: "" + set_metric: "" + set_metric_type: "" + set_next_hop: "" + set_community: {} + set_dampening: {} + check_mode: true + register: cm_delete_children_tenant_action_rule_profile_1 + + - name: Delete children for first action rule profile (normal_mode) + cisco.aci.aci_tenant_action_rule_profile: + <<: *aci_tenant_action_rule_profile_children_deleted + register: nm_delete_children_tenant_action_rule_profile_1 + + - name: Delete children for first action rule profile again - testing idempotency + cisco.aci.aci_tenant_action_rule_profile: + <<: *aci_tenant_action_rule_profile_children_deleted + register: idempotency_delete_children_tenant_action_rule_profile_1 + + - name: Delete children for second action rule profile - APIC version >= 5.0 + when: version.current.0.topSystem.attributes.version is version('5', '>=') + cisco.aci.aci_tenant_action_rule_profile: + <<: *aci_tenant_action_rule_profile_2_5_present + set_next_hop: "" + next_hop_propagation: false + multipath: false + register: nm_delete_children_tenant_action_rule_profile_2_5 + + - name: Delete children for second action rule profile - APIC version < 5.0 + when: version.current.0.topSystem.attributes.version is version('5', '<') + cisco.aci.aci_tenant_action_rule_profile: + <<: *aci_tenant_action_rule_profile_2_present + set_next_hop: "" + register: nm_delete_children_tenant_action_rule_profile_2 + + - name: Asserts for deletion tasks for action rule profile 1 + ansible.builtin.assert: + that: + - cm_delete_children_tenant_action_rule_profile_1 is changed + - cm_delete_children_tenant_action_rule_profile_1.current == cm_delete_children_tenant_action_rule_profile_1.previous + - nm_delete_children_tenant_action_rule_profile_1 is changed + - nm_delete_children_tenant_action_rule_profile_1.current.0.rtctrlAttrP | length == 1 + - idempotency_delete_children_tenant_action_rule_profile_1 is not changed + + - name: Asserts for deletion tasks for action rule profile 2 - APIC version >= 5.0 + when: version.current.0.topSystem.attributes.version is version('5', '>=') + ansible.builtin.assert: + that: + - nm_delete_children_tenant_action_rule_profile_2_5 is changed + - nm_delete_children_tenant_action_rule_profile_2_5.current.0.rtctrlAttrP | length == 1 + + - name: Asserts for deletion tasks for action rule profile 2 - APIC version < 5.0 + when: version.current.0.topSystem.attributes.version is version('5', '<') + ansible.builtin.assert: + that: + - nm_delete_children_tenant_action_rule_profile_2 is changed + - nm_delete_children_tenant_action_rule_profile_2.current.0.rtctrlAttrP | length == 1 - name: Delete first action rule profile (check_mode) - aci_tenant_action_rule_profile: + cisco.aci.aci_tenant_action_rule_profile: <<: *aci_tenant_action_rule_profile_present state: absent check_mode: true register: cm_delete_tenant_action_rule_profile_1 - name: Delete first action rule profile (normal_mode) - aci_tenant_action_rule_profile: + cisco.aci.aci_tenant_action_rule_profile: <<: *aci_tenant_action_rule_profile_present state: absent register: nm_delete_tenant_action_rule_profile_1 - name: Delete first action rule profile again - testing idempotency - aci_tenant_action_rule_profile: + cisco.aci.aci_tenant_action_rule_profile: <<: *aci_tenant_action_rule_profile_present state: absent register: idempotency_delete_tenant_action_rule_profile_1 - - name: Delete second action rule profile (normal_mode) - aci_tenant_action_rule_profile: + - name: Delete second action rule profile - APIC version >= 5.0 + when: version.current.0.topSystem.attributes.version is version('5', '>=') + cisco.aci.aci_tenant_action_rule_profile: + <<: *aci_tenant_action_rule_profile_2_5_present + state: absent + register: nm_delete_tenant_action_rule_profile_2_5 + + - name: Delete second action rule profile - APIC version < 5.0 + when: version.current.0.topSystem.attributes.version is version('5', '<') + cisco.aci.aci_tenant_action_rule_profile: <<: *aci_tenant_action_rule_profile_2_present state: absent register: nm_delete_tenant_action_rule_profile_2 - - name: Asserts for deletion tasks - assert: + - name: Asserts for deletion tasks for action rule profile 1 + ansible.builtin.assert: that: - cm_delete_tenant_action_rule_profile_1 is changed - cm_delete_tenant_action_rule_profile_1.proposed == {} @@ -136,11 +289,24 @@ - nm_delete_tenant_action_rule_profile_1.current == [] - idempotency_delete_tenant_action_rule_profile_1 is not changed - idempotency_delete_tenant_action_rule_profile_1.previous == [] + + - name: Asserts for deletion tasks for action rule profile 2 - APIC version >= 5.0 + when: version.current.0.topSystem.attributes.version is version('5', '>=') + ansible.builtin.assert: + that: + - nm_delete_tenant_action_rule_profile_2_5 is changed + - nm_delete_tenant_action_rule_profile_2_5.previous != [] + - nm_delete_tenant_action_rule_profile_2_5.current == [] + + - name: Asserts for deletion tasks for action rule profile 2 - APIC version < 5.0 + when: version.current.0.topSystem.attributes.version is version('5', '<') + ansible.builtin.assert: + that: - nm_delete_tenant_action_rule_profile_2 is changed - nm_delete_tenant_action_rule_profile_2.previous != [] - nm_delete_tenant_action_rule_profile_2.current == [] - - name: Delete tenant - clean up the environment - aci_tenant: + - name: Delete tenant - cleanup before ending tests + cisco.aci.aci_tenant: <<: *aci_tenant_present state: absent \ No newline at end of file diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_tenant_ep_retention_policy/tasks/main.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_tenant_ep_retention_policy/tasks/main.yml index 96ba34077..29b45938f 100644 --- a/ansible_collections/cisco/aci/tests/integration/targets/aci_tenant_ep_retention_policy/tasks/main.yml +++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_tenant_ep_retention_policy/tasks/main.yml @@ -4,12 +4,12 @@ # GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) - name: Test that we have an ACI APIC host, ACI username and ACI password - fail: + ansible.builtin.fail: msg: 'Please define the following variables: aci_hostname, aci_username and aci_password.' when: aci_hostname is not defined or aci_username is not defined or aci_password is not defined - name: Set vars - set_fact: + ansible.builtin.set_fact: aci_info: &aci_info host: "{{ aci_hostname }}" username: "{{ aci_username }}" @@ -20,20 +20,20 @@ output_level: debug - name: Verify Cloud and Non-Cloud Sites in use. - include_tasks: ../../../../../../integration/targets/aci_cloud_provider/tasks/main.yml + ansible.builtin.include_tasks: ../../../../../../integration/targets/aci_cloud_provider/tasks/main.yml - name: Execute tasks only for non-cloud sites when: query_cloud.current == [] # This condition will execute only non-cloud sites block: # block specifies execution of tasks within, based on conditions # Clean Environment - name: create tenant - aci_tenant: &aci_tenant_present + cisco.aci.aci_tenant: &aci_tenant_present <<: *aci_info tenant: ansible_test state: present - name: Ensure first EP retention protocol policy does not exist - aci_tenant_ep_retention_policy: &aci_tenant_ep_retention_policy_absent + cisco.aci.aci_tenant_ep_retention_policy: &aci_tenant_ep_retention_policy_absent <<: *aci_tenant_present name: ep_policy_anstest description: test for EP retention protocol policy @@ -46,7 +46,7 @@ state: absent - name: Ensure second EP retention protocol policy does not exist - aci_tenant_ep_retention_policy: &aci_tenant_ep_retention_policy_2_absent + cisco.aci.aci_tenant_ep_retention_policy: &aci_tenant_ep_retention_policy_2_absent <<: *aci_tenant_present name: ep_policy_anstest_2 bounce_age: 0 @@ -56,65 +56,65 @@ state: absent - name: Create first EP retention protocol policy (check_mode) - aci_tenant_ep_retention_policy: &aci_tenant_ep_retention_policy_present + cisco.aci.aci_tenant_ep_retention_policy: &aci_tenant_ep_retention_policy_present <<: *aci_tenant_ep_retention_policy_absent state: present check_mode: true register: cm_add_tenant_ep_retention_policy_1 - name: Create first EP retention protocol policy (normal_mode) - aci_tenant_ep_retention_policy: + cisco.aci.aci_tenant_ep_retention_policy: <<: *aci_tenant_ep_retention_policy_present register: nm_add_tenant_ep_retention_policy_1 - name: Create first EP retention protocol policy again - testing idempotency - aci_tenant_ep_retention_policy: + cisco.aci.aci_tenant_ep_retention_policy: <<: *aci_tenant_ep_retention_policy_present register: idempotency_add_tenant_ep_retention_policy_1 - name: Create second EP retention protocol policy - aci_tenant_ep_retention_policy: &aci_tenant_ep_retention_policy_2_present + cisco.aci.aci_tenant_ep_retention_policy: &aci_tenant_ep_retention_policy_2_present <<: *aci_tenant_ep_retention_policy_2_absent state: present register: nm_add_tenant_ep_retention_policy_2 - name: Modify EP retention protocol policy bounce age - testing failure message - aci_tenant_ep_retention_policy: + cisco.aci.aci_tenant_ep_retention_policy: <<: *aci_tenant_ep_retention_policy_present bounce_age: 100 ignore_errors: true register: Modify_tenant_ep_retention_policy_bounce_age - name: Modify EP retention protocol policy hold interval - testing failure message - aci_tenant_ep_retention_policy: + cisco.aci.aci_tenant_ep_retention_policy: <<: *aci_tenant_ep_retention_policy_present hold_interval: 4 ignore_errors: true register: Modify_tenant_ep_retention_policy_hold_interval - name: Modify EP retention protocol policy move frequency - testing failure message - aci_tenant_ep_retention_policy: + cisco.aci.aci_tenant_ep_retention_policy: <<: *aci_tenant_ep_retention_policy_present move_frequency: 65540 ignore_errors: true register: Modify_tenant_ep_retention_policy_move_frequency - name: Modify EP retention protocol policy local ep interval - testing failure message - aci_tenant_ep_retention_policy: + cisco.aci.aci_tenant_ep_retention_policy: <<: *aci_tenant_ep_retention_policy_present local_ep_interval: 119 ignore_errors: true register: Modify_tenant_ep_retention_policy_local_ep_interval - name: Modify EP retention protocol policy remote ep interval - testing failure message - aci_tenant_ep_retention_policy: + cisco.aci.aci_tenant_ep_retention_policy: <<: *aci_tenant_ep_retention_policy_present remote_ep_interval: 119 ignore_errors: true register: Modify_tenant_ep_retention_policy_remote_ep_interval - name: Asserts for creation tasks - assert: + ansible.builtin.assert: that: - cm_add_tenant_ep_retention_policy_1 is changed - cm_add_tenant_ep_retention_policy_1.previous == [] @@ -143,19 +143,19 @@ - Modify_tenant_ep_retention_policy_remote_ep_interval.msg == "The remote_ep_interval must be a value of 0 or between 120 and 65535" - name: Query all EP retention protocol policies - aci_tenant_ep_retention_policy: + cisco.aci.aci_tenant_ep_retention_policy: <<: *aci_info state: query register: query_all_tenant_ep_retention_policy - name: Query first EP retention protocol policy - aci_tenant_ep_retention_policy: + cisco.aci.aci_tenant_ep_retention_policy: <<: *aci_tenant_ep_retention_policy_present state: query register: query_first_tenant_ep_retention_policy - name: Asserts for query tasks - assert: + ansible.builtin.assert: that: - query_all_tenant_ep_retention_policy is not changed - query_all_tenant_ep_retention_policy.current | length >= 2 @@ -170,32 +170,32 @@ - query_first_tenant_ep_retention_policy.current.0.fvEpRetPol.attributes.remoteEpAgeIntvl == "600" - name: Delete first EP retention protocol policy (check_mode) - aci_tenant_ep_retention_policy: + cisco.aci.aci_tenant_ep_retention_policy: <<: *aci_tenant_ep_retention_policy_present state: absent check_mode: true register: cm_delete_tenant_ep_retention_policy_1 - name: Delete first EP retention protocol policy (normal_mode) - aci_tenant_ep_retention_policy: + cisco.aci.aci_tenant_ep_retention_policy: <<: *aci_tenant_ep_retention_policy_present state: absent register: nm_delete_tenant_ep_retention_policy_1 - name: Delete first EP retention protocol policy again - testing idempotency - aci_tenant_ep_retention_policy: + cisco.aci.aci_tenant_ep_retention_policy: <<: *aci_tenant_ep_retention_policy_present state: absent register: idempotency_delete_tenant_ep_retention_policy_1 - name: Delete second EP retention protocol policy (normal_mode) - aci_tenant_ep_retention_policy: + cisco.aci.aci_tenant_ep_retention_policy: <<: *aci_tenant_ep_retention_policy_2_present state: absent register: nm_delete_tenant_ep_retention_policy_2 - name: Asserts for deletion tasks - assert: + ansible.builtin.assert: that: - cm_delete_tenant_ep_retention_policy_1 is changed - cm_delete_tenant_ep_retention_policy_1.proposed == {} @@ -209,6 +209,6 @@ - nm_delete_tenant_ep_retention_policy_2.current == [] - name: Delete tenant - clean up the environment - aci_tenant: + cisco.aci.aci_tenant: <<: *aci_tenant_present state: absent \ No newline at end of file diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_tenant_span_dst_group/tasks/main.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_tenant_span_dst_group/tasks/main.yml index 543a25cd5..6b27dcb27 100644 --- a/ansible_collections/cisco/aci/tests/integration/targets/aci_tenant_span_dst_group/tasks/main.yml +++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_tenant_span_dst_group/tasks/main.yml @@ -4,12 +4,12 @@ # GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) - name: Test that we have an ACI APIC host, ACI username and ACI password - fail: + ansible.builtin.fail: msg: 'Please define the following variables: aci_hostname, aci_username and aci_password.' when: aci_hostname is not defined or aci_username is not defined or aci_password is not defined - name: Set vars - set_fact: + ansible.builtin.set_fact: aci_info: &aci_info host: "{{ aci_hostname }}" username: "{{ aci_username }}" @@ -21,27 +21,27 @@ # CLEAN ENVIRONMENT - name: Remove the ansible_tenant - aci_tenant: + cisco.aci.aci_tenant: <<: *aci_info tenant: ansible_tenant state: absent - name: Verify Cloud and Non-Cloud Sites in use. - include_tasks: ../../../../../../integration/targets/aci_cloud_provider/tasks/main.yml + ansible.builtin.include_tasks: ../../../../../../integration/targets/aci_cloud_provider/tasks/main.yml - name: Execute tasks only for non-cloud sites when: query_cloud.current == [] # This condition will execute only non-cloud sites block: # block specifies execution of tasks within, based on conditions - name: Add a new tenant - aci_tenant: + cisco.aci.aci_tenant: <<: *aci_info tenant: ansible_tenant description: Ansible tenant state: present - name: Add span ansible_group - aci_tenant_span_dst_group: + cisco.aci.aci_tenant_span_dst_group: <<: *aci_info destination_group: ansible_group description: Test span @@ -62,7 +62,7 @@ register: add_span1 - name: Verify add span - assert: + ansible.builtin.assert: that: - add_span1 is changed - add_span1.current.0.spanDestGrp.attributes.name == "ansible_group" @@ -80,7 +80,7 @@ - add_span1.current.0.spanDestGrp.attributes.annotation == 'orchestrator:ansible' - name: Add span ansible_group again - aci_tenant_span_dst_group: + cisco.aci.aci_tenant_span_dst_group: <<: *aci_info destination_group: ansible_group description: Test span @@ -101,12 +101,12 @@ register: add_span1_again - name: Verify add span again - assert: + ansible.builtin.assert: that: - add_span1_again is not changed - name: Change span ansible_group's src ip - aci_tenant_span_dst_group: + cisco.aci.aci_tenant_span_dst_group: <<: *aci_info destination_group: ansible_group2 description: Test span @@ -127,7 +127,7 @@ register: change_span1_ip - name: Change span ansible_group's dscp - aci_tenant_span_dst_group: + cisco.aci.aci_tenant_span_dst_group: <<: *aci_info destination_group: ansible_group2 description: Test span @@ -148,13 +148,13 @@ register: change_span1_dscp - name: Verify changes in span - assert: + ansible.builtin.assert: that: - change_span1_ip.current.0.spanDestGrp.children.0.spanDest.children.0.spanRsDestEpg.attributes.ip == "10.0.0.2" - change_span1_dscp.current.0.spanDestGrp.children.0.spanDest.children.0.spanRsDestEpg.attributes.dscp == "VA" - name: Add span ansible_group2 - aci_tenant_span_dst_group: + cisco.aci.aci_tenant_span_dst_group: <<: *aci_info destination_group: ansible_group2 description: Test span @@ -175,7 +175,7 @@ register: add_span2 - name: Verify addition of second span - assert: + ansible.builtin.assert: that: - add_span2 is changed - add_span2.current.0.spanDestGrp.attributes.name == "ansible_group2" @@ -192,7 +192,7 @@ - add_span2.current.0.spanDestGrp.children.0.spanDest.children.0.spanRsDestEpg.attributes.ttl == "2" - name: Query span ansible_group - aci_tenant_span_dst_group: + cisco.aci.aci_tenant_span_dst_group: <<: *aci_info tenant: ansible_tenant destination_group: ansible_group @@ -200,13 +200,13 @@ register: query_span_ansible_group - name: Query all span dest groups - aci_tenant_span_dst_group: + cisco.aci.aci_tenant_span_dst_group: <<: *aci_info state: query register: query_all_span - name: Verify Query of span - assert: + ansible.builtin.assert: that: - query_span_ansible_group is not changed - query_span_ansible_group.current.0.spanDestGrp.attributes.name == "ansible_group" @@ -224,7 +224,7 @@ - query_all_span | length >= 2 - name: Remove span ansible_group - aci_tenant_span_dst_group: + cisco.aci.aci_tenant_span_dst_group: <<: *aci_info tenant: ansible_tenant destination_group: ansible_group @@ -232,7 +232,7 @@ register: remove_span1 - name: Remove span ansible_group2 - aci_tenant_span_dst_group: + cisco.aci.aci_tenant_span_dst_group: <<: *aci_info tenant: ansible_tenant destination_group: ansible_group2 @@ -240,7 +240,7 @@ register: remove_span2 - name: Verify Remove of span - assert: + ansible.builtin.assert: that: - remove_span1 is changed - remove_span1.current == [] @@ -249,7 +249,7 @@ # CLEAN ENVIRONMENT - name: Remove the ansible_tenant - aci_tenant: + cisco.aci.aci_tenant: <<: *aci_info tenant: ansible_tenant state: absent diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_tenant_span_src_group/tasks/main.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_tenant_span_src_group/tasks/main.yml index 9f83d0344..06b78e596 100644 --- a/ansible_collections/cisco/aci/tests/integration/targets/aci_tenant_span_src_group/tasks/main.yml +++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_tenant_span_src_group/tasks/main.yml @@ -4,12 +4,12 @@ # GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) - name: Test that we have an ACI APIC host, ACI username and ACI password - fail: + ansible.builtin.fail: msg: 'Please define the following variables: aci_hostname, aci_username and aci_password.' when: aci_hostname is not defined or aci_username is not defined or aci_password is not defined - name: Set vars - set_fact: + ansible.builtin.set_fact: aci_info: &aci_info host: "{{ aci_hostname }}" username: "{{ aci_username }}" @@ -27,7 +27,7 @@ state: absent - name: Verify Cloud and Non-Cloud Sites in use. - include_tasks: ../../../../../../integration/targets/aci_cloud_provider/tasks/main.yml + ansible.builtin.include_tasks: ../../../../../../integration/targets/aci_cloud_provider/tasks/main.yml - name: Execute tasks only for non-cloud sites when: query_cloud.current == [] # This condition will execute only non-cloud sites diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_tenant_span_src_group_src/tasks/main.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_tenant_span_src_group_src/tasks/main.yml index 65b8722f9..7c4f5d708 100644 --- a/ansible_collections/cisco/aci/tests/integration/targets/aci_tenant_span_src_group_src/tasks/main.yml +++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_tenant_span_src_group_src/tasks/main.yml @@ -4,12 +4,12 @@ # GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) - name: Test that we have an ACI APIC host, ACI username and ACI password - fail: + ansible.builtin.fail: msg: 'Please define the following variables: aci_hostname, aci_username and aci_password.' when: aci_hostname is not defined or aci_username is not defined or aci_password is not defined - name: Set vars - set_fact: + ansible.builtin.set_fact: aci_info: &aci_info host: "{{ aci_hostname }}" username: "{{ aci_username }}" @@ -27,7 +27,7 @@ state: absent - name: Verify Cloud and Non-Cloud Sites in use. - include_tasks: ../../../../../../integration/targets/aci_cloud_provider/tasks/main.yml + ansible.builtin.include_tasks: ../../../../../../integration/targets/aci_cloud_provider/tasks/main.yml - name: Execute tasks only for non-cloud sites when: query_cloud.current == [] # This condition will execute only non-cloud sites diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_tenant_span_src_group_to_dst_group/tasks/main.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_tenant_span_src_group_to_dst_group/tasks/main.yml index e9dac612d..6a3b87016 100644 --- a/ansible_collections/cisco/aci/tests/integration/targets/aci_tenant_span_src_group_to_dst_group/tasks/main.yml +++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_tenant_span_src_group_to_dst_group/tasks/main.yml @@ -4,12 +4,12 @@ # GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) - name: Test that we have an ACI APIC host, ACI username and ACI password - fail: + ansible.builtin.fail: msg: 'Please define the following variables: aci_hostname, aci_username and aci_password.' when: aci_hostname is not defined or aci_username is not defined or aci_password is not defined - name: Set vars - set_fact: + ansible.builtin.set_fact: aci_info: &aci_info host: "{{ aci_hostname }}" username: "{{ aci_username }}" @@ -27,7 +27,7 @@ state: absent - name: Verify Cloud and Non-Cloud Sites in use. - include_tasks: ../../../../../../integration/targets/aci_cloud_provider/tasks/main.yml + ansible.builtin.include_tasks: ../../../../../../integration/targets/aci_cloud_provider/tasks/main.yml - name: Execute tasks only for non-cloud sites when: query_cloud.current == [] # This condition will execute only non-cloud sites diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_vlan_pool/tasks/dynamic.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_vlan_pool/tasks/dynamic.yml index 0469210f8..6453552c1 100644 --- a/ansible_collections/cisco/aci/tests/integration/targets/aci_vlan_pool/tasks/dynamic.yml +++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_vlan_pool/tasks/dynamic.yml @@ -39,7 +39,7 @@ register: nm_add_dynamic_vlan_pool - name: Verify add_dynamic_vlan_pool - assert: + ansible.builtin.assert: that: - cm_add_dynamic_vlan_pool is changed - nm_add_dynamic_vlan_pool is changed @@ -66,7 +66,7 @@ register: nm_add_dynamic_vlan_pool_again - name: Verify add_dynamic_vlan_pool_again - assert: + ansible.builtin.assert: that: - cm_add_dynamic_vlan_pool_again is not changed - nm_add_dynamic_vlan_pool_again is not changed @@ -88,7 +88,7 @@ register: nm_add_dynamic_vlan_pool_descr - name: Verify add_dynamic_vlan_pool_descr - assert: + ansible.builtin.assert: that: - cm_add_dynamic_vlan_pool_descr is changed - nm_add_dynamic_vlan_pool_descr is changed @@ -116,7 +116,7 @@ register: nm_add_dynamic_vlan_pool_descr_again - name: Verify add_dynamic_vlan_pool_descr_again - assert: + ansible.builtin.assert: that: - cm_add_dynamic_vlan_pool_descr_again is not changed - nm_add_dynamic_vlan_pool_descr_again is not changed @@ -134,7 +134,7 @@ register: nm_add_dynamic_vlan_pool_again_no_descr - name: Verify add_dynamic_vlan_pool_again_no_descr - assert: + ansible.builtin.assert: that: - cm_add_dynamic_vlan_pool_again_no_descr is not changed - nm_add_dynamic_vlan_pool_again_no_descr is not changed @@ -160,7 +160,7 @@ register: nm_query_all_dynamic_vlan_pools - name: Verify query_all_dynamic_vlan_pools - assert: + ansible.builtin.assert: that: - cm_query_all_dynamic_vlan_pools is not changed - nm_query_all_dynamic_vlan_pools is not changed @@ -185,7 +185,7 @@ register: nm_query_dynamic_vlan_pool - name: Verify query_dynamic_vlan_pool - assert: + ansible.builtin.assert: that: - cm_query_dynamic_vlan_pool is not changed - nm_query_dynamic_vlan_pool is not changed @@ -207,7 +207,7 @@ register: nm_remove_dynamic_vlan_pool - name: Verify remove_dynamic_vlan_pool - assert: + ansible.builtin.assert: that: - cm_remove_dynamic_vlan_pool is changed - nm_remove_dynamic_vlan_pool is changed @@ -227,7 +227,7 @@ register: nm_remove_dynamic_vlan_pool_again - name: Verify remove_dynamic_vlan_pool_again - assert: + ansible.builtin.assert: that: - cm_remove_dynamic_vlan_pool_again is not changed - nm_remove_dynamic_vlan_pool_again is not changed @@ -255,7 +255,7 @@ # TODO: Implement more tests - name: Verify query_non_dynamic_vlan_pool - assert: + ansible.builtin.assert: that: - cm_query_non_dynamic_vlan_pool is not changed - nm_query_non_dynamic_vlan_pool is not changed @@ -278,7 +278,7 @@ register: error_on_missing_required_param - name: Verify error_on_missing_required_param - assert: + ansible.builtin.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"' @@ -298,7 +298,7 @@ register: error_on_missing_together_param - name: Verify error_on_missing_together_param - assert: + ansible.builtin.assert: that: - error_on_missing_together_param is failed - error_on_missing_together_param.msg == "ACI requires the 'pool_allocation_mode' when 'pool' is provided" diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_vlan_pool/tasks/main.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_vlan_pool/tasks/main.yml index 0bac9032c..21d769f61 100644 --- a/ansible_collections/cisco/aci/tests/integration/targets/aci_vlan_pool/tasks/main.yml +++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_vlan_pool/tasks/main.yml @@ -4,12 +4,12 @@ # GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) - name: Test that we have an ACI APIC host, ACI username and ACI password - fail: + ansible.builtin.fail: msg: 'Please define the following variables: aci_hostname, aci_username and aci_password.' when: aci_hostname is not defined or aci_username is not defined or aci_password is not defined - name: Verify Cloud and Non-Cloud Sites in use. - include_tasks: ../../../../../../integration/targets/aci_cloud_provider/tasks/main.yml + ansible.builtin.include_tasks: ../../../../../../integration/targets/aci_cloud_provider/tasks/main.yml - name: Execute tasks only for non-cloud sites when: query_cloud.current == [] # This condition will execute only non-cloud sites diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_vlan_pool/tasks/static.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_vlan_pool/tasks/static.yml index 3ddae4c47..de35cba16 100644 --- a/ansible_collections/cisco/aci/tests/integration/targets/aci_vlan_pool/tasks/static.yml +++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_vlan_pool/tasks/static.yml @@ -38,7 +38,7 @@ register: nm_add_static_vlan_pool - name: Verify add_static_vlan_pool - assert: + ansible.builtin.assert: that: - cm_add_static_vlan_pool is changed - nm_add_static_vlan_pool is changed @@ -65,7 +65,7 @@ register: nm_add_static_vlan_pool_again - name: Verify add_static_vlan_pool_again - assert: + ansible.builtin.assert: that: - cm_add_static_vlan_pool_again is not changed - nm_add_static_vlan_pool_again is not changed @@ -87,7 +87,7 @@ register: nm_add_static_vlan_pool_descr - name: Verify add_static_vlan_pool_descr - assert: + ansible.builtin.assert: that: - cm_add_static_vlan_pool_descr is changed - nm_add_static_vlan_pool_descr is changed @@ -115,7 +115,7 @@ register: nm_add_static_vlan_pool_descr_again - name: Verify add_static_vlan_pool_descr_again - assert: + ansible.builtin.assert: that: - cm_add_static_vlan_pool_descr_again is not changed - nm_add_static_vlan_pool_descr_again is not changed @@ -133,7 +133,7 @@ register: nm_add_static_vlan_pool_again_no_descr - name: Verify add_static_vlan_pool_again_no_descr - assert: + ansible.builtin.assert: that: - cm_add_static_vlan_pool_again_no_descr is not changed - nm_add_static_vlan_pool_again_no_descr is not changed @@ -159,7 +159,7 @@ register: nm_query_all_static_vlan_pools - name: Verify query_all_static_vlan_pools - assert: + ansible.builtin.assert: that: - cm_query_all_static_vlan_pools is not changed - nm_query_all_static_vlan_pools is not changed @@ -184,7 +184,7 @@ register: nm_query_static_vlan_pool - name: Verify query_static_vlan_pool - assert: + ansible.builtin.assert: that: - cm_query_static_vlan_pool is not changed - nm_query_static_vlan_pool is not changed @@ -206,7 +206,7 @@ register: nm_remove_static_vlan_pool - name: Verify remove_static_vlan_pool - assert: + ansible.builtin.assert: that: - cm_remove_static_vlan_pool is changed - nm_remove_static_vlan_pool is changed @@ -226,7 +226,7 @@ register: nm_remove_static_vlan_pool_again - name: Verify remove_static_vlan_pool_again - assert: + ansible.builtin.assert: that: - cm_remove_static_vlan_pool_again is not changed - nm_remove_static_vlan_pool_again is not changed @@ -254,7 +254,7 @@ # TODO: Implement more tests - name: Verify query_non_static_vlan_pool - assert: + ansible.builtin.assert: that: - cm_query_non_static_vlan_pool is not changed - nm_query_non_static_vlan_pool is not changed @@ -277,7 +277,7 @@ register: error_on_missing_required_param - name: Verify error_on_missing_required_param - assert: + ansible.builtin.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"' @@ -297,7 +297,7 @@ register: error_on_missing_together_param - name: Verify error_on_missing_together_param - assert: + ansible.builtin.assert: that: - error_on_missing_together_param is failed - error_on_missing_together_param.msg == "ACI requires the 'pool_allocation_mode' when 'pool' is provided" diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_vlan_pool_encap_block/tasks/main.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_vlan_pool_encap_block/tasks/main.yml index 5ccf8bfbf..125d210a9 100644 --- a/ansible_collections/cisco/aci/tests/integration/targets/aci_vlan_pool_encap_block/tasks/main.yml +++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_vlan_pool_encap_block/tasks/main.yml @@ -5,12 +5,12 @@ # GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) - name: Test that we have an aci apic host, aci username and aci password - fail: + ansible.builtin.fail: msg: 'Please define the following variables: aci_hostname, aci_username and aci_password.' when: aci_hostname is not defined or aci_username is not defined or aci_password is not defined - name: Verify Cloud and Non-Cloud Sites in use. - include_tasks: ../../../../../../integration/targets/aci_cloud_provider/tasks/main.yml + ansible.builtin.include_tasks: ../../../../../../integration/targets/aci_cloud_provider/tasks/main.yml - name: Execute tasks only for non-cloud sites when: query_cloud.current == [] # This condition will execute only non-cloud sites @@ -58,7 +58,7 @@ register: encap_block_present_check_mode - name: Present assertions - assert: + ansible.builtin.assert: that: - encap_block_present_check_mode is changed - encap_block_present_check_mode.sent.fvnsEncapBlk.attributes.allocMode == 'inherit' @@ -73,7 +73,7 @@ register: encap_block_present - name: Present assertions - assert: + ansible.builtin.assert: that: - encap_block_present is changed - encap_block_present.previous == [] @@ -87,7 +87,7 @@ register: encap_block_present_idempotent - name: Present assertions - assert: + ansible.builtin.assert: that: - encap_block_present_idempotent is not changed - encap_block_present_idempotent.previous.0.fvnsEncapBlk.attributes.name == "anstest" @@ -100,7 +100,7 @@ register: encap_block_present_update - name: Present assertions - assert: + ansible.builtin.assert: that: - encap_block_present_update is changed - encap_block_present_update.previous != [] @@ -115,7 +115,7 @@ register: encap_block_present_2 - name: Present assertions - assert: + ansible.builtin.assert: that: - encap_block_present_2 is changed - encap_block_present_2.previous == [] @@ -128,7 +128,7 @@ register: encap_block_start_low - name: Present assertions - assert: + ansible.builtin.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" @@ -141,7 +141,7 @@ register: encap_block_start_high - name: Present assertions - assert: + ansible.builtin.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" @@ -154,7 +154,7 @@ register: encap_block_end_low - name: Present assertions - assert: + ansible.builtin.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" @@ -167,7 +167,7 @@ register: encap_block_end_high - name: Present assertions - assert: + ansible.builtin.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" @@ -180,7 +180,7 @@ register: encap_block_start_end - name: Present assertions - assert: + ansible.builtin.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'" @@ -192,7 +192,7 @@ register: encap_block_present_missing_param - name: Present assertions - assert: + ansible.builtin.assert: that: - encap_block_present_missing_param is failed - 'encap_block_present_missing_param.msg == "state is present but all of the following are missing: block_end, block_start"' @@ -204,7 +204,7 @@ register: encap_block_query - name: Query assertions - assert: + ansible.builtin.assert: that: - encap_block_query is not changed - encap_block_query.url.endswith("infra/vlanns-[anstest]-static/from-[vlan-20]-to-[vlan-40].json") @@ -219,7 +219,7 @@ register: encap_block_query_from_to_name - name: Query assertions - assert: + ansible.builtin.assert: that: - encap_block_query_from_to_name is not changed - encap_block_query_from_to_name.url.endswith("class/fvnsEncapBlk.json") @@ -237,7 +237,7 @@ register: encap_block_query_from_name - name: Query assertions - assert: + ansible.builtin.assert: that: - encap_block_query_from_name is not changed - encap_block_query_from_name.url.endswith("class/fvnsEncapBlk.json") @@ -253,7 +253,7 @@ register: encap_block_query_to_name - name: Query assertions - assert: + ansible.builtin.assert: that: - encap_block_query_to_name is not changed - encap_block_query_to_name.url.endswith("class/fvnsEncapBlk.json") @@ -270,7 +270,7 @@ register: encap_block_query_name - name: Query assertions - assert: + ansible.builtin.assert: that: - encap_block_query_name is not changed - encap_block_query_name.url.endswith("class/fvnsEncapBlk.json") @@ -284,7 +284,7 @@ register: encap_block_query_from_to - name: Query assertions - assert: + ansible.builtin.assert: that: - encap_block_query_from_to is not changed - encap_block_query_from_to.url.endswith("class/fvnsEncapBlk.json") @@ -301,7 +301,7 @@ register: encap_block_query_pool - name: Query assertions - assert: + ansible.builtin.assert: that: - encap_block_query_pool is not changed - encap_block_query_pool.current | length == 1 @@ -318,7 +318,7 @@ register: encap_block_query_all - name: Query assertions - assert: + ansible.builtin.assert: that: - encap_block_query_all is not changed - encap_block_query_all.current | length > 1 @@ -332,7 +332,7 @@ register: delete_range - name: Absent assertions - assert: + ansible.builtin.assert: that: - delete_range is changed - delete_range.proposed == {} @@ -346,7 +346,7 @@ register: delete_check_mode - name: Absent assertions - assert: + ansible.builtin.assert: that: - delete_check_mode is changed - delete_check_mode.previous != [] @@ -357,7 +357,7 @@ register: delete_encap_block_2 - name: Absent assertions - assert: + ansible.builtin.assert: that: - delete_encap_block_2 is changed - delete_encap_block_2.previous == delete_check_mode.previous @@ -368,7 +368,7 @@ register: delete_idempotent - name: Absent assertions - assert: + ansible.builtin.assert: that: - delete_idempotent is not changed - delete_idempotent.previous == [] diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_vmm_controller/tasks/main.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_vmm_controller/tasks/main.yml index 7a02169b0..820d03e75 100644 --- a/ansible_collections/cisco/aci/tests/integration/targets/aci_vmm_controller/tasks/main.yml +++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_vmm_controller/tasks/main.yml @@ -1,11 +1,12 @@ # Test code for the ACI modules # Copyright: (c) 2021, Anvitha Jain (@anvitha-jain) +# Copyright: (c) 2023, Akini Ross (@akinross) # GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) # CLEAN ENVIRONMENT - name: Set vars - set_fact: + ansible.builtin.set_fact: aci_info: &aci_info host: "{{ aci_hostname }}" username: "{{ aci_username }}" @@ -31,7 +32,7 @@ - openstack - name: Verify Cloud and Non-Cloud Sites in use. - include_tasks: ../../../../../../integration/targets/aci_cloud_provider/tasks/main.yml + ansible.builtin.include_tasks: ../../../../../../integration/targets/aci_cloud_provider/tasks/main.yml - name: Execute tasks only for non-cloud sites when: query_cloud.current == [] # This condition will skip execution for cloud sites @@ -52,12 +53,12 @@ - openstack - name: Verify VMM add_domain - assert: + ansible.builtin.assert: that: - nm_add_domain is changed - name: Add controller to VMware VMM domain - aci_vmm_controller: &add_controller + cisco.aci.aci_vmm_controller: &add_controller <<: *aci_info domain: vmm_dom name: vCenter1 @@ -69,7 +70,7 @@ register: nm_add_controller - name: Verify VMM add_controller - assert: + ansible.builtin.assert: that: - nm_add_controller is changed - nm_add_controller.sent.vmmCtrlrP.attributes.name == 'vCenter1' @@ -80,7 +81,7 @@ - nm_add_controller.current.0.vmmCtrlrP.attributes.annotation == 'orchestrator:ansible' - name: Add another controller to all VMM domain - aci_vmm_controller: + cisco.aci.aci_vmm_controller: <<: *add_controller name: vCenter2 credentials: vCenterCredentials1 @@ -96,12 +97,12 @@ - openstack - name: Verify another VMM add_controller - assert: + ansible.builtin.assert: that: - add_controller is changed - name: Add controller to VMware VMM domain again - aci_vmm_controller: + cisco.aci.aci_vmm_controller: <<: *add_controller name: vCenter2 controller_hostname: 10.10.1.1 @@ -109,12 +110,12 @@ register: add_controller_again - name: Verify another VMM add_controller again - assert: + ansible.builtin.assert: that: - add_controller_again is not changed - name: Query controller - aci_vmm_controller: + cisco.aci.aci_vmm_controller: <<: *aci_info domain: vmm_dom name: vCenter1 @@ -123,41 +124,96 @@ register: query_controller - name: Verify VMM query_controller - assert: + ansible.builtin.assert: that: - query_controller is not changed - query_controller.current.0.vmmCtrlrP.attributes.dn == 'uni/vmmp-VMware/dom-vmm_dom/ctrlr-vCenter1' - query_controller.current.0.vmmCtrlrP.attributes.name == 'vCenter1' - - name: Query all controllers - aci_vmm_controller: + - name: Query controller ( only vm_provider set ) + cisco.aci.aci_vmm_controller: + <<: *aci_info + vm_provider: vmware + state: query + register: query_controller_vm_provider + + - name: Query controller ( only domain set ) + cisco.aci.aci_vmm_controller: <<: *aci_info domain: vmm_dom + state: query + register: query_controller_domain + + - name: Query controller ( only name set ) + cisco.aci.aci_vmm_controller: + <<: *aci_info + name: vCenter2 + state: query + register: query_controller_name + + - name: Query controller ( only vm_provider and domain set ) + cisco.aci.aci_vmm_controller: + <<: *aci_info vm_provider: vmware + domain: vmm_dom state: query - register: query_controller + register: query_controller_vm_provider_domain + + - name: Query controller ( only vm_provider and name set ) + cisco.aci.aci_vmm_controller: + <<: *aci_info + vm_provider: vmware + name: vCenter2 + state: query + register: query_controller_vm_provider_name + + - name: Query controller ( only domain and name set ) + cisco.aci.aci_vmm_controller: + <<: *aci_info + domain: vmm_dom + name: vCenter2 + state: query + register: query_controller_domain_name + + - name: Query all controllers + cisco.aci.aci_vmm_controller: + <<: *aci_info + state: query + register: query_controller_all - name: Verify VMM query_controller - assert: + ansible.builtin.assert: that: - - query_controller is not changed + - query_controller_vm_provider is not changed + - query_controller_vm_provider.current.0.vmmProvP.attributes.dn == "uni/vmmp-VMware" + - query_controller_domain is not changed + - query_controller_domain.current.0.vmmDomP.attributes.dn == "uni/vmmp-VMware/dom-vmm_dom" + - query_controller_name is not changed + - query_controller_name.current.0.vmmCtrlrP.attributes.dn == "uni/vmmp-VMware/dom-vmm_dom/ctrlr-vCenter2" + - query_controller_vm_provider_domain is not changed + - query_controller_vm_provider_domain.current.0.vmmDomP.attributes.dn == "uni/vmmp-VMware/dom-vmm_dom" + - query_controller_vm_provider_name is not changed + - query_controller_vm_provider_name.current.0.vmmCtrlrP.attributes.dn == "uni/vmmp-VMware/dom-vmm_dom/ctrlr-vCenter2" + - query_controller_domain_name is not changed + - query_controller_domain_name.current.0.vmmDomP.attributes.dn == "uni/vmmp-VMware/dom-vmm_dom" + - query_controller_all is not changed - name: Delete controllers - aci_vmm_controller: + cisco.aci.aci_vmm_controller: <<: *add_controller name: vCenter1 state: absent register: remove_controller - name: Delete controllers - aci_vmm_controller: + cisco.aci.aci_vmm_controller: <<: *add_controller name: vCenter2 state: absent register: remove_controller_2 - name: Verify VMM remove_controller - assert: + ansible.builtin.assert: that: - remove_controller is changed - remove_controller_2 is changed diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_vmm_credential/tasks/main.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_vmm_credential/tasks/main.yml index b76c4563a..f88676dd8 100644 --- a/ansible_collections/cisco/aci/tests/integration/targets/aci_vmm_credential/tasks/main.yml +++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_vmm_credential/tasks/main.yml @@ -4,7 +4,7 @@ # GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) - name: Test that we have an ACI APIC host, ACI username and ACI password - fail: + ansible.builtin.fail: msg: 'Please define the following variables: aci_hostname, aci_username and aci_password.' when: aci_hostname is not defined or aci_username is not defined or aci_password is not defined diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_vmm_credential/tasks/vmware.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_vmm_credential/tasks/vmware.yml index 262ecf33c..c56d62c6c 100644 --- a/ansible_collections/cisco/aci/tests/integration/targets/aci_vmm_credential/tasks/vmware.yml +++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_vmm_credential/tasks/vmware.yml @@ -5,7 +5,7 @@ # CLEAN ENVIRONMENT - name: Set vars - set_fact: + ansible.builtin.set_fact: aci_info: &aci_info host: "{{ aci_hostname }}" username: "{{ aci_username }}" @@ -26,7 +26,7 @@ register: nm_remove_domain - name: Verify Cloud and Non-Cloud Sites in use. - include_tasks: ../../../../../../integration/targets/aci_cloud_provider/tasks/main.yml + ansible.builtin.include_tasks: ../../../../../../integration/targets/aci_cloud_provider/tasks/main.yml - name: Execute tasks only for non-cloud sites when: query_cloud.current == [] # This condition will skip execution for cloud sites @@ -42,7 +42,7 @@ register: nm_add_domain - name: Verify add_domain - assert: + ansible.builtin.assert: that: - nm_add_domain is changed @@ -65,7 +65,7 @@ register: nm_remove_credential - name: Verify remove_credential - assert: + ansible.builtin.assert: that: - cm_remove_credential is not changed - nm_remove_credential is not changed @@ -96,7 +96,7 @@ register: cm_add_credential_again - name: Verify add_credential - assert: + ansible.builtin.assert: that: - cm_add_credential is changed - nm_add_credential is changed @@ -132,7 +132,7 @@ register: nm_mod_credential - name: Verify mod_credential - assert: + ansible.builtin.assert: that: - cm_mod_credential is changed - nm_mod_credential is changed @@ -182,7 +182,7 @@ register: nm_query_all_credential - name: Verify query_credential - assert: + ansible.builtin.assert: that: - cm_query_credential is not changed - nm_query_credential is not changed @@ -209,7 +209,7 @@ register: nm_remove_credential_final - name: Verify remove_credential - assert: + ansible.builtin.assert: that: - cm_remove_credential_again is changed - nm_remove_credential_again is changed diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_vmm_uplink/tasks/main.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_vmm_uplink/tasks/main.yml index 1e7b6a6cf..8d627c730 100644 --- a/ansible_collections/cisco/aci/tests/integration/targets/aci_vmm_uplink/tasks/main.yml +++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_vmm_uplink/tasks/main.yml @@ -4,13 +4,13 @@ # GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) - name: Test that we have an ACI APIC host, ACI username and ACI password - fail: + ansible.builtin.fail: msg: 'Please define the following variables: aci_hostname, aci_username and aci_password.' when: aci_hostname is not defined or aci_username is not defined or aci_password is not defined # GET Credentials from the inventory - name: Set vars - set_fact: + ansible.builtin.set_fact: aci_info: &aci_info host: "{{ aci_hostname }}" username: "{{ aci_username }}" @@ -22,14 +22,14 @@ # PERFORM TESTS ONLY ON SUPPORTED APICS - name: Query system information - aci_system: + cisco.aci.aci_system: <<: *aci_info id: 1 state: query register: version - name: Verify Cloud and Non-Cloud Sites in use. - include_tasks: ../../../../../../integration/targets/aci_cloud_provider/tasks/main.yml + ansible.builtin.include_tasks: ../../../../../../integration/targets/aci_cloud_provider/tasks/main.yml - name: Execute tasks only for non-cloud sites when: @@ -38,7 +38,7 @@ block: # CLEAN ENVIRONMENT - name: Remove ansible_domain if it already exists - aci_domain: + cisco.aci.aci_domain: <<: *aci_info domain: ansible_domain domain_type: vmm @@ -47,7 +47,7 @@ # CREATE VMWARE DOMAIN - name: Create ansible_domain - aci_domain: + cisco.aci.aci_domain: <<: *aci_info domain: ansible_domain domain_type: vmm @@ -56,7 +56,7 @@ # CREATE VMWARE UPLINK CONTAINER - name: Create VMWare Uplink Container - aci_vmm_uplink_container: + cisco.aci.aci_vmm_uplink_container: <<: *aci_info domain: ansible_domain num_of_uplinks: 1 @@ -73,7 +73,7 @@ register: create_uplink - name: Verify Uplink Creation - assert: + ansible.builtin.assert: that: - create_uplink.current.0.vmmUplinkP.attributes.dn == "uni/vmmp-VMware/dom-ansible_domain/uplinkpcont/uplinkp-1" - create_uplink.current.0.vmmUplinkP.attributes.uplinkId == "1" @@ -91,7 +91,7 @@ register: create_uplink_again - name: Verify Uplink Creation idempotence - assert: + ansible.builtin.assert: that: - create_uplink_again is not changed - create_uplink_again.current.0.vmmUplinkP.attributes.dn == "uni/vmmp-VMware/dom-ansible_domain/uplinkpcont/uplinkp-1" @@ -109,7 +109,7 @@ register: update_uplink - name: Verify Uplink update - assert: + ansible.builtin.assert: that: - update_uplink is changed - update_uplink.current.0.vmmUplinkP.attributes.dn == "uni/vmmp-VMware/dom-ansible_domain/uplinkpcont/uplinkp-1" @@ -126,7 +126,7 @@ register: query_uplink - name: Verify Uplink query - assert: + ansible.builtin.assert: that: - query_uplink is not changed - query_uplink.current.0.vmmUplinkP.attributes.dn == "uni/vmmp-VMware/dom-ansible_domain/uplinkpcont/uplinkp-1" @@ -143,7 +143,7 @@ register: remove_uplink - name: Verify VMWare Uplink deletion - assert: + ansible.builtin.assert: that: - remove_uplink is changed - remove_uplink.current == [] @@ -161,13 +161,13 @@ register: remove_uplink_again - name: Verify VMWare Uplink deletion idempotence - assert: + ansible.builtin.assert: that: - remove_uplink_again is not changed # CLEAN UP - name: Remove ansible_domain - aci_domain: + cisco.aci.aci_domain: <<: *aci_info domain: ansible_domain domain_type: vmm diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_vmm_uplink_container/tasks/main.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_vmm_uplink_container/tasks/main.yml index 0ddbe2174..7839728a9 100644 --- a/ansible_collections/cisco/aci/tests/integration/targets/aci_vmm_uplink_container/tasks/main.yml +++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_vmm_uplink_container/tasks/main.yml @@ -4,13 +4,13 @@ # GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) - name: Test that we have an ACI APIC host, ACI username and ACI password - fail: + ansible.builtin.fail: msg: 'Please define the following variables: aci_hostname, aci_username and aci_password.' when: aci_hostname is not defined or aci_username is not defined or aci_password is not defined # GET Credentials from the inventory - name: Set vars - set_fact: + ansible.builtin.set_fact: aci_info: &aci_info host: "{{ aci_hostname }}" username: "{{ aci_username }}" @@ -22,14 +22,14 @@ # PERFORM TESTS ONLY ON SUPPORTED APICS - name: Query system information - aci_system: + cisco.aci.aci_system: <<: *aci_info id: 1 state: query register: version - name: Verify Cloud and Non-Cloud Sites in use. - include_tasks: ../../../../../../integration/targets/aci_cloud_provider/tasks/main.yml + ansible.builtin.include_tasks: ../../../../../../integration/targets/aci_cloud_provider/tasks/main.yml - name: Execute tasks only for non-cloud sites when: @@ -38,7 +38,7 @@ block: # CLEAN ENVIRONMENT - name: Remove ansible_domain if it already exists - aci_domain: + cisco.aci.aci_domain: <<: *aci_info domain: ansible_domain domain_type: vmm @@ -47,7 +47,7 @@ # CREATE VMWARE DOMAIN - name: Create ansible_domain - aci_domain: + cisco.aci.aci_domain: <<: *aci_info domain: ansible_domain domain_type: vmm @@ -56,7 +56,7 @@ # CREATE VMWARE UPLINK CONTAINER - name: Create VMWare Uplink Container - aci_vmm_uplink_container: + cisco.aci.aci_vmm_uplink_container: <<: *aci_info domain: ansible_domain num_of_uplinks: 2 @@ -64,7 +64,7 @@ register: create_container - name: Verify Uplink Container Creation - assert: + ansible.builtin.assert: that: - create_container.current.0.vmmUplinkPCont.attributes.dn == "uni/vmmp-VMware/dom-ansible_domain/uplinkpcont" - create_container.current.0.vmmUplinkPCont.attributes.numOfUplinks == "2" @@ -72,7 +72,7 @@ # CREATE VMWARE UPLINK CONTAINER AGAIN TO CHECK IDEMPOTENCE - name: Create VMWare Uplink Container again - aci_vmm_uplink_container: + cisco.aci.aci_vmm_uplink_container: <<: *aci_info domain: ansible_domain num_of_uplinks: 2 @@ -80,7 +80,7 @@ register: create_container_again - name: Verify Uplink Container Creation Idempotence - assert: + ansible.builtin.assert: that: - create_container_again is not changed - create_container_again.current.0.vmmUplinkPCont.attributes.dn == "uni/vmmp-VMware/dom-ansible_domain/uplinkpcont" @@ -88,7 +88,7 @@ # MODIFY VMWARE UPLINK CONTAINER - name: Update VMWare Uplink Container - aci_vmm_uplink_container: + cisco.aci.aci_vmm_uplink_container: <<: *aci_info domain: ansible_domain num_of_uplinks: 3 @@ -96,7 +96,7 @@ register: update_container - name: Verify Uplink Container is updated - assert: + ansible.builtin.assert: that: - update_container is changed - update_container.current.0.vmmUplinkPCont.attributes.dn == "uni/vmmp-VMware/dom-ansible_domain/uplinkpcont" @@ -104,14 +104,14 @@ # QUERY VMWARE UPLINK CONTAINER - name: Update VMWare Uplink Container - aci_vmm_uplink_container: + cisco.aci.aci_vmm_uplink_container: <<: *aci_info domain: ansible_domain state: query register: query_container - name: Verify Uplink Container Query - assert: + ansible.builtin.assert: that: - query_container is not changed - query_container.current.0.vmmUplinkPCont.attributes.dn == "uni/vmmp-VMware/dom-ansible_domain/uplinkpcont" @@ -119,14 +119,14 @@ # DELETE VMWARE UPLINK CONTAINER - name: Remove Uplink Container - aci_vmm_uplink_container: + cisco.aci.aci_vmm_uplink_container: <<: *aci_info domain: ansible_domain state: absent register: delete_container - name: Verify Uplink Container removal - assert: + ansible.builtin.assert: that: - delete_container is changed - delete_container.current == [] @@ -135,20 +135,20 @@ # DELETE VMWARE UPLINK CONTAINER AGAIN TO TEST IDEMPOTENCE - name: Remove Uplink Container again - aci_vmm_uplink_container: + cisco.aci.aci_vmm_uplink_container: <<: *aci_info domain: ansible_domain state: absent register: delete_container_again - name: Verify Uplink Container removal idempotence - assert: + ansible.builtin.assert: that: - delete_container_again is not changed # CLEAN UP - name: Remove ansible_domain - aci_domain: + cisco.aci.aci_domain: <<: *aci_info domain: ansible_domain domain_type: vmm diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_vmm_vswitch_policy/tasks/main.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_vmm_vswitch_policy/tasks/main.yml index 371137af4..3038ff30a 100644 --- a/ansible_collections/cisco/aci/tests/integration/targets/aci_vmm_vswitch_policy/tasks/main.yml +++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_vmm_vswitch_policy/tasks/main.yml @@ -5,7 +5,7 @@ # CLEAN ENVIRONMENT - name: Set vars - set_fact: + ansible.builtin.set_fact: aci_info: &aci_info host: "{{ aci_hostname }}" username: "{{ aci_username }}" @@ -16,7 +16,7 @@ output_level: '{{ aci_output_level | default("debug") }}' - name: Query system information - aci_system: + cisco.aci.aci_system: <<: *aci_info id: 1 state: query @@ -37,7 +37,7 @@ - { domain: 'microsoft_dom', provider: 'microsoft' } - name: Verify Cloud and Non-Cloud Sites in use. - include_tasks: ../../../../../../integration/targets/aci_cloud_provider/tasks/main.yml + ansible.builtin.include_tasks: ../../../../../../integration/targets/aci_cloud_provider/tasks/main.yml - name: Execute tasks only for non-cloud sites when: query_cloud.current == [] # This condition will skip execution for cloud sites @@ -57,12 +57,12 @@ - { domain: 'microsoft_dom', provider: 'microsoft' } - name: Verify VMM add_domain - assert: + ansible.builtin.assert: that: - nm_add_domain is changed - name: Add a vSwitch policy to vmware domain - aci_vmm_vswitch_policy: &add_vmware_policies + cisco.aci.aci_vmm_vswitch_policy: &add_vmware_policies <<: *aci_info domain: vmm_dom vm_provider: vmware @@ -73,7 +73,7 @@ register: add_vmware_policy - name: Verify VMM add_vmware_policy - assert: + ansible.builtin.assert: that: - add_vmware_policy is changed - add_vmware_policy.previous == [] @@ -84,7 +84,7 @@ - add_vmware_policy.current.0.vmmVSwitchPolicyCont.attributes.annotation == 'orchestrator:ansible' - name: Add a vSwitch policy to vmware domain - aci_vmm_vswitch_policy: + cisco.aci.aci_vmm_vswitch_policy: <<: *add_vmware_policies netflow_exporter: name: Netflow_Exporter_policy @@ -94,7 +94,7 @@ register: add_vmware_policy_2 - name: Verify VMM add_vmware_policy_2 - assert: + ansible.builtin.assert: that: - add_vmware_policy_2 is changed - add_vmware_policy_2.current.0.vmmVSwitchPolicyCont.attributes.dn == 'uni/vmmp-VMware/dom-vmm_dom/vswitchpolcont' @@ -105,7 +105,7 @@ - add_vmware_policy_2.current.0.vmmVSwitchPolicyCont.children.4.vmmRsVswitchOverrideLldpIfPol.attributes.tDn == 'uni/infra/lldpIfP-LLDP_policy' - name: Add MTU policy to vmware domain when version is >= 4.2 - aci_vmm_vswitch_policy: + cisco.aci.aci_vmm_vswitch_policy: <<: *add_vmware_policies mtu_policy: MTU_policy state: present @@ -113,7 +113,7 @@ when: version.current.0.topSystem.attributes.version is version('4.2', '>=') - name: Verify VMM add_vmware_mtu_policy - assert: + ansible.builtin.assert: that: - add_vmware_mtu_policy is changed - add_vmware_mtu_policy.current.0.vmmVSwitchPolicyCont.attributes.dn == 'uni/vmmp-VMware/dom-vmm_dom/vswitchpolcont' @@ -121,7 +121,7 @@ when: version.current.0.topSystem.attributes.version is version('4.2', '>=') - name: Add a vSwitch policy to microsoft domain - aci_vmm_vswitch_policy: + cisco.aci.aci_vmm_vswitch_policy: <<: *aci_info domain: vmm_dom vm_provider: microsoft @@ -132,7 +132,7 @@ register: add_microsoft_policy - name: Verify VMM add_microsoft_policy - assert: + ansible.builtin.assert: that: - add_microsoft_policy is changed - add_microsoft_policy.previous == [] @@ -142,7 +142,7 @@ - add_microsoft_policy.current.0.vmmVSwitchPolicyCont.children.2.vmmRsVswitchOverrideLldpIfPol.attributes.tDn == 'uni/infra/lldpIfP-ms_LLDP_policy' - name: Add STP vSwitch policy to another microsoft domain - aci_vmm_vswitch_policy: + cisco.aci.aci_vmm_vswitch_policy: <<: *aci_info domain: microsoft_dom vm_provider: microsoft @@ -151,7 +151,7 @@ register: add_microsoft_stp_policy - name: Verify VMM add_microsoft_stp_policy - assert: + ansible.builtin.assert: that: - add_microsoft_stp_policy is changed - add_microsoft_stp_policy.previous == [] @@ -159,25 +159,25 @@ - add_microsoft_stp_policy.current.0.vmmVSwitchPolicyCont.children.0.vmmRsVswitchOverrideStpPol.attributes.tDn == 'uni/infra/ifPol-ms_STP_policy' - name: Query all the vSwitch policy - aci_vmm_vswitch_policy: + cisco.aci.aci_vmm_vswitch_policy: <<: *aci_info state: query register: query_all_vmware - name: Query all the vSwitch policy of the VMWare domain - aci_vmm_vswitch_policy: + cisco.aci.aci_vmm_vswitch_policy: <<: *aci_info state: query register: query_all_microsoft - name: Verify Query all tasks for vmware and microsoft domain - assert: + ansible.builtin.assert: that: - query_all_vmware is not changed - query_all_microsoft is not changed - name: Query vSwitch policies of VMWare domain - aci_vmm_vswitch_policy: + cisco.aci.aci_vmm_vswitch_policy: <<: *aci_info domain: vmm_dom vm_provider: vmware @@ -185,13 +185,13 @@ register: query_vmware - name: Verify Query vSwitch policy of the VMWare domain - assert: + ansible.builtin.assert: that: - query_vmware is not changed - query_vmware.current.0.vmmVSwitchPolicyCont.attributes.dn == 'uni/vmmp-VMware/dom-vmm_dom/vswitchpolcont' - name: Remove vSwitch Policy from VMware VMM domain - aci_vmm_vswitch_policy: + cisco.aci.aci_vmm_vswitch_policy: <<: *aci_info domain: vmm_dom vm_provider: vmware @@ -199,7 +199,7 @@ register: remove_vmware_vSwitch_policy - name: Verify remove_vmware_vSwitch_policy - assert: + ansible.builtin.assert: that: - remove_vmware_vSwitch_policy is changed - remove_vmware_vSwitch_policy.current == [] \ No newline at end of file diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_vrf/tasks/main.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_vrf/tasks/main.yml index 695f40fe7..6903b3c71 100644 --- a/ansible_collections/cisco/aci/tests/integration/targets/aci_vrf/tasks/main.yml +++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_vrf/tasks/main.yml @@ -4,7 +4,7 @@ # GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) - name: Test that we have an ACI APIC host, ACI username and ACI password - fail: + ansible.builtin.fail: msg: 'Please define the following variables: aci_hostname, aci_username and aci_password.' when: aci_hostname is not defined or aci_username is not defined or aci_password is not defined @@ -73,7 +73,7 @@ register: vrf_present_missing_param - name: present asserts - assert: + ansible.builtin.assert: that: - vrf_present_check_mode is changed - vrf_present_check_mode.sent.fvCtx.attributes.descr == 'Ansible Test' @@ -126,7 +126,7 @@ register: query_vrf - name: query asserts - assert: + ansible.builtin.assert: that: - query_all is not changed - query_all.current | length > 1 @@ -177,7 +177,7 @@ register: vrf_absent_missing_param - name: asserts for deletion task - assert: + ansible.builtin.assert: that: - vrf_absent_check_mode is changed - vrf_absent_check_mode.previous != [] diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_vrf_leak_internal_subnet/tasks/main.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_vrf_leak_internal_subnet/tasks/main.yml index 2455f24e4..33df4b78f 100644 --- a/ansible_collections/cisco/aci/tests/integration/targets/aci_vrf_leak_internal_subnet/tasks/main.yml +++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_vrf_leak_internal_subnet/tasks/main.yml @@ -4,12 +4,12 @@ # GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) - name: Test that we have an ACI APIC host, ACI username and ACI password - fail: + ansible.builtin.fail: msg: 'Please define the following variables: aci_hostname, aci_username and aci_password.' when: aci_hostname is not defined or aci_username is not defined or aci_password is not defined - name: Verify Cloud and Non-Cloud Sites in use. - include_tasks: ../../../../../../integration/targets/aci_cloud_provider/tasks/main.yml + ansible.builtin.include_tasks: ../../../../../../integration/targets/aci_cloud_provider/tasks/main.yml - name: Execute tasks only for non-cloud sites when: @@ -17,7 +17,7 @@ - version.current.0.topSystem.attributes.version is version('5', '>=') block: # block specifies execution of tasks within, based on conditions - name: Set vars - set_fact: + ansible.builtin.set_fact: aci_info: &aci_info host: '{{ aci_hostname }}' username: '{{ aci_username }}' @@ -113,7 +113,7 @@ attributes_list_present: "{{ leak_sub_present.current.0.leakInternalSubnet.children | map(attribute='leakTo.attributes') | list | sort(attribute='ctxName') }}" - name: present asserts - assert: + ansible.builtin.assert: that: - vrf_present is changed - leak_sub_check_mode is changed @@ -166,7 +166,7 @@ attributes_list_query: "{{ query.current.0.leakInternalSubnet.children | map(attribute='leakTo.attributes') | list | sort(attribute='ctxName') }}" - name: query asserts - assert: + ansible.builtin.assert: that: - query_all is not changed - query is not changed @@ -215,7 +215,7 @@ register: leak_sub_delete_idempotency - name: delete asserts - assert: + ansible.builtin.assert: that: - leak_sub_delete_check_mode is changed - leak_sub_delete_check_mode.current.0.leakInternalSubnet.children.0.leakTo.attributes.ctxName == 'test3' diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_vrf_multicast/aliases b/ansible_collections/cisco/aci/tests/integration/targets/aci_vrf_multicast/aliases new file mode 100644 index 000000000..209b793f9 --- /dev/null +++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_vrf_multicast/aliases @@ -0,0 +1,2 @@ +# No ACI simulator yet, so not enabled +# unsupported diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_vrf_multicast/tasks/main.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_vrf_multicast/tasks/main.yml new file mode 100644 index 000000000..7b2991bd5 --- /dev/null +++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_vrf_multicast/tasks/main.yml @@ -0,0 +1,1133 @@ +# Test code for the ACI modules +# Copyright: (c) 2023, Tim Cragg (@timcragg) +# Copyright: (c) 2023, Akini Ross (@akinross) + +# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) + +- name: Test that we have an ACI APIC host, ACI username and ACI password + ansible.builtin.fail: + msg: 'Please define the following variables: aci_hostname, aci_username and aci_password.' + when: aci_hostname is not defined or aci_username is not defined or aci_password is not defined + +# SET VARS + +- name: Set vars + ansible.builtin.set_fact: + aci_info: &aci_info + host: '{{ aci_hostname }}' + username: '{{ aci_username }}' + password: '{{ aci_password }}' + validate_certs: '{{ aci_validate_certs | default(false) }}' + use_ssl: '{{ aci_use_ssl | default(true) }}' + use_proxy: '{{ aci_use_proxy | default(true) }}' + output_level: '{{ aci_output_level | default("info") }}' + +# CLEAN ENVIRONMENT + +- name: Remove ansible_tenant + cisco.aci.aci_tenant: &aci_tenant_absent + <<: *aci_info + tenant: ansible_tenant + state: absent + +- name: Create ansible_tenant + cisco.aci.aci_tenant: &aci_tenant + <<: *aci_tenant_absent + state: present + +- name: Create ansible_vrf + cisco.aci.aci_vrf: &aci_ansible_vrf_1 + <<: *aci_tenant + vrf: ansible_vrf_1 + state: present + +- name: Create ansible_second_vrf + cisco.aci.aci_vrf: &aci_ansible_vrf_2 + <<: *aci_tenant + vrf: ansible_vrf_2 + state: present + +# ENABLE MULTICAST + +- name: Enable multicast on VRF 1 (check mode) + cisco.aci.aci_vrf_multicast: + <<: *aci_ansible_vrf_1 + check_mode: yes + register: cm_enable_multicast + +- name: Enable multicast on VRF 1 (normal mode) + cisco.aci.aci_vrf_multicast: + <<: *aci_ansible_vrf_1 + register: nm_enable_multicast + +- name: Enable multicast on VRF 1 again + cisco.aci.aci_vrf_multicast: + <<: *aci_ansible_vrf_1 + register: nm_enable_multicast_again + +- name: Verify create multicast VRF 1 + ansible.builtin.assert: + that: + - cm_enable_multicast is changed + - cm_enable_multicast.current == [] + - cm_enable_multicast.previous == [] + - cm_enable_multicast.proposed.pimCtxP.attributes.annotation == "orchestrator:ansible" + - cm_enable_multicast.proposed.pimCtxP.attributes.dn == "uni/tn-ansible_tenant/ctx-ansible_vrf_1/pimctxp" + - cm_enable_multicast.proposed.pimCtxP.children.0.pimResPol.children == [] + - cm_enable_multicast.proposed.pimCtxP.children.1.pimASMPatPol.children.0.pimSharedRangePol.children == [] + - cm_enable_multicast.proposed.pimCtxP.children.1.pimASMPatPol.children.1.pimSGRangeExpPol.children == [] + - cm_enable_multicast.proposed.pimCtxP.children.1.pimASMPatPol.children.2.pimRegTrPol.children == [] + - cm_enable_multicast.proposed.pimCtxP.children.2.pimSSMPatPol.children.0.pimSSMRangePol.children == [] + - nm_enable_multicast is changed + - nm_enable_multicast.current.0.pimCtxP.attributes.annotation == "orchestrator:ansible" + - nm_enable_multicast.current.0.pimCtxP.attributes.dn == "uni/tn-ansible_tenant/ctx-ansible_vrf_1/pimctxp" + - nm_enable_multicast.current.0.pimCtxP.attributes.mtu == "1500" + - nm_enable_multicast.current.0.pimCtxP.attributes.ctrl == "" + - nm_enable_multicast.current.0.pimCtxP.children.0.pimSSMPatPol.children.0.pimSSMRangePol.attributes.name == "" + - nm_enable_multicast.current.0.pimCtxP.children.1.pimASMPatPol.children.0.pimSharedRangePol.attributes.name == "" + - nm_enable_multicast.current.0.pimCtxP.children.1.pimASMPatPol.children.1.pimSGRangeExpPol.attributes.sgExpItvl == "default-timeout" + - nm_enable_multicast.current.0.pimCtxP.children.1.pimASMPatPol.children.2.pimRegTrPol.attributes.maxRate == "65535" + - nm_enable_multicast.current.0.pimCtxP.children.1.pimASMPatPol.children.2.pimRegTrPol.attributes.srcIp == "0.0.0.0" + - nm_enable_multicast.current.0.pimCtxP.children.2.pimResPol.attributes.max == "unlimited" + - nm_enable_multicast.current.0.pimCtxP.children.2.pimResPol.attributes.rsvd == "undefined" + - nm_enable_multicast.previous == [] + - nm_enable_multicast_again is not changed + - nm_enable_multicast_again.current.0.pimCtxP.attributes.annotation == "orchestrator:ansible" + - nm_enable_multicast_again.current.0.pimCtxP.attributes.dn == "uni/tn-ansible_tenant/ctx-ansible_vrf_1/pimctxp" + - nm_enable_multicast_again.current.0.pimCtxP.attributes.mtu == "1500" + - nm_enable_multicast_again.current.0.pimCtxP.attributes.ctrl == "" + - nm_enable_multicast_again.current.0.pimCtxP.children.0.pimSSMPatPol.children.0.pimSSMRangePol.attributes.name == "" + - nm_enable_multicast_again.current.0.pimCtxP.children.1.pimASMPatPol.children.0.pimSharedRangePol.attributes.name == "" + - nm_enable_multicast_again.current.0.pimCtxP.children.1.pimASMPatPol.children.1.pimSGRangeExpPol.attributes.sgExpItvl == "default-timeout" + - nm_enable_multicast_again.current.0.pimCtxP.children.1.pimASMPatPol.children.2.pimRegTrPol.attributes.maxRate == "65535" + - nm_enable_multicast_again.current.0.pimCtxP.children.1.pimASMPatPol.children.2.pimRegTrPol.attributes.srcIp == "0.0.0.0" + - nm_enable_multicast_again.current.0.pimCtxP.children.2.pimResPol.attributes.max == "unlimited" + - nm_enable_multicast_again.current.0.pimCtxP.children.2.pimResPol.attributes.rsvd == "undefined" + - nm_enable_multicast_again.previous.0.pimCtxP.attributes.annotation == "orchestrator:ansible" + - nm_enable_multicast_again.previous.0.pimCtxP.attributes.dn == "uni/tn-ansible_tenant/ctx-ansible_vrf_1/pimctxp" + - nm_enable_multicast_again.previous.0.pimCtxP.attributes.mtu == "1500" + - nm_enable_multicast_again.previous.0.pimCtxP.attributes.ctrl == "" + - nm_enable_multicast_again.previous.0.pimCtxP.children.0.pimSSMPatPol.children.0.pimSSMRangePol.attributes.name == "" + - nm_enable_multicast_again.previous.0.pimCtxP.children.1.pimASMPatPol.children.0.pimSharedRangePol.attributes.name == "" + - nm_enable_multicast_again.previous.0.pimCtxP.children.1.pimASMPatPol.children.1.pimSGRangeExpPol.attributes.sgExpItvl == "default-timeout" + - nm_enable_multicast_again.previous.0.pimCtxP.children.1.pimASMPatPol.children.2.pimRegTrPol.attributes.maxRate == "65535" + - nm_enable_multicast_again.previous.0.pimCtxP.children.1.pimASMPatPol.children.2.pimRegTrPol.attributes.srcIp == "0.0.0.0" + - nm_enable_multicast_again.previous.0.pimCtxP.children.2.pimResPol.attributes.max == "unlimited" + - nm_enable_multicast_again.previous.0.pimCtxP.children.2.pimResPol.attributes.rsvd == "undefined" + +# UPDATE MULTICAST SETTINGS + +- name: Update pim setting on VRF 1 + cisco.aci.aci_vrf_multicast: + <<: *aci_ansible_vrf_1 + pim_setting: + mtu: 2000 + control_state: [ fast, strict ] + register: nm_update_pim_setting + +- name: Remove control_state from pim setting on VRF 1 + cisco.aci.aci_vrf_multicast: + <<: *aci_ansible_vrf_1 + pim_setting: + control_state: [] + register: nm_update_pim_setting_remove_control_state + +- name: Verify update pim setting on VRF 1 + ansible.builtin.assert: + that: + - nm_update_pim_setting is changed + - nm_update_pim_setting.current.0.pimCtxP.attributes.annotation == "orchestrator:ansible" + - nm_update_pim_setting.current.0.pimCtxP.attributes.dn == "uni/tn-ansible_tenant/ctx-ansible_vrf_1/pimctxp" + - nm_update_pim_setting.current.0.pimCtxP.attributes.mtu == "2000" + - nm_update_pim_setting.current.0.pimCtxP.attributes.ctrl == "fast-conv,strict-rfc-compliant" + - nm_update_pim_setting.current.0.pimCtxP.children.0.pimSSMPatPol.children.0.pimSSMRangePol.attributes.name == "" + - nm_update_pim_setting.current.0.pimCtxP.children.1.pimASMPatPol.children.0.pimSharedRangePol.attributes.name == "" + - nm_update_pim_setting.current.0.pimCtxP.children.1.pimASMPatPol.children.1.pimSGRangeExpPol.attributes.sgExpItvl == "default-timeout" + - nm_update_pim_setting.current.0.pimCtxP.children.1.pimASMPatPol.children.2.pimRegTrPol.attributes.maxRate == "65535" + - nm_update_pim_setting.current.0.pimCtxP.children.1.pimASMPatPol.children.2.pimRegTrPol.attributes.srcIp == "0.0.0.0" + - nm_update_pim_setting.current.0.pimCtxP.children.2.pimResPol.attributes.max == "unlimited" + - nm_update_pim_setting.current.0.pimCtxP.children.2.pimResPol.attributes.rsvd == "undefined" + - nm_update_pim_setting.previous.0.pimCtxP.attributes.annotation == "orchestrator:ansible" + - nm_update_pim_setting.previous.0.pimCtxP.attributes.dn == "uni/tn-ansible_tenant/ctx-ansible_vrf_1/pimctxp" + - nm_update_pim_setting.previous.0.pimCtxP.attributes.mtu == "1500" + - nm_update_pim_setting.previous.0.pimCtxP.attributes.ctrl == "" + - nm_update_pim_setting.previous.0.pimCtxP.children.0.pimSSMPatPol.children.0.pimSSMRangePol.attributes.name == "" + - nm_update_pim_setting.previous.0.pimCtxP.children.1.pimASMPatPol.children.0.pimSharedRangePol.attributes.name == "" + - nm_update_pim_setting.previous.0.pimCtxP.children.1.pimASMPatPol.children.1.pimSGRangeExpPol.attributes.sgExpItvl == "default-timeout" + - nm_update_pim_setting.previous.0.pimCtxP.children.1.pimASMPatPol.children.2.pimRegTrPol.attributes.maxRate == "65535" + - nm_update_pim_setting.previous.0.pimCtxP.children.1.pimASMPatPol.children.2.pimRegTrPol.attributes.srcIp == "0.0.0.0" + - nm_update_pim_setting.previous.0.pimCtxP.children.2.pimResPol.attributes.max == "unlimited" + - nm_update_pim_setting.previous.0.pimCtxP.children.2.pimResPol.attributes.rsvd == "undefined" + - nm_update_pim_setting_remove_control_state is changed + - nm_update_pim_setting_remove_control_state.current.0.pimCtxP.attributes.annotation == "orchestrator:ansible" + - nm_update_pim_setting_remove_control_state.current.0.pimCtxP.attributes.dn == "uni/tn-ansible_tenant/ctx-ansible_vrf_1/pimctxp" + - nm_update_pim_setting_remove_control_state.current.0.pimCtxP.attributes.mtu == "2000" + - nm_update_pim_setting_remove_control_state.current.0.pimCtxP.attributes.ctrl == "" + - nm_update_pim_setting_remove_control_state.current.0.pimCtxP.children.0.pimSSMPatPol.children.0.pimSSMRangePol.attributes.name == "" + - nm_update_pim_setting_remove_control_state.current.0.pimCtxP.children.1.pimASMPatPol.children.0.pimSharedRangePol.attributes.name == "" + - nm_update_pim_setting_remove_control_state.current.0.pimCtxP.children.1.pimASMPatPol.children.1.pimSGRangeExpPol.attributes.sgExpItvl == "default-timeout" + - nm_update_pim_setting_remove_control_state.current.0.pimCtxP.children.1.pimASMPatPol.children.2.pimRegTrPol.attributes.maxRate == "65535" + - nm_update_pim_setting_remove_control_state.current.0.pimCtxP.children.1.pimASMPatPol.children.2.pimRegTrPol.attributes.srcIp == "0.0.0.0" + - nm_update_pim_setting_remove_control_state.current.0.pimCtxP.children.2.pimResPol.attributes.max == "unlimited" + - nm_update_pim_setting_remove_control_state.current.0.pimCtxP.children.2.pimResPol.attributes.rsvd == "undefined" + - nm_update_pim_setting_remove_control_state.previous.0.pimCtxP.attributes.annotation == "orchestrator:ansible" + - nm_update_pim_setting_remove_control_state.previous.0.pimCtxP.attributes.dn == "uni/tn-ansible_tenant/ctx-ansible_vrf_1/pimctxp" + - nm_update_pim_setting_remove_control_state.previous.0.pimCtxP.attributes.mtu == "2000" + - nm_update_pim_setting_remove_control_state.previous.0.pimCtxP.attributes.ctrl == "fast-conv,strict-rfc-compliant" + - nm_update_pim_setting_remove_control_state.previous.0.pimCtxP.children.0.pimSSMPatPol.children.0.pimSSMRangePol.attributes.name == "" + - nm_update_pim_setting_remove_control_state.previous.0.pimCtxP.children.1.pimASMPatPol.children.0.pimSharedRangePol.attributes.name == "" + - nm_update_pim_setting_remove_control_state.previous.0.pimCtxP.children.1.pimASMPatPol.children.1.pimSGRangeExpPol.attributes.sgExpItvl == "default-timeout" + - nm_update_pim_setting_remove_control_state.previous.0.pimCtxP.children.1.pimASMPatPol.children.2.pimRegTrPol.attributes.maxRate == "65535" + - nm_update_pim_setting_remove_control_state.previous.0.pimCtxP.children.1.pimASMPatPol.children.2.pimRegTrPol.attributes.srcIp == "0.0.0.0" + - nm_update_pim_setting_remove_control_state.previous.0.pimCtxP.children.2.pimResPol.attributes.max == "unlimited" + - nm_update_pim_setting_remove_control_state.previous.0.pimCtxP.children.2.pimResPol.attributes.rsvd == "undefined" + +# UPDATE MULTICAST RESOURCE POLICY + +- name: Update resource policy on VRF 1 + cisco.aci.aci_vrf_multicast: + <<: *aci_ansible_vrf_1 + resource_policy: + maximum_limit: 100 + register: nm_update_resource_policy + +- name: Add a routemap to resource policy on VRF 1 + cisco.aci.aci_vrf_multicast: + <<: *aci_ansible_vrf_1 + resource_policy: + reserved_multicast_entries: 10 + reserved_route_map: uni/tn-ansible_test/rtmap-ansible_test + register: nm_update_resource_policy_add_route_map + +- name: Update maximum limit from resource policy with routemap on VRF 1 + cisco.aci.aci_vrf_multicast: + <<: *aci_ansible_vrf_1 + resource_policy: + maximum_limit: 50 + register: nm_update_resource_policy_with_route_map + +- name: Remove maximum limit from resource policy on VRF 1 + cisco.aci.aci_vrf_multicast: + <<: *aci_ansible_vrf_1 + resource_policy: + maximum_limit: 0 + register: nm_update_resource_policy_with_route_map_remove_maximum_limit + +- name: Update reserved multicast entries from resource policy on VRF 1 + cisco.aci.aci_vrf_multicast: + <<: *aci_ansible_vrf_1 + resource_policy: + reserved_multicast_entries: 20 + reserved_route_map: uni/tn-ansible_test/rtmap-ansible_test_changed + register: nm_update_resource_policy_change_reserved_multicast_entries + +- name: Remove a routemap from resource policy on VRF 1 + cisco.aci.aci_vrf_multicast: + <<: *aci_ansible_vrf_1 + resource_policy: + reserved_route_map: "" + register: nm_update_resource_policy_remove_route_map + +- name: Remove a routemap from resource policy on VRF 1 again + cisco.aci.aci_vrf_multicast: + <<: *aci_ansible_vrf_1 + resource_policy: + reserved_route_map: "" + register: nm_update_resource_policy_remove_route_map_again + +- name: Verify update resource policy on VRF 1 + ansible.builtin.assert: + that: + - nm_update_resource_policy is changed + - nm_update_resource_policy.current.0.pimCtxP.attributes.annotation == "orchestrator:ansible" + - nm_update_resource_policy.current.0.pimCtxP.attributes.dn == "uni/tn-ansible_tenant/ctx-ansible_vrf_1/pimctxp" + - nm_update_resource_policy.current.0.pimCtxP.attributes.mtu == "2000" + - nm_update_resource_policy.current.0.pimCtxP.attributes.ctrl == "" + - nm_update_resource_policy.current.0.pimCtxP.children.0.pimSSMPatPol.children.0.pimSSMRangePol.attributes.name == "" + - nm_update_resource_policy.current.0.pimCtxP.children.1.pimASMPatPol.children.0.pimSharedRangePol.attributes.name == "" + - nm_update_resource_policy.current.0.pimCtxP.children.1.pimASMPatPol.children.1.pimSGRangeExpPol.attributes.sgExpItvl == "default-timeout" + - nm_update_resource_policy.current.0.pimCtxP.children.1.pimASMPatPol.children.2.pimRegTrPol.attributes.maxRate == "65535" + - nm_update_resource_policy.current.0.pimCtxP.children.1.pimASMPatPol.children.2.pimRegTrPol.attributes.srcIp == "0.0.0.0" + - nm_update_resource_policy.current.0.pimCtxP.children.2.pimResPol.attributes.max == "100" + - nm_update_resource_policy.current.0.pimCtxP.children.2.pimResPol.attributes.rsvd == "undefined" + - nm_update_resource_policy.previous.0.pimCtxP.attributes.annotation == "orchestrator:ansible" + - nm_update_resource_policy.previous.0.pimCtxP.attributes.dn == "uni/tn-ansible_tenant/ctx-ansible_vrf_1/pimctxp" + - nm_update_resource_policy.previous.0.pimCtxP.attributes.mtu == "2000" + - nm_update_resource_policy.previous.0.pimCtxP.attributes.ctrl == "" + - nm_update_resource_policy.previous.0.pimCtxP.children.0.pimSSMPatPol.children.0.pimSSMRangePol.attributes.name == "" + - nm_update_resource_policy.previous.0.pimCtxP.children.1.pimASMPatPol.children.0.pimSharedRangePol.attributes.name == "" + - nm_update_resource_policy.previous.0.pimCtxP.children.1.pimASMPatPol.children.1.pimSGRangeExpPol.attributes.sgExpItvl == "default-timeout" + - nm_update_resource_policy.previous.0.pimCtxP.children.1.pimASMPatPol.children.2.pimRegTrPol.attributes.maxRate == "65535" + - nm_update_resource_policy.previous.0.pimCtxP.children.1.pimASMPatPol.children.2.pimRegTrPol.attributes.srcIp == "0.0.0.0" + - nm_update_resource_policy.previous.0.pimCtxP.children.2.pimResPol.attributes.max == "unlimited" + - nm_update_resource_policy.previous.0.pimCtxP.children.2.pimResPol.attributes.rsvd == "undefined" + - nm_update_resource_policy_add_route_map is changed + - nm_update_resource_policy_add_route_map.current.0.pimCtxP.attributes.annotation == "orchestrator:ansible" + - nm_update_resource_policy_add_route_map.current.0.pimCtxP.attributes.dn == "uni/tn-ansible_tenant/ctx-ansible_vrf_1/pimctxp" + - nm_update_resource_policy_add_route_map.current.0.pimCtxP.attributes.mtu == "2000" + - nm_update_resource_policy_add_route_map.current.0.pimCtxP.attributes.ctrl == "" + - nm_update_resource_policy_add_route_map.current.0.pimCtxP.children.0.pimSSMPatPol.children.0.pimSSMRangePol.attributes.name == "" + - nm_update_resource_policy_add_route_map.current.0.pimCtxP.children.1.pimASMPatPol.children.0.pimSharedRangePol.attributes.name == "" + - nm_update_resource_policy_add_route_map.current.0.pimCtxP.children.1.pimASMPatPol.children.1.pimSGRangeExpPol.attributes.sgExpItvl == "default-timeout" + - nm_update_resource_policy_add_route_map.current.0.pimCtxP.children.1.pimASMPatPol.children.2.pimRegTrPol.attributes.maxRate == "65535" + - nm_update_resource_policy_add_route_map.current.0.pimCtxP.children.1.pimASMPatPol.children.2.pimRegTrPol.attributes.srcIp == "0.0.0.0" + - nm_update_resource_policy_add_route_map.current.0.pimCtxP.children.2.pimResPol.attributes.max == "100" + - nm_update_resource_policy_add_route_map.current.0.pimCtxP.children.2.pimResPol.attributes.rsvd == "10" + - nm_update_resource_policy_add_route_map.current.0.pimCtxP.children.2.pimResPol.children.0.rtdmcRsFilterToRtMapPol.attributes.tDn == "uni/tn-ansible_test/rtmap-ansible_test" + - nm_update_resource_policy_add_route_map.previous.0.pimCtxP.attributes.annotation == "orchestrator:ansible" + - nm_update_resource_policy_add_route_map.previous.0.pimCtxP.attributes.dn == "uni/tn-ansible_tenant/ctx-ansible_vrf_1/pimctxp" + - nm_update_resource_policy_add_route_map.previous.0.pimCtxP.attributes.mtu == "2000" + - nm_update_resource_policy_add_route_map.previous.0.pimCtxP.attributes.ctrl == "" + - nm_update_resource_policy_add_route_map.previous.0.pimCtxP.children.0.pimSSMPatPol.children.0.pimSSMRangePol.attributes.name == "" + - nm_update_resource_policy_add_route_map.previous.0.pimCtxP.children.1.pimASMPatPol.children.0.pimSharedRangePol.attributes.name == "" + - nm_update_resource_policy_add_route_map.previous.0.pimCtxP.children.1.pimASMPatPol.children.1.pimSGRangeExpPol.attributes.sgExpItvl == "default-timeout" + - nm_update_resource_policy_add_route_map.previous.0.pimCtxP.children.1.pimASMPatPol.children.2.pimRegTrPol.attributes.maxRate == "65535" + - nm_update_resource_policy_add_route_map.previous.0.pimCtxP.children.1.pimASMPatPol.children.2.pimRegTrPol.attributes.srcIp == "0.0.0.0" + - nm_update_resource_policy_add_route_map.previous.0.pimCtxP.children.2.pimResPol.attributes.max == "100" + - nm_update_resource_policy_add_route_map.previous.0.pimCtxP.children.2.pimResPol.attributes.rsvd == "undefined" + - "'children' not in nm_update_resource_policy_add_route_map.previous.0.pimCtxP.children.2.pimResPol" + - nm_update_resource_policy_with_route_map is changed + - nm_update_resource_policy_with_route_map.current.0.pimCtxP.attributes.annotation == "orchestrator:ansible" + - nm_update_resource_policy_with_route_map.current.0.pimCtxP.attributes.dn == "uni/tn-ansible_tenant/ctx-ansible_vrf_1/pimctxp" + - nm_update_resource_policy_with_route_map.current.0.pimCtxP.attributes.mtu == "2000" + - nm_update_resource_policy_with_route_map.current.0.pimCtxP.attributes.ctrl == "" + - nm_update_resource_policy_with_route_map.current.0.pimCtxP.children.0.pimSSMPatPol.children.0.pimSSMRangePol.attributes.name == "" + - nm_update_resource_policy_with_route_map.current.0.pimCtxP.children.1.pimASMPatPol.children.0.pimSharedRangePol.attributes.name == "" + - nm_update_resource_policy_with_route_map.current.0.pimCtxP.children.1.pimASMPatPol.children.1.pimSGRangeExpPol.attributes.sgExpItvl == "default-timeout" + - nm_update_resource_policy_with_route_map.current.0.pimCtxP.children.1.pimASMPatPol.children.2.pimRegTrPol.attributes.maxRate == "65535" + - nm_update_resource_policy_with_route_map.current.0.pimCtxP.children.1.pimASMPatPol.children.2.pimRegTrPol.attributes.srcIp == "0.0.0.0" + - nm_update_resource_policy_with_route_map.current.0.pimCtxP.children.2.pimResPol.attributes.max == "50" + - nm_update_resource_policy_with_route_map.current.0.pimCtxP.children.2.pimResPol.attributes.rsvd == "10" + - nm_update_resource_policy_with_route_map.current.0.pimCtxP.children.2.pimResPol.children.0.rtdmcRsFilterToRtMapPol.attributes.tDn == "uni/tn-ansible_test/rtmap-ansible_test" + - nm_update_resource_policy_with_route_map.previous.0.pimCtxP.attributes.annotation == "orchestrator:ansible" + - nm_update_resource_policy_with_route_map.previous.0.pimCtxP.attributes.dn == "uni/tn-ansible_tenant/ctx-ansible_vrf_1/pimctxp" + - nm_update_resource_policy_with_route_map.previous.0.pimCtxP.attributes.mtu == "2000" + - nm_update_resource_policy_with_route_map.previous.0.pimCtxP.attributes.ctrl == "" + - nm_update_resource_policy_with_route_map.previous.0.pimCtxP.children.0.pimSSMPatPol.children.0.pimSSMRangePol.attributes.name == "" + - nm_update_resource_policy_with_route_map.previous.0.pimCtxP.children.1.pimASMPatPol.children.0.pimSharedRangePol.attributes.name == "" + - nm_update_resource_policy_with_route_map.previous.0.pimCtxP.children.1.pimASMPatPol.children.1.pimSGRangeExpPol.attributes.sgExpItvl == "default-timeout" + - nm_update_resource_policy_with_route_map.previous.0.pimCtxP.children.1.pimASMPatPol.children.2.pimRegTrPol.attributes.maxRate == "65535" + - nm_update_resource_policy_with_route_map.previous.0.pimCtxP.children.1.pimASMPatPol.children.2.pimRegTrPol.attributes.srcIp == "0.0.0.0" + - nm_update_resource_policy_with_route_map.previous.0.pimCtxP.children.2.pimResPol.attributes.max == "100" + - nm_update_resource_policy_with_route_map.previous.0.pimCtxP.children.2.pimResPol.attributes.rsvd == "10" + - nm_update_resource_policy_with_route_map.previous.0.pimCtxP.children.2.pimResPol.children.0.rtdmcRsFilterToRtMapPol.attributes.tDn == "uni/tn-ansible_test/rtmap-ansible_test" + - nm_update_resource_policy_with_route_map_remove_maximum_limit is changed + - nm_update_resource_policy_with_route_map_remove_maximum_limit.current.0.pimCtxP.attributes.annotation == "orchestrator:ansible" + - nm_update_resource_policy_with_route_map_remove_maximum_limit.current.0.pimCtxP.attributes.dn == "uni/tn-ansible_tenant/ctx-ansible_vrf_1/pimctxp" + - nm_update_resource_policy_with_route_map_remove_maximum_limit.current.0.pimCtxP.attributes.mtu == "2000" + - nm_update_resource_policy_with_route_map_remove_maximum_limit.current.0.pimCtxP.attributes.ctrl == "" + - nm_update_resource_policy_with_route_map_remove_maximum_limit.current.0.pimCtxP.children.0.pimSSMPatPol.children.0.pimSSMRangePol.attributes.name == "" + - nm_update_resource_policy_with_route_map_remove_maximum_limit.current.0.pimCtxP.children.1.pimASMPatPol.children.0.pimSharedRangePol.attributes.name == "" + - nm_update_resource_policy_with_route_map_remove_maximum_limit.current.0.pimCtxP.children.1.pimASMPatPol.children.1.pimSGRangeExpPol.attributes.sgExpItvl == "default-timeout" + - nm_update_resource_policy_with_route_map_remove_maximum_limit.current.0.pimCtxP.children.1.pimASMPatPol.children.2.pimRegTrPol.attributes.maxRate == "65535" + - nm_update_resource_policy_with_route_map_remove_maximum_limit.current.0.pimCtxP.children.1.pimASMPatPol.children.2.pimRegTrPol.attributes.srcIp == "0.0.0.0" + - nm_update_resource_policy_with_route_map_remove_maximum_limit.current.0.pimCtxP.children.2.pimResPol.attributes.max == "unlimited" + - nm_update_resource_policy_with_route_map_remove_maximum_limit.current.0.pimCtxP.children.2.pimResPol.attributes.rsvd == "10" + - nm_update_resource_policy_with_route_map_remove_maximum_limit.current.0.pimCtxP.children.2.pimResPol.children.0.rtdmcRsFilterToRtMapPol.attributes.tDn == "uni/tn-ansible_test/rtmap-ansible_test" + - nm_update_resource_policy_with_route_map_remove_maximum_limit.previous.0.pimCtxP.attributes.annotation == "orchestrator:ansible" + - nm_update_resource_policy_with_route_map_remove_maximum_limit.previous.0.pimCtxP.attributes.dn == "uni/tn-ansible_tenant/ctx-ansible_vrf_1/pimctxp" + - nm_update_resource_policy_with_route_map_remove_maximum_limit.previous.0.pimCtxP.attributes.mtu == "2000" + - nm_update_resource_policy_with_route_map_remove_maximum_limit.previous.0.pimCtxP.attributes.ctrl == "" + - nm_update_resource_policy_with_route_map_remove_maximum_limit.previous.0.pimCtxP.children.0.pimSSMPatPol.children.0.pimSSMRangePol.attributes.name == "" + - nm_update_resource_policy_with_route_map_remove_maximum_limit.previous.0.pimCtxP.children.1.pimASMPatPol.children.0.pimSharedRangePol.attributes.name == "" + - nm_update_resource_policy_with_route_map_remove_maximum_limit.previous.0.pimCtxP.children.1.pimASMPatPol.children.1.pimSGRangeExpPol.attributes.sgExpItvl == "default-timeout" + - nm_update_resource_policy_with_route_map_remove_maximum_limit.previous.0.pimCtxP.children.1.pimASMPatPol.children.2.pimRegTrPol.attributes.maxRate == "65535" + - nm_update_resource_policy_with_route_map_remove_maximum_limit.previous.0.pimCtxP.children.1.pimASMPatPol.children.2.pimRegTrPol.attributes.srcIp == "0.0.0.0" + - nm_update_resource_policy_with_route_map_remove_maximum_limit.previous.0.pimCtxP.children.2.pimResPol.attributes.max == "50" + - nm_update_resource_policy_with_route_map_remove_maximum_limit.previous.0.pimCtxP.children.2.pimResPol.attributes.rsvd == "10" + - nm_update_resource_policy_with_route_map_remove_maximum_limit.previous.0.pimCtxP.children.2.pimResPol.children.0.rtdmcRsFilterToRtMapPol.attributes.tDn == "uni/tn-ansible_test/rtmap-ansible_test" + - nm_update_resource_policy_change_reserved_multicast_entries is changed + - nm_update_resource_policy_change_reserved_multicast_entries.current.0.pimCtxP.attributes.annotation == "orchestrator:ansible" + - nm_update_resource_policy_change_reserved_multicast_entries.current.0.pimCtxP.attributes.dn == "uni/tn-ansible_tenant/ctx-ansible_vrf_1/pimctxp" + - nm_update_resource_policy_change_reserved_multicast_entries.current.0.pimCtxP.attributes.mtu == "2000" + - nm_update_resource_policy_change_reserved_multicast_entries.current.0.pimCtxP.attributes.ctrl == "" + - nm_update_resource_policy_change_reserved_multicast_entries.current.0.pimCtxP.children.0.pimSSMPatPol.children.0.pimSSMRangePol.attributes.name == "" + - nm_update_resource_policy_change_reserved_multicast_entries.current.0.pimCtxP.children.1.pimASMPatPol.children.0.pimSharedRangePol.attributes.name == "" + - nm_update_resource_policy_change_reserved_multicast_entries.current.0.pimCtxP.children.1.pimASMPatPol.children.1.pimSGRangeExpPol.attributes.sgExpItvl == "default-timeout" + - nm_update_resource_policy_change_reserved_multicast_entries.current.0.pimCtxP.children.1.pimASMPatPol.children.2.pimRegTrPol.attributes.maxRate == "65535" + - nm_update_resource_policy_change_reserved_multicast_entries.current.0.pimCtxP.children.1.pimASMPatPol.children.2.pimRegTrPol.attributes.srcIp == "0.0.0.0" + - nm_update_resource_policy_change_reserved_multicast_entries.current.0.pimCtxP.children.2.pimResPol.attributes.max == "unlimited" + - nm_update_resource_policy_change_reserved_multicast_entries.current.0.pimCtxP.children.2.pimResPol.attributes.rsvd == "20" + - nm_update_resource_policy_change_reserved_multicast_entries.current.0.pimCtxP.children.2.pimResPol.children.0.rtdmcRsFilterToRtMapPol.attributes.tDn == "uni/tn-ansible_test/rtmap-ansible_test_changed" + - nm_update_resource_policy_change_reserved_multicast_entries.previous.0.pimCtxP.attributes.annotation == "orchestrator:ansible" + - nm_update_resource_policy_change_reserved_multicast_entries.previous.0.pimCtxP.attributes.dn == "uni/tn-ansible_tenant/ctx-ansible_vrf_1/pimctxp" + - nm_update_resource_policy_change_reserved_multicast_entries.previous.0.pimCtxP.attributes.mtu == "2000" + - nm_update_resource_policy_change_reserved_multicast_entries.previous.0.pimCtxP.attributes.ctrl == "" + - nm_update_resource_policy_change_reserved_multicast_entries.previous.0.pimCtxP.children.0.pimSSMPatPol.children.0.pimSSMRangePol.attributes.name == "" + - nm_update_resource_policy_change_reserved_multicast_entries.previous.0.pimCtxP.children.1.pimASMPatPol.children.0.pimSharedRangePol.attributes.name == "" + - nm_update_resource_policy_change_reserved_multicast_entries.previous.0.pimCtxP.children.1.pimASMPatPol.children.1.pimSGRangeExpPol.attributes.sgExpItvl == "default-timeout" + - nm_update_resource_policy_change_reserved_multicast_entries.previous.0.pimCtxP.children.1.pimASMPatPol.children.2.pimRegTrPol.attributes.maxRate == "65535" + - nm_update_resource_policy_change_reserved_multicast_entries.previous.0.pimCtxP.children.1.pimASMPatPol.children.2.pimRegTrPol.attributes.srcIp == "0.0.0.0" + - nm_update_resource_policy_change_reserved_multicast_entries.previous.0.pimCtxP.children.2.pimResPol.attributes.max == "unlimited" + - nm_update_resource_policy_change_reserved_multicast_entries.previous.0.pimCtxP.children.2.pimResPol.attributes.rsvd == "10" + - nm_update_resource_policy_change_reserved_multicast_entries.previous.0.pimCtxP.children.2.pimResPol.children.0.rtdmcRsFilterToRtMapPol.attributes.tDn == "uni/tn-ansible_test/rtmap-ansible_test" + - nm_update_resource_policy_remove_route_map is changed + - nm_update_resource_policy_remove_route_map.current.0.pimCtxP.attributes.annotation == "orchestrator:ansible" + - nm_update_resource_policy_remove_route_map.current.0.pimCtxP.attributes.dn == "uni/tn-ansible_tenant/ctx-ansible_vrf_1/pimctxp" + - nm_update_resource_policy_remove_route_map.current.0.pimCtxP.attributes.mtu == "2000" + - nm_update_resource_policy_remove_route_map.current.0.pimCtxP.attributes.ctrl == "" + - nm_update_resource_policy_remove_route_map.current.0.pimCtxP.children.0.pimSSMPatPol.children.0.pimSSMRangePol.attributes.name == "" + - nm_update_resource_policy_remove_route_map.current.0.pimCtxP.children.1.pimASMPatPol.children.0.pimSharedRangePol.attributes.name == "" + - nm_update_resource_policy_remove_route_map.current.0.pimCtxP.children.1.pimASMPatPol.children.1.pimSGRangeExpPol.attributes.sgExpItvl == "default-timeout" + - nm_update_resource_policy_remove_route_map.current.0.pimCtxP.children.1.pimASMPatPol.children.2.pimRegTrPol.attributes.maxRate == "65535" + - nm_update_resource_policy_remove_route_map.current.0.pimCtxP.children.1.pimASMPatPol.children.2.pimRegTrPol.attributes.srcIp == "0.0.0.0" + - nm_update_resource_policy_remove_route_map.current.0.pimCtxP.children.2.pimResPol.attributes.max == "unlimited" + - nm_update_resource_policy_remove_route_map.current.0.pimCtxP.children.2.pimResPol.attributes.rsvd == "undefined" + - "'children' not in nm_update_resource_policy_remove_route_map.current.0.pimCtxP.children.2.pimResPol" + - nm_update_resource_policy_remove_route_map.previous.0.pimCtxP.attributes.annotation == "orchestrator:ansible" + - nm_update_resource_policy_remove_route_map.previous.0.pimCtxP.attributes.dn == "uni/tn-ansible_tenant/ctx-ansible_vrf_1/pimctxp" + - nm_update_resource_policy_remove_route_map.previous.0.pimCtxP.attributes.mtu == "2000" + - nm_update_resource_policy_remove_route_map.previous.0.pimCtxP.attributes.ctrl == "" + - nm_update_resource_policy_remove_route_map.previous.0.pimCtxP.children.0.pimSSMPatPol.children.0.pimSSMRangePol.attributes.name == "" + - nm_update_resource_policy_remove_route_map.previous.0.pimCtxP.children.1.pimASMPatPol.children.0.pimSharedRangePol.attributes.name == "" + - nm_update_resource_policy_remove_route_map.previous.0.pimCtxP.children.1.pimASMPatPol.children.1.pimSGRangeExpPol.attributes.sgExpItvl == "default-timeout" + - nm_update_resource_policy_remove_route_map.previous.0.pimCtxP.children.1.pimASMPatPol.children.2.pimRegTrPol.attributes.maxRate == "65535" + - nm_update_resource_policy_remove_route_map.previous.0.pimCtxP.children.1.pimASMPatPol.children.2.pimRegTrPol.attributes.srcIp == "0.0.0.0" + - nm_update_resource_policy_remove_route_map.previous.0.pimCtxP.children.2.pimResPol.attributes.max == "unlimited" + - nm_update_resource_policy_remove_route_map.previous.0.pimCtxP.children.2.pimResPol.attributes.rsvd == "20" + - nm_update_resource_policy_remove_route_map.previous.0.pimCtxP.children.2.pimResPol.children.0.rtdmcRsFilterToRtMapPol.attributes.tDn == "uni/tn-ansible_test/rtmap-ansible_test_changed" + - nm_update_resource_policy_remove_route_map_again is not changed + +# UPDATE MULTICAST ASM + +- name: Add a shared range routemap to any source multicast on VRF 1 + cisco.aci.aci_vrf_multicast: + <<: *aci_ansible_vrf_1 + any_source_multicast: + shared_range_route_map: uni/tn-ansible_test/rtmap-ansible_test + register: nm_update_any_source_multicast_add_shared_range_route_map + +- name: Remove a shared range routemap from any source multicast on VRF 1 + cisco.aci.aci_vrf_multicast: + <<: *aci_ansible_vrf_1 + any_source_multicast: + shared_range_route_map: "" + register: nm_update_any_source_multicast_remove_shared_range_route_map + +- name: Remove a shared range routemap from any source multicast on VRF 1 again + cisco.aci.aci_vrf_multicast: + <<: *aci_ansible_vrf_1 + any_source_multicast: + shared_range_route_map: "" + register: nm_update_any_source_multicast_remove_shared_range_route_map_again + +- name: Update expiry seconds for any source multicast on VRF 1 + cisco.aci.aci_vrf_multicast: + <<: *aci_ansible_vrf_1 + any_source_multicast: + expiry: 500 + register: nm_update_any_source_multicast_expiry_seconds + +- name: Remove expiry seconds for any source multicast on VRF 1 + cisco.aci.aci_vrf_multicast: + <<: *aci_ansible_vrf_1 + any_source_multicast: + expiry: 0 + register: nm_update_any_source_multicast_remove_expiry_seconds + +- name: Add a source group expiry routemap to any source multicast on VRF 1 + cisco.aci.aci_vrf_multicast: + <<: *aci_ansible_vrf_1 + any_source_multicast: + source_group_expiry_route_map: uni/tn-ansible_test/rtmap-ansible_test + register: nm_update_any_source_multicast_add_source_group_expiry_route_map + +- name: Remove a source group expiry routemap from any source multicast on VRF 1 + cisco.aci.aci_vrf_multicast: + <<: *aci_ansible_vrf_1 + any_source_multicast: + source_group_expiry_route_map: "" + register: nm_update_any_source_multicast_remove_source_group_expiry_route_map + +- name: Remove a source group expiry routemap from any source multicast on VRF 1 again + cisco.aci.aci_vrf_multicast: + <<: *aci_ansible_vrf_1 + any_source_multicast: + source_group_expiry_route_map: "" + register: nm_update_any_source_multicast_remove_source_group_expiry_route_map_again + +- name: Update max rate for any source multicast on VRF 1 + cisco.aci.aci_vrf_multicast: + <<: *aci_ansible_vrf_1 + any_source_multicast: + max_rate: 64000 + register: nm_update_any_source_multicast_max_rate + +- name: Remove max rate for any source multicast on VRF 1 + cisco.aci.aci_vrf_multicast: + <<: *aci_ansible_vrf_1 + any_source_multicast: + source_ip: 1.1.1.1 + register: nm_update_any_source_multicast_ip + +- name: Verify update any source multicast on VRF 1 + ansible.builtin.assert: + that: + - nm_update_any_source_multicast_add_shared_range_route_map is changed + - nm_update_any_source_multicast_add_shared_range_route_map.current.0.pimCtxP.attributes.annotation == "orchestrator:ansible" + - nm_update_any_source_multicast_add_shared_range_route_map.current.0.pimCtxP.attributes.dn == "uni/tn-ansible_tenant/ctx-ansible_vrf_1/pimctxp" + - nm_update_any_source_multicast_add_shared_range_route_map.current.0.pimCtxP.attributes.mtu == "2000" + - nm_update_any_source_multicast_add_shared_range_route_map.current.0.pimCtxP.attributes.ctrl == "" + - nm_update_any_source_multicast_add_shared_range_route_map.current.0.pimCtxP.children.0.pimSSMPatPol.children.0.pimSSMRangePol.attributes.name == "" + - nm_update_any_source_multicast_add_shared_range_route_map.current.0.pimCtxP.children.1.pimASMPatPol.children.0.pimSharedRangePol.attributes.name == "" + - nm_update_any_source_multicast_add_shared_range_route_map.current.0.pimCtxP.children.1.pimASMPatPol.children.0.pimSharedRangePol.children.0.rtdmcRsFilterToRtMapPol.attributes.tDn == "uni/tn-ansible_test/rtmap-ansible_test" + - nm_update_any_source_multicast_add_shared_range_route_map.current.0.pimCtxP.children.1.pimASMPatPol.children.1.pimSGRangeExpPol.attributes.sgExpItvl == "default-timeout" + - nm_update_any_source_multicast_add_shared_range_route_map.current.0.pimCtxP.children.1.pimASMPatPol.children.2.pimRegTrPol.attributes.maxRate == "65535" + - nm_update_any_source_multicast_add_shared_range_route_map.current.0.pimCtxP.children.1.pimASMPatPol.children.2.pimRegTrPol.attributes.srcIp == "0.0.0.0" + - nm_update_any_source_multicast_add_shared_range_route_map.current.0.pimCtxP.children.2.pimResPol.attributes.max == "unlimited" + - nm_update_any_source_multicast_add_shared_range_route_map.current.0.pimCtxP.children.2.pimResPol.attributes.rsvd == "undefined" + - nm_update_any_source_multicast_add_shared_range_route_map.previous.0.pimCtxP.attributes.annotation == "orchestrator:ansible" + - nm_update_any_source_multicast_add_shared_range_route_map.previous.0.pimCtxP.attributes.dn == "uni/tn-ansible_tenant/ctx-ansible_vrf_1/pimctxp" + - nm_update_any_source_multicast_add_shared_range_route_map.previous.0.pimCtxP.attributes.mtu == "2000" + - nm_update_any_source_multicast_add_shared_range_route_map.previous.0.pimCtxP.attributes.ctrl == "" + - nm_update_any_source_multicast_add_shared_range_route_map.previous.0.pimCtxP.children.0.pimSSMPatPol.children.0.pimSSMRangePol.attributes.name == "" + - nm_update_any_source_multicast_add_shared_range_route_map.previous.0.pimCtxP.children.1.pimASMPatPol.children.0.pimSharedRangePol.attributes.name == "" + - "'children' not in nm_update_any_source_multicast_remove_shared_range_route_map.current.0.pimCtxP.children.1.pimASMPatPol.children.0.pimSharedRangePol" + - nm_update_any_source_multicast_add_shared_range_route_map.previous.0.pimCtxP.children.1.pimASMPatPol.children.1.pimSGRangeExpPol.attributes.sgExpItvl == "default-timeout" + - nm_update_any_source_multicast_add_shared_range_route_map.previous.0.pimCtxP.children.1.pimASMPatPol.children.2.pimRegTrPol.attributes.maxRate == "65535" + - nm_update_any_source_multicast_add_shared_range_route_map.previous.0.pimCtxP.children.1.pimASMPatPol.children.2.pimRegTrPol.attributes.srcIp == "0.0.0.0" + - nm_update_any_source_multicast_add_shared_range_route_map.previous.0.pimCtxP.children.2.pimResPol.attributes.max == "unlimited" + - nm_update_any_source_multicast_add_shared_range_route_map.previous.0.pimCtxP.children.2.pimResPol.attributes.rsvd == "undefined" + - nm_update_any_source_multicast_remove_shared_range_route_map is changed + - nm_update_any_source_multicast_remove_shared_range_route_map.current.0.pimCtxP.attributes.annotation == "orchestrator:ansible" + - nm_update_any_source_multicast_remove_shared_range_route_map.current.0.pimCtxP.attributes.dn == "uni/tn-ansible_tenant/ctx-ansible_vrf_1/pimctxp" + - nm_update_any_source_multicast_remove_shared_range_route_map.current.0.pimCtxP.attributes.mtu == "2000" + - nm_update_any_source_multicast_remove_shared_range_route_map.current.0.pimCtxP.attributes.ctrl == "" + - nm_update_any_source_multicast_remove_shared_range_route_map.current.0.pimCtxP.children.0.pimSSMPatPol.children.0.pimSSMRangePol.attributes.name == "" + - nm_update_any_source_multicast_remove_shared_range_route_map.current.0.pimCtxP.children.1.pimASMPatPol.children.0.pimSharedRangePol.attributes.name == "" + - "'children' not in nm_update_any_source_multicast_remove_shared_range_route_map.current.0.pimCtxP.children.1.pimASMPatPol.children.0.pimSharedRangePol" + - nm_update_any_source_multicast_remove_shared_range_route_map.current.0.pimCtxP.children.1.pimASMPatPol.children.1.pimSGRangeExpPol.attributes.sgExpItvl == "default-timeout" + - nm_update_any_source_multicast_remove_shared_range_route_map.current.0.pimCtxP.children.1.pimASMPatPol.children.2.pimRegTrPol.attributes.maxRate == "65535" + - nm_update_any_source_multicast_remove_shared_range_route_map.current.0.pimCtxP.children.1.pimASMPatPol.children.2.pimRegTrPol.attributes.srcIp == "0.0.0.0" + - nm_update_any_source_multicast_remove_shared_range_route_map.current.0.pimCtxP.children.2.pimResPol.attributes.max == "unlimited" + - nm_update_any_source_multicast_remove_shared_range_route_map.current.0.pimCtxP.children.2.pimResPol.attributes.rsvd == "undefined" + - nm_update_any_source_multicast_remove_shared_range_route_map.previous.0.pimCtxP.attributes.annotation == "orchestrator:ansible" + - nm_update_any_source_multicast_remove_shared_range_route_map.previous.0.pimCtxP.attributes.dn == "uni/tn-ansible_tenant/ctx-ansible_vrf_1/pimctxp" + - nm_update_any_source_multicast_remove_shared_range_route_map.previous.0.pimCtxP.attributes.mtu == "2000" + - nm_update_any_source_multicast_remove_shared_range_route_map.previous.0.pimCtxP.attributes.ctrl == "" + - nm_update_any_source_multicast_remove_shared_range_route_map.previous.0.pimCtxP.children.0.pimSSMPatPol.children.0.pimSSMRangePol.attributes.name == "" + - nm_update_any_source_multicast_remove_shared_range_route_map.previous.0.pimCtxP.children.1.pimASMPatPol.children.0.pimSharedRangePol.attributes.name == "" + - nm_update_any_source_multicast_remove_shared_range_route_map.previous.0.pimCtxP.children.1.pimASMPatPol.children.0.pimSharedRangePol.children.0.rtdmcRsFilterToRtMapPol.attributes.tDn == "uni/tn-ansible_test/rtmap-ansible_test" + - nm_update_any_source_multicast_remove_shared_range_route_map.previous.0.pimCtxP.children.1.pimASMPatPol.children.1.pimSGRangeExpPol.attributes.sgExpItvl == "default-timeout" + - nm_update_any_source_multicast_remove_shared_range_route_map.previous.0.pimCtxP.children.1.pimASMPatPol.children.2.pimRegTrPol.attributes.maxRate == "65535" + - nm_update_any_source_multicast_remove_shared_range_route_map.previous.0.pimCtxP.children.1.pimASMPatPol.children.2.pimRegTrPol.attributes.srcIp == "0.0.0.0" + - nm_update_any_source_multicast_remove_shared_range_route_map.previous.0.pimCtxP.children.2.pimResPol.attributes.max == "unlimited" + - nm_update_any_source_multicast_remove_shared_range_route_map.previous.0.pimCtxP.children.2.pimResPol.attributes.rsvd == "undefined" + - nm_update_any_source_multicast_remove_shared_range_route_map_again is not changed + - nm_update_any_source_multicast_expiry_seconds is changed + - nm_update_any_source_multicast_expiry_seconds.current.0.pimCtxP.attributes.annotation == "orchestrator:ansible" + - nm_update_any_source_multicast_expiry_seconds.current.0.pimCtxP.attributes.dn == "uni/tn-ansible_tenant/ctx-ansible_vrf_1/pimctxp" + - nm_update_any_source_multicast_expiry_seconds.current.0.pimCtxP.attributes.mtu == "2000" + - nm_update_any_source_multicast_expiry_seconds.current.0.pimCtxP.attributes.ctrl == "" + - nm_update_any_source_multicast_expiry_seconds.current.0.pimCtxP.children.0.pimSSMPatPol.children.0.pimSSMRangePol.attributes.name == "" + - nm_update_any_source_multicast_expiry_seconds.current.0.pimCtxP.children.1.pimASMPatPol.children.0.pimSharedRangePol.attributes.name == "" + - nm_update_any_source_multicast_expiry_seconds.current.0.pimCtxP.children.1.pimASMPatPol.children.1.pimSGRangeExpPol.attributes.sgExpItvl == "500" + - nm_update_any_source_multicast_expiry_seconds.current.0.pimCtxP.children.1.pimASMPatPol.children.2.pimRegTrPol.attributes.maxRate == "65535" + - nm_update_any_source_multicast_expiry_seconds.current.0.pimCtxP.children.1.pimASMPatPol.children.2.pimRegTrPol.attributes.srcIp == "0.0.0.0" + - nm_update_any_source_multicast_expiry_seconds.current.0.pimCtxP.children.2.pimResPol.attributes.max == "unlimited" + - nm_update_any_source_multicast_expiry_seconds.current.0.pimCtxP.children.2.pimResPol.attributes.rsvd == "undefined" + - nm_update_any_source_multicast_expiry_seconds.previous.0.pimCtxP.attributes.annotation == "orchestrator:ansible" + - nm_update_any_source_multicast_expiry_seconds.previous.0.pimCtxP.attributes.dn == "uni/tn-ansible_tenant/ctx-ansible_vrf_1/pimctxp" + - nm_update_any_source_multicast_expiry_seconds.previous.0.pimCtxP.attributes.mtu == "2000" + - nm_update_any_source_multicast_expiry_seconds.previous.0.pimCtxP.attributes.ctrl == "" + - nm_update_any_source_multicast_expiry_seconds.previous.0.pimCtxP.children.0.pimSSMPatPol.children.0.pimSSMRangePol.attributes.name == "" + - nm_update_any_source_multicast_expiry_seconds.previous.0.pimCtxP.children.1.pimASMPatPol.children.0.pimSharedRangePol.attributes.name == "" + - nm_update_any_source_multicast_expiry_seconds.previous.0.pimCtxP.children.1.pimASMPatPol.children.1.pimSGRangeExpPol.attributes.sgExpItvl == "default-timeout" + - nm_update_any_source_multicast_expiry_seconds.previous.0.pimCtxP.children.1.pimASMPatPol.children.2.pimRegTrPol.attributes.maxRate == "65535" + - nm_update_any_source_multicast_expiry_seconds.previous.0.pimCtxP.children.1.pimASMPatPol.children.2.pimRegTrPol.attributes.srcIp == "0.0.0.0" + - nm_update_any_source_multicast_expiry_seconds.previous.0.pimCtxP.children.2.pimResPol.attributes.max == "unlimited" + - nm_update_any_source_multicast_expiry_seconds.previous.0.pimCtxP.children.2.pimResPol.attributes.rsvd == "undefined" + - nm_update_any_source_multicast_remove_expiry_seconds is changed + - nm_update_any_source_multicast_remove_expiry_seconds.current.0.pimCtxP.attributes.annotation == "orchestrator:ansible" + - nm_update_any_source_multicast_remove_expiry_seconds.current.0.pimCtxP.attributes.dn == "uni/tn-ansible_tenant/ctx-ansible_vrf_1/pimctxp" + - nm_update_any_source_multicast_remove_expiry_seconds.current.0.pimCtxP.attributes.mtu == "2000" + - nm_update_any_source_multicast_remove_expiry_seconds.current.0.pimCtxP.attributes.ctrl == "" + - nm_update_any_source_multicast_remove_expiry_seconds.current.0.pimCtxP.children.0.pimSSMPatPol.children.0.pimSSMRangePol.attributes.name == "" + - nm_update_any_source_multicast_remove_expiry_seconds.current.0.pimCtxP.children.1.pimASMPatPol.children.0.pimSharedRangePol.attributes.name == "" + - nm_update_any_source_multicast_remove_expiry_seconds.current.0.pimCtxP.children.1.pimASMPatPol.children.1.pimSGRangeExpPol.attributes.sgExpItvl == "default-timeout" + - nm_update_any_source_multicast_remove_expiry_seconds.current.0.pimCtxP.children.1.pimASMPatPol.children.2.pimRegTrPol.attributes.maxRate == "65535" + - nm_update_any_source_multicast_remove_expiry_seconds.current.0.pimCtxP.children.1.pimASMPatPol.children.2.pimRegTrPol.attributes.srcIp == "0.0.0.0" + - nm_update_any_source_multicast_remove_expiry_seconds.current.0.pimCtxP.children.2.pimResPol.attributes.max == "unlimited" + - nm_update_any_source_multicast_remove_expiry_seconds.current.0.pimCtxP.children.2.pimResPol.attributes.rsvd == "undefined" + - nm_update_any_source_multicast_remove_expiry_seconds.previous.0.pimCtxP.attributes.annotation == "orchestrator:ansible" + - nm_update_any_source_multicast_remove_expiry_seconds.previous.0.pimCtxP.attributes.dn == "uni/tn-ansible_tenant/ctx-ansible_vrf_1/pimctxp" + - nm_update_any_source_multicast_remove_expiry_seconds.previous.0.pimCtxP.attributes.mtu == "2000" + - nm_update_any_source_multicast_remove_expiry_seconds.previous.0.pimCtxP.attributes.ctrl == "" + - nm_update_any_source_multicast_remove_expiry_seconds.previous.0.pimCtxP.children.0.pimSSMPatPol.children.0.pimSSMRangePol.attributes.name == "" + - nm_update_any_source_multicast_remove_expiry_seconds.previous.0.pimCtxP.children.1.pimASMPatPol.children.0.pimSharedRangePol.attributes.name == "" + - nm_update_any_source_multicast_remove_expiry_seconds.previous.0.pimCtxP.children.1.pimASMPatPol.children.1.pimSGRangeExpPol.attributes.sgExpItvl == "500" + - nm_update_any_source_multicast_remove_expiry_seconds.previous.0.pimCtxP.children.1.pimASMPatPol.children.2.pimRegTrPol.attributes.maxRate == "65535" + - nm_update_any_source_multicast_remove_expiry_seconds.previous.0.pimCtxP.children.1.pimASMPatPol.children.2.pimRegTrPol.attributes.srcIp == "0.0.0.0" + - nm_update_any_source_multicast_remove_expiry_seconds.previous.0.pimCtxP.children.2.pimResPol.attributes.max == "unlimited" + - nm_update_any_source_multicast_remove_expiry_seconds.previous.0.pimCtxP.children.2.pimResPol.attributes.rsvd == "undefined" + - nm_update_any_source_multicast_add_source_group_expiry_route_map is changed + - nm_update_any_source_multicast_add_source_group_expiry_route_map.current.0.pimCtxP.attributes.annotation == "orchestrator:ansible" + - nm_update_any_source_multicast_add_source_group_expiry_route_map.current.0.pimCtxP.attributes.dn == "uni/tn-ansible_tenant/ctx-ansible_vrf_1/pimctxp" + - nm_update_any_source_multicast_add_source_group_expiry_route_map.current.0.pimCtxP.attributes.mtu == "2000" + - nm_update_any_source_multicast_add_source_group_expiry_route_map.current.0.pimCtxP.attributes.ctrl == "" + - nm_update_any_source_multicast_add_source_group_expiry_route_map.current.0.pimCtxP.children.0.pimSSMPatPol.children.0.pimSSMRangePol.attributes.name == "" + - nm_update_any_source_multicast_add_source_group_expiry_route_map.current.0.pimCtxP.children.1.pimASMPatPol.children.0.pimSharedRangePol.attributes.name == "" + - nm_update_any_source_multicast_add_source_group_expiry_route_map.current.0.pimCtxP.children.1.pimASMPatPol.children.1.pimSGRangeExpPol.attributes.sgExpItvl == "default-timeout" + - nm_update_any_source_multicast_add_source_group_expiry_route_map.current.0.pimCtxP.children.1.pimASMPatPol.children.1.pimSGRangeExpPol.children.0.rtdmcRsFilterToRtMapPol.attributes.tDn == "uni/tn-ansible_test/rtmap-ansible_test" + - nm_update_any_source_multicast_add_source_group_expiry_route_map.current.0.pimCtxP.children.1.pimASMPatPol.children.2.pimRegTrPol.attributes.maxRate == "65535" + - nm_update_any_source_multicast_add_source_group_expiry_route_map.current.0.pimCtxP.children.1.pimASMPatPol.children.2.pimRegTrPol.attributes.srcIp == "0.0.0.0" + - nm_update_any_source_multicast_add_source_group_expiry_route_map.current.0.pimCtxP.children.2.pimResPol.attributes.max == "unlimited" + - nm_update_any_source_multicast_add_source_group_expiry_route_map.current.0.pimCtxP.children.2.pimResPol.attributes.rsvd == "undefined" + - nm_update_any_source_multicast_add_source_group_expiry_route_map.previous.0.pimCtxP.attributes.annotation == "orchestrator:ansible" + - nm_update_any_source_multicast_add_source_group_expiry_route_map.previous.0.pimCtxP.attributes.dn == "uni/tn-ansible_tenant/ctx-ansible_vrf_1/pimctxp" + - nm_update_any_source_multicast_add_source_group_expiry_route_map.previous.0.pimCtxP.attributes.mtu == "2000" + - nm_update_any_source_multicast_add_source_group_expiry_route_map.previous.0.pimCtxP.attributes.ctrl == "" + - nm_update_any_source_multicast_add_source_group_expiry_route_map.previous.0.pimCtxP.children.0.pimSSMPatPol.children.0.pimSSMRangePol.attributes.name == "" + - nm_update_any_source_multicast_add_source_group_expiry_route_map.previous.0.pimCtxP.children.1.pimASMPatPol.children.0.pimSharedRangePol.attributes.name == "" + - nm_update_any_source_multicast_add_source_group_expiry_route_map.previous.0.pimCtxP.children.1.pimASMPatPol.children.1.pimSGRangeExpPol.attributes.sgExpItvl == "default-timeout" + - "'children' not in nm_update_any_source_multicast_add_source_group_expiry_route_map.previous.0.pimCtxP.children.1.pimASMPatPol.children.1.pimSGRangeExpPol" + - nm_update_any_source_multicast_add_source_group_expiry_route_map.previous.0.pimCtxP.children.1.pimASMPatPol.children.2.pimRegTrPol.attributes.maxRate == "65535" + - nm_update_any_source_multicast_add_source_group_expiry_route_map.previous.0.pimCtxP.children.1.pimASMPatPol.children.2.pimRegTrPol.attributes.srcIp == "0.0.0.0" + - nm_update_any_source_multicast_add_source_group_expiry_route_map.previous.0.pimCtxP.children.2.pimResPol.attributes.max == "unlimited" + - nm_update_any_source_multicast_add_source_group_expiry_route_map.previous.0.pimCtxP.children.2.pimResPol.attributes.rsvd == "undefined" + - nm_update_any_source_multicast_remove_source_group_expiry_route_map is changed + - nm_update_any_source_multicast_remove_source_group_expiry_route_map.current.0.pimCtxP.attributes.annotation == "orchestrator:ansible" + - nm_update_any_source_multicast_remove_source_group_expiry_route_map.current.0.pimCtxP.attributes.dn == "uni/tn-ansible_tenant/ctx-ansible_vrf_1/pimctxp" + - nm_update_any_source_multicast_remove_source_group_expiry_route_map.current.0.pimCtxP.attributes.mtu == "2000" + - nm_update_any_source_multicast_remove_source_group_expiry_route_map.current.0.pimCtxP.attributes.ctrl == "" + - nm_update_any_source_multicast_remove_source_group_expiry_route_map.current.0.pimCtxP.children.0.pimSSMPatPol.children.0.pimSSMRangePol.attributes.name == "" + - nm_update_any_source_multicast_remove_source_group_expiry_route_map.current.0.pimCtxP.children.1.pimASMPatPol.children.0.pimSharedRangePol.attributes.name == "" + - nm_update_any_source_multicast_remove_source_group_expiry_route_map.current.0.pimCtxP.children.1.pimASMPatPol.children.1.pimSGRangeExpPol.attributes.sgExpItvl == "default-timeout" + - "'children' not in nm_update_any_source_multicast_remove_source_group_expiry_route_map.current.0.pimCtxP.children.1.pimASMPatPol.children.1.pimSGRangeExpPol" + - nm_update_any_source_multicast_remove_source_group_expiry_route_map.current.0.pimCtxP.children.1.pimASMPatPol.children.2.pimRegTrPol.attributes.maxRate == "65535" + - nm_update_any_source_multicast_remove_source_group_expiry_route_map.current.0.pimCtxP.children.1.pimASMPatPol.children.2.pimRegTrPol.attributes.srcIp == "0.0.0.0" + - nm_update_any_source_multicast_remove_source_group_expiry_route_map.current.0.pimCtxP.children.2.pimResPol.attributes.max == "unlimited" + - nm_update_any_source_multicast_remove_source_group_expiry_route_map.current.0.pimCtxP.children.2.pimResPol.attributes.rsvd == "undefined" + - nm_update_any_source_multicast_remove_source_group_expiry_route_map.previous.0.pimCtxP.attributes.annotation == "orchestrator:ansible" + - nm_update_any_source_multicast_remove_source_group_expiry_route_map.previous.0.pimCtxP.attributes.dn == "uni/tn-ansible_tenant/ctx-ansible_vrf_1/pimctxp" + - nm_update_any_source_multicast_remove_source_group_expiry_route_map.previous.0.pimCtxP.attributes.mtu == "2000" + - nm_update_any_source_multicast_remove_source_group_expiry_route_map.previous.0.pimCtxP.attributes.ctrl == "" + - nm_update_any_source_multicast_remove_source_group_expiry_route_map.previous.0.pimCtxP.children.0.pimSSMPatPol.children.0.pimSSMRangePol.attributes.name == "" + - nm_update_any_source_multicast_remove_source_group_expiry_route_map.previous.0.pimCtxP.children.1.pimASMPatPol.children.0.pimSharedRangePol.attributes.name == "" + - nm_update_any_source_multicast_remove_source_group_expiry_route_map.previous.0.pimCtxP.children.1.pimASMPatPol.children.1.pimSGRangeExpPol.attributes.sgExpItvl == "default-timeout" + - nm_update_any_source_multicast_remove_source_group_expiry_route_map.previous.0.pimCtxP.children.1.pimASMPatPol.children.1.pimSGRangeExpPol.children.0.rtdmcRsFilterToRtMapPol.attributes.tDn == "uni/tn-ansible_test/rtmap-ansible_test" + - nm_update_any_source_multicast_remove_source_group_expiry_route_map.previous.0.pimCtxP.children.1.pimASMPatPol.children.2.pimRegTrPol.attributes.maxRate == "65535" + - nm_update_any_source_multicast_remove_source_group_expiry_route_map.previous.0.pimCtxP.children.1.pimASMPatPol.children.2.pimRegTrPol.attributes.srcIp == "0.0.0.0" + - nm_update_any_source_multicast_remove_source_group_expiry_route_map.previous.0.pimCtxP.children.2.pimResPol.attributes.max == "unlimited" + - nm_update_any_source_multicast_remove_source_group_expiry_route_map.previous.0.pimCtxP.children.2.pimResPol.attributes.rsvd == "undefined" + - nm_update_any_source_multicast_remove_source_group_expiry_route_map_again is not changed + - nm_update_any_source_multicast_max_rate is changed + - nm_update_any_source_multicast_max_rate.current.0.pimCtxP.attributes.annotation == "orchestrator:ansible" + - nm_update_any_source_multicast_max_rate.current.0.pimCtxP.attributes.dn == "uni/tn-ansible_tenant/ctx-ansible_vrf_1/pimctxp" + - nm_update_any_source_multicast_max_rate.current.0.pimCtxP.attributes.mtu == "2000" + - nm_update_any_source_multicast_max_rate.current.0.pimCtxP.attributes.ctrl == "" + - nm_update_any_source_multicast_max_rate.current.0.pimCtxP.children.0.pimSSMPatPol.children.0.pimSSMRangePol.attributes.name == "" + - nm_update_any_source_multicast_max_rate.current.0.pimCtxP.children.1.pimASMPatPol.children.0.pimSharedRangePol.attributes.name == "" + - nm_update_any_source_multicast_max_rate.current.0.pimCtxP.children.1.pimASMPatPol.children.1.pimSGRangeExpPol.attributes.sgExpItvl == "default-timeout" + - nm_update_any_source_multicast_max_rate.current.0.pimCtxP.children.1.pimASMPatPol.children.2.pimRegTrPol.attributes.maxRate == "64000" + - nm_update_any_source_multicast_max_rate.current.0.pimCtxP.children.1.pimASMPatPol.children.2.pimRegTrPol.attributes.srcIp == "0.0.0.0" + - nm_update_any_source_multicast_max_rate.current.0.pimCtxP.children.2.pimResPol.attributes.max == "unlimited" + - nm_update_any_source_multicast_max_rate.current.0.pimCtxP.children.2.pimResPol.attributes.rsvd == "undefined" + - nm_update_any_source_multicast_max_rate.previous.0.pimCtxP.attributes.annotation == "orchestrator:ansible" + - nm_update_any_source_multicast_max_rate.previous.0.pimCtxP.attributes.dn == "uni/tn-ansible_tenant/ctx-ansible_vrf_1/pimctxp" + - nm_update_any_source_multicast_max_rate.previous.0.pimCtxP.attributes.mtu == "2000" + - nm_update_any_source_multicast_max_rate.previous.0.pimCtxP.attributes.ctrl == "" + - nm_update_any_source_multicast_max_rate.previous.0.pimCtxP.children.0.pimSSMPatPol.children.0.pimSSMRangePol.attributes.name == "" + - nm_update_any_source_multicast_max_rate.previous.0.pimCtxP.children.1.pimASMPatPol.children.0.pimSharedRangePol.attributes.name == "" + - nm_update_any_source_multicast_max_rate.previous.0.pimCtxP.children.1.pimASMPatPol.children.1.pimSGRangeExpPol.attributes.sgExpItvl == "default-timeout" + - nm_update_any_source_multicast_max_rate.previous.0.pimCtxP.children.1.pimASMPatPol.children.2.pimRegTrPol.attributes.maxRate == "65535" + - nm_update_any_source_multicast_max_rate.previous.0.pimCtxP.children.1.pimASMPatPol.children.2.pimRegTrPol.attributes.srcIp == "0.0.0.0" + - nm_update_any_source_multicast_max_rate.previous.0.pimCtxP.children.2.pimResPol.attributes.max == "unlimited" + - nm_update_any_source_multicast_max_rate.previous.0.pimCtxP.children.2.pimResPol.attributes.rsvd == "undefined" + - nm_update_any_source_multicast_ip is changed + - nm_update_any_source_multicast_ip.current.0.pimCtxP.attributes.annotation == "orchestrator:ansible" + - nm_update_any_source_multicast_ip.current.0.pimCtxP.attributes.dn == "uni/tn-ansible_tenant/ctx-ansible_vrf_1/pimctxp" + - nm_update_any_source_multicast_ip.current.0.pimCtxP.attributes.mtu == "2000" + - nm_update_any_source_multicast_ip.current.0.pimCtxP.attributes.ctrl == "" + - nm_update_any_source_multicast_ip.current.0.pimCtxP.children.0.pimSSMPatPol.children.0.pimSSMRangePol.attributes.name == "" + - nm_update_any_source_multicast_ip.current.0.pimCtxP.children.1.pimASMPatPol.children.0.pimSharedRangePol.attributes.name == "" + - nm_update_any_source_multicast_ip.current.0.pimCtxP.children.1.pimASMPatPol.children.1.pimSGRangeExpPol.attributes.sgExpItvl == "default-timeout" + - nm_update_any_source_multicast_ip.current.0.pimCtxP.children.1.pimASMPatPol.children.2.pimRegTrPol.attributes.maxRate == "64000" + - nm_update_any_source_multicast_ip.current.0.pimCtxP.children.1.pimASMPatPol.children.2.pimRegTrPol.attributes.srcIp == "1.1.1.1" + - nm_update_any_source_multicast_ip.current.0.pimCtxP.children.2.pimResPol.attributes.max == "unlimited" + - nm_update_any_source_multicast_ip.current.0.pimCtxP.children.2.pimResPol.attributes.rsvd == "undefined" + - nm_update_any_source_multicast_ip.previous.0.pimCtxP.attributes.annotation == "orchestrator:ansible" + - nm_update_any_source_multicast_ip.previous.0.pimCtxP.attributes.dn == "uni/tn-ansible_tenant/ctx-ansible_vrf_1/pimctxp" + - nm_update_any_source_multicast_ip.previous.0.pimCtxP.attributes.mtu == "2000" + - nm_update_any_source_multicast_ip.previous.0.pimCtxP.attributes.ctrl == "" + - nm_update_any_source_multicast_ip.previous.0.pimCtxP.children.0.pimSSMPatPol.children.0.pimSSMRangePol.attributes.name == "" + - nm_update_any_source_multicast_ip.previous.0.pimCtxP.children.1.pimASMPatPol.children.0.pimSharedRangePol.attributes.name == "" + - nm_update_any_source_multicast_ip.previous.0.pimCtxP.children.1.pimASMPatPol.children.1.pimSGRangeExpPol.attributes.sgExpItvl == "default-timeout" + - nm_update_any_source_multicast_ip.previous.0.pimCtxP.children.1.pimASMPatPol.children.2.pimRegTrPol.attributes.maxRate == "64000" + - nm_update_any_source_multicast_ip.previous.0.pimCtxP.children.1.pimASMPatPol.children.2.pimRegTrPol.attributes.srcIp == "0.0.0.0" + - nm_update_any_source_multicast_ip.previous.0.pimCtxP.children.2.pimResPol.attributes.max == "unlimited" + - nm_update_any_source_multicast_ip.previous.0.pimCtxP.children.2.pimResPol.attributes.rsvd == "undefined" + +# UPDATE MULTICAST SSM + +- name: Add a routemap to source specific multicast on VRF 1 + cisco.aci.aci_vrf_multicast: + <<: *aci_ansible_vrf_1 + source_specific_multicast: + group_range_route_map: uni/tn-ansible_test/rtmap-ansible_test + register: nm_update_source_specific_multicast_add_route_map + +- name: Remove a routemap from source specific multicast on VRF 1 + cisco.aci.aci_vrf_multicast: + <<: *aci_ansible_vrf_1 + source_specific_multicast: + group_range_route_map: "" + register: nm_update_source_specific_multicast_remove_route_map + +- name: Remove a routemap from source specific multicast on VRF 1 again + cisco.aci.aci_vrf_multicast: + <<: *aci_ansible_vrf_1 + source_specific_multicast: + group_range_route_map: "" + register: nm_update_source_specific_multicast_remove_route_map_again + +- name: Verify update source specific multicast on VRF 1 + ansible.builtin.assert: + that: + - nm_update_source_specific_multicast_add_route_map is changed + - nm_update_source_specific_multicast_add_route_map.current.0.pimCtxP.attributes.annotation == "orchestrator:ansible" + - nm_update_source_specific_multicast_add_route_map.current.0.pimCtxP.attributes.dn == "uni/tn-ansible_tenant/ctx-ansible_vrf_1/pimctxp" + - nm_update_source_specific_multicast_add_route_map.current.0.pimCtxP.attributes.mtu == "2000" + - nm_update_source_specific_multicast_add_route_map.current.0.pimCtxP.attributes.ctrl == "" + - nm_update_source_specific_multicast_add_route_map.current.0.pimCtxP.children.0.pimSSMPatPol.children.0.pimSSMRangePol.attributes.name == "" + - nm_update_source_specific_multicast_add_route_map.current.0.pimCtxP.children.0.pimSSMPatPol.children.0.pimSSMRangePol.children.0.rtdmcRsFilterToRtMapPol.attributes.tDn == "uni/tn-ansible_test/rtmap-ansible_test" + - nm_update_source_specific_multicast_add_route_map.current.0.pimCtxP.children.1.pimASMPatPol.children.0.pimSharedRangePol.attributes.name == "" + - nm_update_source_specific_multicast_add_route_map.current.0.pimCtxP.children.1.pimASMPatPol.children.1.pimSGRangeExpPol.attributes.sgExpItvl == "default-timeout" + - nm_update_source_specific_multicast_add_route_map.current.0.pimCtxP.children.1.pimASMPatPol.children.2.pimRegTrPol.attributes.maxRate == "64000" + - nm_update_source_specific_multicast_add_route_map.current.0.pimCtxP.children.1.pimASMPatPol.children.2.pimRegTrPol.attributes.srcIp == "1.1.1.1" + - nm_update_source_specific_multicast_add_route_map.current.0.pimCtxP.children.2.pimResPol.attributes.max == "unlimited" + - nm_update_source_specific_multicast_add_route_map.current.0.pimCtxP.children.2.pimResPol.attributes.rsvd == "undefined" + - nm_update_source_specific_multicast_add_route_map.previous.0.pimCtxP.attributes.annotation == "orchestrator:ansible" + - nm_update_source_specific_multicast_add_route_map.previous.0.pimCtxP.attributes.dn == "uni/tn-ansible_tenant/ctx-ansible_vrf_1/pimctxp" + - nm_update_source_specific_multicast_add_route_map.previous.0.pimCtxP.attributes.mtu == "2000" + - nm_update_source_specific_multicast_add_route_map.previous.0.pimCtxP.attributes.ctrl == "" + - nm_update_source_specific_multicast_add_route_map.previous.0.pimCtxP.children.0.pimSSMPatPol.children.0.pimSSMRangePol.attributes.name == "" + - "'children' not in nm_update_source_specific_multicast_add_route_map.previous.0.pimCtxP.children.0.pimSSMPatPol.children.0.pimSSMRangePol" + - nm_update_source_specific_multicast_add_route_map.previous.0.pimCtxP.children.1.pimASMPatPol.children.0.pimSharedRangePol.attributes.name == "" + - nm_update_source_specific_multicast_add_route_map.previous.0.pimCtxP.children.1.pimASMPatPol.children.1.pimSGRangeExpPol.attributes.sgExpItvl == "default-timeout" + - nm_update_source_specific_multicast_add_route_map.previous.0.pimCtxP.children.1.pimASMPatPol.children.2.pimRegTrPol.attributes.maxRate == "64000" + - nm_update_source_specific_multicast_add_route_map.previous.0.pimCtxP.children.1.pimASMPatPol.children.2.pimRegTrPol.attributes.srcIp == "1.1.1.1" + - nm_update_source_specific_multicast_add_route_map.previous.0.pimCtxP.children.2.pimResPol.attributes.max == "unlimited" + - nm_update_source_specific_multicast_add_route_map.previous.0.pimCtxP.children.2.pimResPol.attributes.rsvd == "undefined" + - nm_update_source_specific_multicast_remove_route_map is changed + - nm_update_source_specific_multicast_remove_route_map.current.0.pimCtxP.attributes.annotation == "orchestrator:ansible" + - nm_update_source_specific_multicast_remove_route_map.current.0.pimCtxP.attributes.dn == "uni/tn-ansible_tenant/ctx-ansible_vrf_1/pimctxp" + - nm_update_source_specific_multicast_remove_route_map.current.0.pimCtxP.attributes.mtu == "2000" + - nm_update_source_specific_multicast_remove_route_map.current.0.pimCtxP.attributes.ctrl == "" + - nm_update_source_specific_multicast_remove_route_map.current.0.pimCtxP.children.0.pimSSMPatPol.children.0.pimSSMRangePol.attributes.name == "" + - "'children' not in nm_update_source_specific_multicast_remove_route_map.current.0.pimCtxP.children.0.pimSSMPatPol.children.0.pimSSMRangePol" + - nm_update_source_specific_multicast_remove_route_map.current.0.pimCtxP.children.1.pimASMPatPol.children.0.pimSharedRangePol.attributes.name == "" + - nm_update_source_specific_multicast_remove_route_map.current.0.pimCtxP.children.1.pimASMPatPol.children.1.pimSGRangeExpPol.attributes.sgExpItvl == "default-timeout" + - nm_update_source_specific_multicast_remove_route_map.current.0.pimCtxP.children.1.pimASMPatPol.children.2.pimRegTrPol.attributes.maxRate == "64000" + - nm_update_source_specific_multicast_remove_route_map.current.0.pimCtxP.children.1.pimASMPatPol.children.2.pimRegTrPol.attributes.srcIp == "1.1.1.1" + - nm_update_source_specific_multicast_remove_route_map.current.0.pimCtxP.children.2.pimResPol.attributes.max == "unlimited" + - nm_update_source_specific_multicast_remove_route_map.current.0.pimCtxP.children.2.pimResPol.attributes.rsvd == "undefined" + - nm_update_source_specific_multicast_remove_route_map.previous.0.pimCtxP.attributes.annotation == "orchestrator:ansible" + - nm_update_source_specific_multicast_remove_route_map.previous.0.pimCtxP.attributes.dn == "uni/tn-ansible_tenant/ctx-ansible_vrf_1/pimctxp" + - nm_update_source_specific_multicast_remove_route_map.previous.0.pimCtxP.attributes.mtu == "2000" + - nm_update_source_specific_multicast_remove_route_map.previous.0.pimCtxP.attributes.ctrl == "" + - nm_update_source_specific_multicast_remove_route_map.previous.0.pimCtxP.children.0.pimSSMPatPol.children.0.pimSSMRangePol.attributes.name == "" + - nm_update_source_specific_multicast_remove_route_map.previous.0.pimCtxP.children.0.pimSSMPatPol.children.0.pimSSMRangePol.children.0.rtdmcRsFilterToRtMapPol.attributes.tDn == "uni/tn-ansible_test/rtmap-ansible_test" + - nm_update_source_specific_multicast_remove_route_map.previous.0.pimCtxP.children.1.pimASMPatPol.children.0.pimSharedRangePol.attributes.name == "" + - nm_update_source_specific_multicast_remove_route_map.previous.0.pimCtxP.children.1.pimASMPatPol.children.1.pimSGRangeExpPol.attributes.sgExpItvl == "default-timeout" + - nm_update_source_specific_multicast_remove_route_map.previous.0.pimCtxP.children.1.pimASMPatPol.children.2.pimRegTrPol.attributes.maxRate == "64000" + - nm_update_source_specific_multicast_remove_route_map.previous.0.pimCtxP.children.1.pimASMPatPol.children.2.pimRegTrPol.attributes.srcIp == "1.1.1.1" + - nm_update_source_specific_multicast_remove_route_map.previous.0.pimCtxP.children.2.pimResPol.attributes.max == "unlimited" + - nm_update_source_specific_multicast_remove_route_map.previous.0.pimCtxP.children.2.pimResPol.attributes.rsvd == "undefined" + - nm_update_source_specific_multicast_remove_route_map_again is not changed + +# UPDATE MULTICAST BOOTSTRAP ROUTER (BSR) + +- name: Add a routemap to bootstrap router on VRF 1 + cisco.aci.aci_vrf_multicast: + <<: *aci_ansible_vrf_1 + bootstrap_router: + bsr_filter: uni/tn-ansible_test/rtmap-ansible_test + register: nm_update_bootstrap_router_add_route_map + +- name: Remove a routemap to bootstrap router on VRF 1 + cisco.aci.aci_vrf_multicast: + <<: *aci_ansible_vrf_1 + bootstrap_router: + bsr_filter: "" + register: nm_update_bootstrap_router_remove_route_map + +- name: Update bootstrap router on VRF 1 + cisco.aci.aci_vrf_multicast: + <<: *aci_ansible_vrf_1 + bootstrap_router: + rp_updates: [ forward, listen ] + register: nm_update_bootstrap_router + +- name: Remove rp_updates for bootstrap router on VRF 1 + cisco.aci.aci_vrf_multicast: + <<: *aci_ansible_vrf_1 + bootstrap_router: + rp_updates: [] + register: nm_update_bootstrap_router_remove_rp_updates + +- name: Verify update bootstrap router on VRF 1 + ansible.builtin.assert: + that: + - nm_update_bootstrap_router_add_route_map is changed + - nm_update_bootstrap_router_add_route_map.current.0.pimCtxP.attributes.dn == "uni/tn-ansible_tenant/ctx-ansible_vrf_1/pimctxp" + - nm_update_bootstrap_router_add_route_map.current.0.pimCtxP.attributes.mtu == "2000" + - nm_update_bootstrap_router_add_route_map.current.0.pimCtxP.attributes.ctrl == "" + - nm_update_bootstrap_router_add_route_map.current.0.pimCtxP.children.0.pimSSMPatPol.children.0.pimSSMRangePol.attributes.name == "" + - nm_update_bootstrap_router_add_route_map.current.0.pimCtxP.children.1.pimResPol.attributes.max == "unlimited" + - nm_update_bootstrap_router_add_route_map.current.0.pimCtxP.children.1.pimResPol.attributes.rsvd == "undefined" + - nm_update_bootstrap_router_add_route_map.current.0.pimCtxP.children.2.pimASMPatPol.children.0.pimSharedRangePol.attributes.name == "" + - nm_update_bootstrap_router_add_route_map.current.0.pimCtxP.children.2.pimASMPatPol.children.1.pimSGRangeExpPol.attributes.sgExpItvl == "default-timeout" + - nm_update_bootstrap_router_add_route_map.current.0.pimCtxP.children.2.pimASMPatPol.children.2.pimRegTrPol.attributes.maxRate == "64000" + - nm_update_bootstrap_router_add_route_map.current.0.pimCtxP.children.2.pimASMPatPol.children.2.pimRegTrPol.attributes.srcIp == "1.1.1.1" + - nm_update_bootstrap_router_add_route_map.current.0.pimCtxP.children.3.pimBSRPPol.children.0.pimBSRFilterPol.children.0.rtdmcRsFilterToRtMapPol.attributes.tDn == "uni/tn-ansible_test/rtmap-ansible_test" + - nm_update_bootstrap_router_add_route_map.current.0.pimCtxP.children.3.pimBSRPPol.attributes.ctrl == "" + - nm_update_bootstrap_router_add_route_map.previous.0.pimCtxP.attributes.annotation == "orchestrator:ansible" + - nm_update_bootstrap_router_add_route_map.previous.0.pimCtxP.attributes.dn == "uni/tn-ansible_tenant/ctx-ansible_vrf_1/pimctxp" + - nm_update_bootstrap_router_add_route_map.previous.0.pimCtxP.attributes.mtu == "2000" + - nm_update_bootstrap_router_add_route_map.previous.0.pimCtxP.attributes.ctrl == "" + - nm_update_bootstrap_router_add_route_map.previous.0.pimCtxP.children.0.pimSSMPatPol.children.0.pimSSMRangePol.attributes.name == "" + - nm_update_bootstrap_router_add_route_map.previous.0.pimCtxP.children.1.pimASMPatPol.children.0.pimSharedRangePol.attributes.name == "" + - nm_update_bootstrap_router_add_route_map.previous.0.pimCtxP.children.1.pimASMPatPol.children.1.pimSGRangeExpPol.attributes.sgExpItvl == "default-timeout" + - nm_update_bootstrap_router_add_route_map.previous.0.pimCtxP.children.1.pimASMPatPol.children.2.pimRegTrPol.attributes.maxRate == "64000" + - nm_update_bootstrap_router_add_route_map.previous.0.pimCtxP.children.1.pimASMPatPol.children.2.pimRegTrPol.attributes.srcIp == "1.1.1.1" + - nm_update_bootstrap_router_add_route_map.previous.0.pimCtxP.children.2.pimResPol.attributes.max == "unlimited" + - nm_update_bootstrap_router_add_route_map.previous.0.pimCtxP.children.2.pimResPol.attributes.rsvd == "undefined" + - nm_update_bootstrap_router_add_route_map.previous.0.pimCtxP.children | length == 3 + - nm_update_bootstrap_router_remove_route_map is changed + - nm_update_bootstrap_router_remove_route_map.current.0.pimCtxP.attributes.dn == "uni/tn-ansible_tenant/ctx-ansible_vrf_1/pimctxp" + - nm_update_bootstrap_router_remove_route_map.current.0.pimCtxP.attributes.mtu == "2000" + - nm_update_bootstrap_router_remove_route_map.current.0.pimCtxP.attributes.ctrl == "" + - nm_update_bootstrap_router_remove_route_map.current.0.pimCtxP.children.0.pimSSMPatPol.children.0.pimSSMRangePol.attributes.name == "" + - nm_update_bootstrap_router_remove_route_map.current.0.pimCtxP.children.1.pimResPol.attributes.max == "unlimited" + - nm_update_bootstrap_router_remove_route_map.current.0.pimCtxP.children.1.pimResPol.attributes.rsvd == "undefined" + - nm_update_bootstrap_router_remove_route_map.current.0.pimCtxP.children.2.pimASMPatPol.children.0.pimSharedRangePol.attributes.name == "" + - nm_update_bootstrap_router_remove_route_map.current.0.pimCtxP.children.2.pimASMPatPol.children.1.pimSGRangeExpPol.attributes.sgExpItvl == "default-timeout" + - nm_update_bootstrap_router_remove_route_map.current.0.pimCtxP.children.2.pimASMPatPol.children.2.pimRegTrPol.attributes.maxRate == "64000" + - nm_update_bootstrap_router_remove_route_map.current.0.pimCtxP.children.2.pimASMPatPol.children.2.pimRegTrPol.attributes.srcIp == "1.1.1.1" + - "'children' not in nm_update_bootstrap_router_remove_route_map.current.0.pimCtxP.children.3.pimBSRPPol.children.0.pimBSRFilterPol" + - nm_update_bootstrap_router_remove_route_map.current.0.pimCtxP.children.3.pimBSRPPol.attributes.ctrl == "" + - nm_update_bootstrap_router_remove_route_map.previous.0.pimCtxP.attributes.dn == "uni/tn-ansible_tenant/ctx-ansible_vrf_1/pimctxp" + - nm_update_bootstrap_router_remove_route_map.previous.0.pimCtxP.attributes.mtu == "2000" + - nm_update_bootstrap_router_remove_route_map.previous.0.pimCtxP.attributes.ctrl == "" + - nm_update_bootstrap_router_remove_route_map.previous.0.pimCtxP.children.0.pimSSMPatPol.children.0.pimSSMRangePol.attributes.name == "" + - nm_update_bootstrap_router_remove_route_map.previous.0.pimCtxP.children.1.pimResPol.attributes.max == "unlimited" + - nm_update_bootstrap_router_remove_route_map.previous.0.pimCtxP.children.1.pimResPol.attributes.rsvd == "undefined" + - nm_update_bootstrap_router_remove_route_map.previous.0.pimCtxP.children.2.pimASMPatPol.children.0.pimSharedRangePol.attributes.name == "" + - nm_update_bootstrap_router_remove_route_map.previous.0.pimCtxP.children.2.pimASMPatPol.children.1.pimSGRangeExpPol.attributes.sgExpItvl == "default-timeout" + - nm_update_bootstrap_router_remove_route_map.previous.0.pimCtxP.children.2.pimASMPatPol.children.2.pimRegTrPol.attributes.maxRate == "64000" + - nm_update_bootstrap_router_remove_route_map.previous.0.pimCtxP.children.2.pimASMPatPol.children.2.pimRegTrPol.attributes.srcIp == "1.1.1.1" + - nm_update_bootstrap_router_remove_route_map.previous.0.pimCtxP.children.3.pimBSRPPol.children.0.pimBSRFilterPol.children.0.rtdmcRsFilterToRtMapPol.attributes.tDn == "uni/tn-ansible_test/rtmap-ansible_test" + - nm_update_bootstrap_router_remove_route_map.previous.0.pimCtxP.children.3.pimBSRPPol.attributes.ctrl == "" + - nm_update_bootstrap_router is changed + - nm_update_bootstrap_router.current.0.pimCtxP.attributes.dn == "uni/tn-ansible_tenant/ctx-ansible_vrf_1/pimctxp" + - nm_update_bootstrap_router.current.0.pimCtxP.attributes.mtu == "2000" + - nm_update_bootstrap_router.current.0.pimCtxP.attributes.ctrl == "" + - nm_update_bootstrap_router.current.0.pimCtxP.children.0.pimSSMPatPol.children.0.pimSSMRangePol.attributes.name == "" + - nm_update_bootstrap_router.current.0.pimCtxP.children.1.pimResPol.attributes.max == "unlimited" + - nm_update_bootstrap_router.current.0.pimCtxP.children.1.pimResPol.attributes.rsvd == "undefined" + - nm_update_bootstrap_router.current.0.pimCtxP.children.2.pimASMPatPol.children.0.pimSharedRangePol.attributes.name == "" + - nm_update_bootstrap_router.current.0.pimCtxP.children.2.pimASMPatPol.children.1.pimSGRangeExpPol.attributes.sgExpItvl == "default-timeout" + - nm_update_bootstrap_router.current.0.pimCtxP.children.2.pimASMPatPol.children.2.pimRegTrPol.attributes.maxRate == "64000" + - nm_update_bootstrap_router.current.0.pimCtxP.children.2.pimASMPatPol.children.2.pimRegTrPol.attributes.srcIp == "1.1.1.1" + - nm_update_bootstrap_router.current.0.pimCtxP.children.3.pimBSRPPol.attributes.ctrl == "forward,listen" + - nm_update_bootstrap_router.previous.0.pimCtxP.attributes.dn == "uni/tn-ansible_tenant/ctx-ansible_vrf_1/pimctxp" + - nm_update_bootstrap_router.previous.0.pimCtxP.attributes.mtu == "2000" + - nm_update_bootstrap_router.previous.0.pimCtxP.attributes.ctrl == "" + - nm_update_bootstrap_router.previous.0.pimCtxP.children.0.pimSSMPatPol.children.0.pimSSMRangePol.attributes.name == "" + - nm_update_bootstrap_router.previous.0.pimCtxP.children.1.pimResPol.attributes.max == "unlimited" + - nm_update_bootstrap_router.previous.0.pimCtxP.children.1.pimResPol.attributes.rsvd == "undefined" + - nm_update_bootstrap_router.previous.0.pimCtxP.children.2.pimASMPatPol.children.0.pimSharedRangePol.attributes.name == "" + - nm_update_bootstrap_router.previous.0.pimCtxP.children.2.pimASMPatPol.children.1.pimSGRangeExpPol.attributes.sgExpItvl == "default-timeout" + - nm_update_bootstrap_router.previous.0.pimCtxP.children.2.pimASMPatPol.children.2.pimRegTrPol.attributes.maxRate == "64000" + - nm_update_bootstrap_router.previous.0.pimCtxP.children.2.pimASMPatPol.children.2.pimRegTrPol.attributes.srcIp == "1.1.1.1" + - nm_update_bootstrap_router.previous.0.pimCtxP.children.3.pimBSRPPol.attributes.ctrl == "" + - nm_update_bootstrap_router_remove_rp_updates is changed + - nm_update_bootstrap_router_remove_rp_updates.current.0.pimCtxP.attributes.dn == "uni/tn-ansible_tenant/ctx-ansible_vrf_1/pimctxp" + - nm_update_bootstrap_router_remove_rp_updates.current.0.pimCtxP.attributes.mtu == "2000" + - nm_update_bootstrap_router_remove_rp_updates.current.0.pimCtxP.attributes.ctrl == "" + - nm_update_bootstrap_router_remove_rp_updates.current.0.pimCtxP.children.0.pimSSMPatPol.children.0.pimSSMRangePol.attributes.name == "" + - nm_update_bootstrap_router_remove_rp_updates.current.0.pimCtxP.children.1.pimResPol.attributes.max == "unlimited" + - nm_update_bootstrap_router_remove_rp_updates.current.0.pimCtxP.children.1.pimResPol.attributes.rsvd == "undefined" + - nm_update_bootstrap_router_remove_rp_updates.current.0.pimCtxP.children.2.pimASMPatPol.children.0.pimSharedRangePol.attributes.name == "" + - nm_update_bootstrap_router_remove_rp_updates.current.0.pimCtxP.children.2.pimASMPatPol.children.1.pimSGRangeExpPol.attributes.sgExpItvl == "default-timeout" + - nm_update_bootstrap_router_remove_rp_updates.current.0.pimCtxP.children.2.pimASMPatPol.children.2.pimRegTrPol.attributes.maxRate == "64000" + - nm_update_bootstrap_router_remove_rp_updates.current.0.pimCtxP.children.2.pimASMPatPol.children.2.pimRegTrPol.attributes.srcIp == "1.1.1.1" + - nm_update_bootstrap_router_remove_rp_updates.current.0.pimCtxP.children.3.pimBSRPPol.attributes.ctrl == "" + - nm_update_bootstrap_router_remove_rp_updates.previous.0.pimCtxP.attributes.dn == "uni/tn-ansible_tenant/ctx-ansible_vrf_1/pimctxp" + - nm_update_bootstrap_router_remove_rp_updates.previous.0.pimCtxP.attributes.mtu == "2000" + - nm_update_bootstrap_router_remove_rp_updates.previous.0.pimCtxP.attributes.ctrl == "" + - nm_update_bootstrap_router_remove_rp_updates.previous.0.pimCtxP.children.0.pimSSMPatPol.children.0.pimSSMRangePol.attributes.name == "" + - nm_update_bootstrap_router_remove_rp_updates.previous.0.pimCtxP.children.1.pimResPol.attributes.max == "unlimited" + - nm_update_bootstrap_router_remove_rp_updates.previous.0.pimCtxP.children.1.pimResPol.attributes.rsvd == "undefined" + - nm_update_bootstrap_router_remove_rp_updates.previous.0.pimCtxP.children.2.pimASMPatPol.children.0.pimSharedRangePol.attributes.name == "" + - nm_update_bootstrap_router_remove_rp_updates.previous.0.pimCtxP.children.2.pimASMPatPol.children.1.pimSGRangeExpPol.attributes.sgExpItvl == "default-timeout" + - nm_update_bootstrap_router_remove_rp_updates.previous.0.pimCtxP.children.2.pimASMPatPol.children.2.pimRegTrPol.attributes.maxRate == "64000" + - nm_update_bootstrap_router_remove_rp_updates.previous.0.pimCtxP.children.2.pimASMPatPol.children.2.pimRegTrPol.attributes.srcIp == "1.1.1.1" + - nm_update_bootstrap_router_remove_rp_updates.previous.0.pimCtxP.children.3.pimBSRPPol.attributes.ctrl == "forward,listen" + +# UPDATE MULTICAST AUTO-RP + +- name: Add a routemap to auro-rp on VRF 1 + cisco.aci.aci_vrf_multicast: + <<: *aci_ansible_vrf_1 + auto_rp: + ma_filter: uni/tn-ansible_test/rtmap-ansible_test + register: nm_update_auto_rp_add_route_map + +- name: Remove a routemap to auro-rp on VRF 1 + cisco.aci.aci_vrf_multicast: + <<: *aci_ansible_vrf_1 + auto_rp: + ma_filter: "" + register: nm_update_auto_rp_remove_route_map + +- name: Update auro-rp on VRF 1 + cisco.aci.aci_vrf_multicast: + <<: *aci_ansible_vrf_1 + auto_rp: + rp_updates: [ forward, listen ] + register: nm_update_auto_rp + +- name: Remove rp_updates for auro-rp on VRF 1 + cisco.aci.aci_vrf_multicast: + <<: *aci_ansible_vrf_1 + auto_rp: + rp_updates: [] + register: nm_update_auto_rp_remove_rp_updates + +- name: Verify update auro-rp on VRF 1 + ansible.builtin.assert: + that: + - nm_update_auto_rp_add_route_map is changed + - nm_update_auto_rp_add_route_map.current.0.pimCtxP.attributes.dn == "uni/tn-ansible_tenant/ctx-ansible_vrf_1/pimctxp" + - nm_update_auto_rp_add_route_map.current.0.pimCtxP.attributes.mtu == "2000" + - nm_update_auto_rp_add_route_map.current.0.pimCtxP.attributes.ctrl == "" + - nm_update_auto_rp_add_route_map.current.0.pimCtxP.children.0.pimSSMPatPol.children.0.pimSSMRangePol.attributes.name == "" + - nm_update_auto_rp_add_route_map.current.0.pimCtxP.children.1.pimASMPatPol.children.0.pimSharedRangePol.attributes.name == "" + - nm_update_auto_rp_add_route_map.current.0.pimCtxP.children.1.pimASMPatPol.children.1.pimSGRangeExpPol.attributes.sgExpItvl == "default-timeout" + - nm_update_auto_rp_add_route_map.current.0.pimCtxP.children.1.pimASMPatPol.children.2.pimRegTrPol.attributes.maxRate == "64000" + - nm_update_auto_rp_add_route_map.current.0.pimCtxP.children.1.pimASMPatPol.children.2.pimRegTrPol.attributes.srcIp == "1.1.1.1" + - nm_update_auto_rp_add_route_map.current.0.pimCtxP.children.2.pimBSRPPol.attributes.ctrl == "" + - nm_update_auto_rp_add_route_map.current.0.pimCtxP.children.3.pimResPol.attributes.max == "unlimited" + - nm_update_auto_rp_add_route_map.current.0.pimCtxP.children.3.pimResPol.attributes.rsvd == "undefined" + - nm_update_auto_rp_add_route_map.current.0.pimCtxP.children.4.pimAutoRPPol.attributes.ctrl == "" + - nm_update_auto_rp_add_route_map.current.0.pimCtxP.children.4.pimAutoRPPol.children.0.pimMAFilterPol.children.0.rtdmcRsFilterToRtMapPol.attributes.tDn == "uni/tn-ansible_test/rtmap-ansible_test" + - nm_update_auto_rp_add_route_map.previous.0.pimCtxP.attributes.annotation == "orchestrator:ansible" + - nm_update_auto_rp_add_route_map.previous.0.pimCtxP.attributes.dn == "uni/tn-ansible_tenant/ctx-ansible_vrf_1/pimctxp" + - nm_update_auto_rp_add_route_map.previous.0.pimCtxP.attributes.mtu == "2000" + - nm_update_auto_rp_add_route_map.previous.0.pimCtxP.attributes.ctrl == "" + - nm_update_auto_rp_add_route_map.previous.0.pimCtxP.children.0.pimSSMPatPol.children.0.pimSSMRangePol.attributes.name == "" + - nm_update_auto_rp_add_route_map.previous.0.pimCtxP.children.1.pimResPol.attributes.max == "unlimited" + - nm_update_auto_rp_add_route_map.previous.0.pimCtxP.children.1.pimResPol.attributes.rsvd == "undefined" + - nm_update_auto_rp_add_route_map.previous.0.pimCtxP.children.2.pimASMPatPol.children.0.pimSharedRangePol.attributes.name == "" + - nm_update_auto_rp_add_route_map.previous.0.pimCtxP.children.2.pimASMPatPol.children.1.pimSGRangeExpPol.attributes.sgExpItvl == "default-timeout" + - nm_update_auto_rp_add_route_map.previous.0.pimCtxP.children.2.pimASMPatPol.children.2.pimRegTrPol.attributes.maxRate == "64000" + - nm_update_auto_rp_add_route_map.previous.0.pimCtxP.children.2.pimASMPatPol.children.2.pimRegTrPol.attributes.srcIp == "1.1.1.1" + - nm_update_auto_rp_add_route_map.previous.0.pimCtxP.children.3.pimBSRPPol.attributes.ctrl == "" + - nm_update_auto_rp_add_route_map.previous.0.pimCtxP.children | length == 4 + - nm_update_auto_rp_remove_route_map is changed + - nm_update_auto_rp_remove_route_map.current.0.pimCtxP.attributes.dn == "uni/tn-ansible_tenant/ctx-ansible_vrf_1/pimctxp" + - nm_update_auto_rp_remove_route_map.current.0.pimCtxP.attributes.mtu == "2000" + - nm_update_auto_rp_remove_route_map.current.0.pimCtxP.attributes.ctrl == "" + - nm_update_auto_rp_remove_route_map.current.0.pimCtxP.children.0.pimSSMPatPol.children.0.pimSSMRangePol.attributes.name == "" + - nm_update_auto_rp_remove_route_map.current.0.pimCtxP.children.1.pimASMPatPol.children.0.pimSharedRangePol.attributes.name == "" + - nm_update_auto_rp_remove_route_map.current.0.pimCtxP.children.1.pimASMPatPol.children.1.pimSGRangeExpPol.attributes.sgExpItvl == "default-timeout" + - nm_update_auto_rp_remove_route_map.current.0.pimCtxP.children.1.pimASMPatPol.children.2.pimRegTrPol.attributes.maxRate == "64000" + - nm_update_auto_rp_remove_route_map.current.0.pimCtxP.children.1.pimASMPatPol.children.2.pimRegTrPol.attributes.srcIp == "1.1.1.1" + - nm_update_auto_rp_remove_route_map.current.0.pimCtxP.children.2.pimBSRPPol.attributes.ctrl == "" + - nm_update_auto_rp_remove_route_map.current.0.pimCtxP.children.3.pimResPol.attributes.max == "unlimited" + - nm_update_auto_rp_remove_route_map.current.0.pimCtxP.children.3.pimResPol.attributes.rsvd == "undefined" + - nm_update_auto_rp_remove_route_map.current.0.pimCtxP.children.4.pimAutoRPPol.attributes.ctrl == "" + - "'children' not in nm_update_auto_rp_remove_route_map.current.0.pimCtxP.children.4.pimAutoRPPol.children.0.pimMAFilterPol" + - nm_update_auto_rp_remove_route_map.previous.0.pimCtxP.attributes.dn == "uni/tn-ansible_tenant/ctx-ansible_vrf_1/pimctxp" + - nm_update_auto_rp_remove_route_map.previous.0.pimCtxP.attributes.mtu == "2000" + - nm_update_auto_rp_remove_route_map.previous.0.pimCtxP.attributes.ctrl == "" + - nm_update_auto_rp_remove_route_map.previous.0.pimCtxP.children.0.pimSSMPatPol.children.0.pimSSMRangePol.attributes.name == "" + - nm_update_auto_rp_remove_route_map.previous.0.pimCtxP.children.1.pimASMPatPol.children.0.pimSharedRangePol.attributes.name == "" + - nm_update_auto_rp_remove_route_map.previous.0.pimCtxP.children.1.pimASMPatPol.children.1.pimSGRangeExpPol.attributes.sgExpItvl == "default-timeout" + - nm_update_auto_rp_remove_route_map.previous.0.pimCtxP.children.1.pimASMPatPol.children.2.pimRegTrPol.attributes.maxRate == "64000" + - nm_update_auto_rp_remove_route_map.previous.0.pimCtxP.children.1.pimASMPatPol.children.2.pimRegTrPol.attributes.srcIp == "1.1.1.1" + - nm_update_auto_rp_remove_route_map.previous.0.pimCtxP.children.2.pimBSRPPol.attributes.ctrl == "" + - nm_update_auto_rp_remove_route_map.previous.0.pimCtxP.children.3.pimResPol.attributes.max == "unlimited" + - nm_update_auto_rp_remove_route_map.previous.0.pimCtxP.children.3.pimResPol.attributes.rsvd == "undefined" + - nm_update_auto_rp_remove_route_map.previous.0.pimCtxP.children.4.pimAutoRPPol.attributes.ctrl == "" + - nm_update_auto_rp_remove_route_map.previous.0.pimCtxP.children.4.pimAutoRPPol.children.0.pimMAFilterPol.children.0.rtdmcRsFilterToRtMapPol.attributes.tDn == "uni/tn-ansible_test/rtmap-ansible_test" + - nm_update_auto_rp is changed + - nm_update_auto_rp.current.0.pimCtxP.attributes.dn == "uni/tn-ansible_tenant/ctx-ansible_vrf_1/pimctxp" + - nm_update_auto_rp.current.0.pimCtxP.attributes.mtu == "2000" + - nm_update_auto_rp.current.0.pimCtxP.attributes.ctrl == "" + - nm_update_auto_rp.current.0.pimCtxP.children.0.pimSSMPatPol.children.0.pimSSMRangePol.attributes.name == "" + - nm_update_auto_rp.current.0.pimCtxP.children.1.pimASMPatPol.children.0.pimSharedRangePol.attributes.name == "" + - nm_update_auto_rp.current.0.pimCtxP.children.1.pimASMPatPol.children.1.pimSGRangeExpPol.attributes.sgExpItvl == "default-timeout" + - nm_update_auto_rp.current.0.pimCtxP.children.1.pimASMPatPol.children.2.pimRegTrPol.attributes.maxRate == "64000" + - nm_update_auto_rp.current.0.pimCtxP.children.1.pimASMPatPol.children.2.pimRegTrPol.attributes.srcIp == "1.1.1.1" + - nm_update_auto_rp.current.0.pimCtxP.children.2.pimBSRPPol.attributes.ctrl == "" + - nm_update_auto_rp.current.0.pimCtxP.children.3.pimResPol.attributes.max == "unlimited" + - nm_update_auto_rp.current.0.pimCtxP.children.3.pimResPol.attributes.rsvd == "undefined" + - nm_update_auto_rp.current.0.pimCtxP.children.4.pimAutoRPPol.attributes.ctrl == "forward,listen" + - nm_update_auto_rp.previous.0.pimCtxP.attributes.dn == "uni/tn-ansible_tenant/ctx-ansible_vrf_1/pimctxp" + - nm_update_auto_rp.previous.0.pimCtxP.attributes.mtu == "2000" + - nm_update_auto_rp.previous.0.pimCtxP.attributes.ctrl == "" + - nm_update_auto_rp.previous.0.pimCtxP.children.0.pimSSMPatPol.children.0.pimSSMRangePol.attributes.name == "" + - nm_update_auto_rp.previous.0.pimCtxP.children.1.pimASMPatPol.children.0.pimSharedRangePol.attributes.name == "" + - nm_update_auto_rp.previous.0.pimCtxP.children.1.pimASMPatPol.children.1.pimSGRangeExpPol.attributes.sgExpItvl == "default-timeout" + - nm_update_auto_rp.previous.0.pimCtxP.children.1.pimASMPatPol.children.2.pimRegTrPol.attributes.maxRate == "64000" + - nm_update_auto_rp.previous.0.pimCtxP.children.1.pimASMPatPol.children.2.pimRegTrPol.attributes.srcIp == "1.1.1.1" + - nm_update_auto_rp.previous.0.pimCtxP.children.2.pimBSRPPol.attributes.ctrl == "" + - nm_update_auto_rp.previous.0.pimCtxP.children.3.pimResPol.attributes.max == "unlimited" + - nm_update_auto_rp.previous.0.pimCtxP.children.3.pimResPol.attributes.rsvd == "undefined" + - nm_update_auto_rp.previous.0.pimCtxP.children.4.pimAutoRPPol.attributes.ctrl == "" + - nm_update_auto_rp_remove_rp_updates is changed + - nm_update_auto_rp_remove_rp_updates.current.0.pimCtxP.attributes.dn == "uni/tn-ansible_tenant/ctx-ansible_vrf_1/pimctxp" + - nm_update_auto_rp_remove_rp_updates.current.0.pimCtxP.attributes.mtu == "2000" + - nm_update_auto_rp_remove_rp_updates.current.0.pimCtxP.attributes.ctrl == "" + - nm_update_auto_rp_remove_rp_updates.current.0.pimCtxP.children.0.pimSSMPatPol.children.0.pimSSMRangePol.attributes.name == "" + - nm_update_auto_rp_remove_rp_updates.current.0.pimCtxP.children.1.pimASMPatPol.children.0.pimSharedRangePol.attributes.name == "" + - nm_update_auto_rp_remove_rp_updates.current.0.pimCtxP.children.1.pimASMPatPol.children.1.pimSGRangeExpPol.attributes.sgExpItvl == "default-timeout" + - nm_update_auto_rp_remove_rp_updates.current.0.pimCtxP.children.1.pimASMPatPol.children.2.pimRegTrPol.attributes.maxRate == "64000" + - nm_update_auto_rp_remove_rp_updates.current.0.pimCtxP.children.1.pimASMPatPol.children.2.pimRegTrPol.attributes.srcIp == "1.1.1.1" + - nm_update_auto_rp_remove_rp_updates.current.0.pimCtxP.children.2.pimBSRPPol.attributes.ctrl == "" + - nm_update_auto_rp_remove_rp_updates.current.0.pimCtxP.children.3.pimResPol.attributes.max == "unlimited" + - nm_update_auto_rp_remove_rp_updates.current.0.pimCtxP.children.3.pimResPol.attributes.rsvd == "undefined" + - nm_update_auto_rp_remove_rp_updates.current.0.pimCtxP.children.4.pimAutoRPPol.attributes.ctrl == "" + - nm_update_auto_rp_remove_rp_updates.previous.0.pimCtxP.attributes.dn == "uni/tn-ansible_tenant/ctx-ansible_vrf_1/pimctxp" + - nm_update_auto_rp_remove_rp_updates.previous.0.pimCtxP.attributes.mtu == "2000" + - nm_update_auto_rp_remove_rp_updates.previous.0.pimCtxP.attributes.ctrl == "" + - nm_update_auto_rp_remove_rp_updates.previous.0.pimCtxP.children.0.pimSSMPatPol.children.0.pimSSMRangePol.attributes.name == "" + - nm_update_auto_rp_remove_rp_updates.previous.0.pimCtxP.children.1.pimASMPatPol.children.0.pimSharedRangePol.attributes.name == "" + - nm_update_auto_rp_remove_rp_updates.previous.0.pimCtxP.children.1.pimASMPatPol.children.1.pimSGRangeExpPol.attributes.sgExpItvl == "default-timeout" + - nm_update_auto_rp_remove_rp_updates.previous.0.pimCtxP.children.1.pimASMPatPol.children.2.pimRegTrPol.attributes.maxRate == "64000" + - nm_update_auto_rp_remove_rp_updates.previous.0.pimCtxP.children.1.pimASMPatPol.children.2.pimRegTrPol.attributes.srcIp == "1.1.1.1" + - nm_update_auto_rp_remove_rp_updates.previous.0.pimCtxP.children.2.pimBSRPPol.attributes.ctrl == "" + - nm_update_auto_rp_remove_rp_updates.previous.0.pimCtxP.children.3.pimResPol.attributes.max == "unlimited" + - nm_update_auto_rp_remove_rp_updates.previous.0.pimCtxP.children.3.pimResPol.attributes.rsvd == "undefined" + - nm_update_auto_rp_remove_rp_updates.previous.0.pimCtxP.children.4.pimAutoRPPol.attributes.ctrl == "forward,listen" + +# QUERY MULTICAST SETTINGS + +- name: Enable multicast on VRF 2 + cisco.aci.aci_vrf_multicast: + <<: *aci_ansible_vrf_2 + register: nm_update_resource_policy + +- name: Query multicast on VRF 1 + cisco.aci.aci_vrf_multicast: + <<: *aci_ansible_vrf_1 + state: query + register: query_one + +- name: Query multicast on all VRFs + cisco.aci.aci_vrf_multicast: + <<: *aci_info + state: query + register: query_all + +- name: Verify multicast VRF queries + ansible.builtin.assert: + that: + - query_one is not changed + - query_one.current | length == 1 + - query_one.current.0.fvCtx.children.0.pimCtxP.attributes.rn == "pimctxp" + - query_one.current.0.fvCtx.children.0.pimCtxP.attributes.mtu == "2000" + - query_one.current.0.fvCtx.children.0.pimCtxP.attributes.ctrl == "" + - query_one.current.0.fvCtx.children.0.pimCtxP.children.0.pimSSMPatPol.children.0.pimSSMRangePol.attributes.name == "" + - query_one.current.0.fvCtx.children.0.pimCtxP.children.1.pimASMPatPol.children.0.pimSharedRangePol.attributes.name == "" + - query_one.current.0.fvCtx.children.0.pimCtxP.children.1.pimASMPatPol.children.1.pimSGRangeExpPol.attributes.sgExpItvl == "default-timeout" + - query_one.current.0.fvCtx.children.0.pimCtxP.children.1.pimASMPatPol.children.2.pimRegTrPol.attributes.maxRate == "64000" + - query_one.current.0.fvCtx.children.0.pimCtxP.children.1.pimASMPatPol.children.2.pimRegTrPol.attributes.srcIp == "1.1.1.1" + - query_one.current.0.fvCtx.children.0.pimCtxP.children.2.pimBSRPPol.attributes.ctrl == "" + - query_one.current.0.fvCtx.children.0.pimCtxP.children.3.pimResPol.attributes.max == "unlimited" + - query_one.current.0.fvCtx.children.0.pimCtxP.children.3.pimResPol.attributes.rsvd == "undefined" + - query_one.current.0.fvCtx.children.0.pimCtxP.children.4.pimAutoRPPol.attributes.ctrl == "" + - query_all is not changed + - query_all.current | length > 1 + +# DISABLE MULTICAST + +- name: Disable multicast on VRF + cisco.aci.aci_vrf_multicast: + <<: *aci_ansible_vrf_1 + state: absent + check_mode: true + register: cm_disable_multicast + +- name: Disable multicast on VRF + cisco.aci.aci_vrf_multicast: + <<: *aci_ansible_vrf_1 + state: absent + register: nm_disable_multicast + +- name: Disable multicast on VRF again + cisco.aci.aci_vrf_multicast: + <<: *aci_ansible_vrf_1 + state: absent + register: nm_disable_multicast_again + +- name: Verify disable multicast on VRF + ansible.builtin.assert: + that: + - cm_disable_multicast is changed + - cm_disable_multicast.proposed == {} + - cm_disable_multicast.previous.0.pimCtxP.attributes.dn == "uni/tn-ansible_tenant/ctx-ansible_vrf_1/pimctxp" + - cm_disable_multicast.previous.0.pimCtxP.attributes.mtu == "2000" + - cm_disable_multicast.previous.0.pimCtxP.attributes.ctrl == "" + - cm_disable_multicast.previous.0.pimCtxP.children.0.pimSSMPatPol.children.0.pimSSMRangePol.attributes.name == "" + - cm_disable_multicast.previous.0.pimCtxP.children.1.pimASMPatPol.children.0.pimSharedRangePol.attributes.name == "" + - cm_disable_multicast.previous.0.pimCtxP.children.1.pimASMPatPol.children.1.pimSGRangeExpPol.attributes.sgExpItvl == "default-timeout" + - cm_disable_multicast.previous.0.pimCtxP.children.1.pimASMPatPol.children.2.pimRegTrPol.attributes.maxRate == "64000" + - cm_disable_multicast.previous.0.pimCtxP.children.1.pimASMPatPol.children.2.pimRegTrPol.attributes.srcIp == "1.1.1.1" + - cm_disable_multicast.previous.0.pimCtxP.children.2.pimBSRPPol.attributes.ctrl == "" + - cm_disable_multicast.previous.0.pimCtxP.children.3.pimResPol.attributes.max == "unlimited" + - cm_disable_multicast.previous.0.pimCtxP.children.3.pimResPol.attributes.rsvd == "undefined" + - cm_disable_multicast.previous.0.pimCtxP.children.4.pimAutoRPPol.attributes.ctrl == "" + - nm_disable_multicast is changed + - nm_disable_multicast.current == [] + - nm_disable_multicast.previous.0.pimCtxP.attributes.dn == "uni/tn-ansible_tenant/ctx-ansible_vrf_1/pimctxp" + - nm_disable_multicast.previous.0.pimCtxP.attributes.mtu == "2000" + - nm_disable_multicast.previous.0.pimCtxP.attributes.ctrl == "" + - nm_disable_multicast.previous.0.pimCtxP.children.0.pimSSMPatPol.children.0.pimSSMRangePol.attributes.name == "" + - nm_disable_multicast.previous.0.pimCtxP.children.1.pimASMPatPol.children.0.pimSharedRangePol.attributes.name == "" + - nm_disable_multicast.previous.0.pimCtxP.children.1.pimASMPatPol.children.1.pimSGRangeExpPol.attributes.sgExpItvl == "default-timeout" + - nm_disable_multicast.previous.0.pimCtxP.children.1.pimASMPatPol.children.2.pimRegTrPol.attributes.maxRate == "64000" + - nm_disable_multicast.previous.0.pimCtxP.children.1.pimASMPatPol.children.2.pimRegTrPol.attributes.srcIp == "1.1.1.1" + - nm_disable_multicast.previous.0.pimCtxP.children.2.pimBSRPPol.attributes.ctrl == "" + - nm_disable_multicast.previous.0.pimCtxP.children.3.pimResPol.attributes.max == "unlimited" + - nm_disable_multicast.previous.0.pimCtxP.children.3.pimResPol.attributes.rsvd == "undefined" + - nm_disable_multicast.previous.0.pimCtxP.children.4.pimAutoRPPol.attributes.ctrl == "" + - nm_disable_multicast_again is not changed + - nm_disable_multicast_again.current == [] + - nm_disable_multicast_again.previous == [] + +# ERRORS + +- name: Mutually exclusive parameters resource_policy (error) + cisco.aci.aci_vrf_multicast: + <<: *aci_ansible_vrf_1 + resource_policy: + reserved_multicast_entries: 10 + ignore_errors: true + register: err_mutually_exclusive_resource_policy + +- name: Entries is 0 when routemap provided (error) + cisco.aci.aci_vrf_multicast: + <<: *aci_ansible_vrf_1 + resource_policy: + reserved_route_map: uni/tn-ansible_test/rtmap-ansible_test + reserved_multicast_entries: 0 + ignore_errors: true + register: err_reserved_multicast_entries_is_0 + +- name: Verify errors + ansible.builtin.assert: + that: + - err_mutually_exclusive_resource_policy is failed + - err_mutually_exclusive_resource_policy.msg == "parameters are mutually exclusive{{':'}} reserved_route_map|reserved_multicast_entries" + - err_reserved_multicast_entries_is_0 is failed + - err_reserved_multicast_entries_is_0.msg == "C(reserved_multicast_entries) must be provided and greater than 0 when C(reserved_route_map) is provided" + +# CLEAN ENVIRONMENT + +- name: Remove ansible_tenant + cisco.aci.aci_tenant: + <<: *aci_tenant_absent diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_vzany_to_contract/tasks/main.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_vzany_to_contract/tasks/main.yml index 65e6f1278..11c4d4e86 100644 --- a/ansible_collections/cisco/aci/tests/integration/targets/aci_vzany_to_contract/tasks/main.yml +++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_vzany_to_contract/tasks/main.yml @@ -3,7 +3,7 @@ # SET VARS - name: Set vars - set_fact: + ansible.builtin.set_fact: aci_info: &aci_info host: '{{ aci_hostname }}' username: '{{ aci_username }}' @@ -77,7 +77,7 @@ register: nm_vzany_prov - name: Verify vzany_prov - assert: + ansible.builtin.assert: that: - cm_vzany_prov is changed - nm_vzany_prov is changed @@ -91,7 +91,7 @@ register: add_prov_again - name: Verify add_prov_again - assert: + ansible.builtin.assert: that: - add_prov_again is not changed @@ -123,7 +123,7 @@ register: query_all_provs - name: Verify query_all_provs - assert: + ansible.builtin.assert: that: - query_all_provs is not changed - query_all_provs.current|length >= 2 @@ -136,7 +136,7 @@ register: query_spec_bind - name: Verify query_spec_bind - assert: + ansible.builtin.assert: that: - query_spec_bind is not changed - query_spec_bind.current|length == 1 @@ -161,7 +161,7 @@ register: del_cif - name: Verify remove_intf - assert: + ansible.builtin.assert: that: - del_prov is changed - del_cons is changed diff --git a/ansible_collections/cisco/aci/tests/unit/compat/builtins.py b/ansible_collections/cisco/aci/tests/unit/compat/builtins.py index bfc8adfbe..43f88203a 100644 --- a/ansible_collections/cisco/aci/tests/unit/compat/builtins.py +++ b/ansible_collections/cisco/aci/tests/unit/compat/builtins.py @@ -19,16 +19,3 @@ 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/ansible_collections/cisco/aci/tests/unit/mock/loader.py b/ansible_collections/cisco/aci/tests/unit/mock/loader.py index 524870cfa..2caea2883 100644 --- a/ansible_collections/cisco/aci/tests/unit/mock/loader.py +++ b/ansible_collections/cisco/aci/tests/unit/mock/loader.py @@ -30,7 +30,7 @@ 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 + assert isinstance(file_mapping, dict) super(DictDataLoader, self).__init__() diff --git a/ansible_collections/cisco/aci/tests/unit/module_utils/test_aci.py b/ansible_collections/cisco/aci/tests/unit/module_utils/test_aci.py index a1e07ed24..0305ee4c3 100644 --- a/ansible_collections/cisco/aci/tests/unit/module_utils/test_aci.py +++ b/ansible_collections/cisco/aci/tests/unit/module_utils/test_aci.py @@ -40,8 +40,6 @@ 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") diff --git a/ansible_collections/cisco/dnac/.github/workflows/docs.yml b/ansible_collections/cisco/dnac/.github/workflows/docs.yml index 1f69ba0d6..46ab0dbc2 100644 --- a/ansible_collections/cisco/dnac/.github/workflows/docs.yml +++ b/ansible_collections/cisco/dnac/.github/workflows/docs.yml @@ -6,21 +6,21 @@ on: - v[0-9]+.[0-9]+.[0-9]+ branches: - main - + workflow_dispatch: jobs: docs: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v4 - name: configure git run: | git config user.name "${GITHUB_ACTOR}" git config user.email "${GITHUB_ACTOR}@bots.github.com" git fetch --no-tags --prune --depth=1 origin +refs/heads/*:refs/remotes/origin/* - name: Set up Python - uses: actions/setup-python@v2 + uses: actions/setup-python@v5 with: - python-version: "3.7" + python-version: "3.11" - name: Install dependencies run: make doc-setup - name: Build docs diff --git a/ansible_collections/cisco/dnac/.github/workflows/sanity_tests.yml b/ansible_collections/cisco/dnac/.github/workflows/sanity_tests.yml index 32d46d478..e974d81c7 100644 --- a/ansible_collections/cisco/dnac/.github/workflows/sanity_tests.yml +++ b/ansible_collections/cisco/dnac/.github/workflows/sanity_tests.yml @@ -5,22 +5,30 @@ on: pull_request: schedule: - cron: '0 6 * * *' + workflow_dispatch: env: NAMESPACE: cisco COLLECTION_NAME: dnac jobs: + # https://docs.ansible.com/ansible/latest/reference_appendices/release_and_maintenance.html#ansible-core-support-matrix + # 2.14 supports Python 3.9-3.11 + # 2.15 supports Python 3.9-3.11 + # 2.16 supports Python 3.10-3.12 + # https://docs.ansible.com/ansible/devel/roadmap/ROADMAP_2_17.html + # milestone is 2.17 until after 2.17 branches from devel + # devel is 2.17 until 2024-04-01 sanity: name: Sanity (Ⓐ${{ matrix.ansible }}) strategy: matrix: ansible: - - stable-2.14 - stable-2.15 - - devel - runs-on: ubuntu-20.04 + - stable-2.16 + - stable-2.17 + runs-on: ubuntu-22.04 steps: - name: Check out code - uses: actions/checkout@v3 + uses: actions/checkout@v4 with: path: cisco-en-programmability/dnacenter-ansible - name: Create directory @@ -28,9 +36,9 @@ jobs: - name: Move repository run: mv ./cisco-en-programmability/dnacenter-ansible ./ansible_collections/${{env.NAMESPACE}}/${{env.COLLECTION_NAME}} - name: Set up Python - uses: actions/setup-python@v3 + uses: actions/setup-python@v5 with: - python-version: '3.10' + python-version: '3.11' - name: Install ansible-base (${{ matrix.ansible }}) run: pip install https://github.com/ansible/ansible/archive/${{ matrix.ansible }}.tar.gz --disable-pip-version-check - name: Run sanity tests diff --git a/ansible_collections/cisco/dnac/.github/workflows/sanity_tests_devel.yml b/ansible_collections/cisco/dnac/.github/workflows/sanity_tests_devel.yml new file mode 100644 index 000000000..98b549491 --- /dev/null +++ b/ansible_collections/cisco/dnac/.github/workflows/sanity_tests_devel.yml @@ -0,0 +1,32 @@ +name: CI Devel +on: + workflow_dispatch: +env: + NAMESPACE: cisco + COLLECTION_NAME: dnac +jobs: + sanity: + name: Sanity (Ⓐ${{ matrix.ansible }}) + strategy: + matrix: + ansible: + - devel + runs-on: ubuntu-22.04 + steps: + - name: Check out code + uses: actions/checkout@v4 + with: + path: cisco-en-programmability/dnacenter-ansible + - name: Create directory + run: mkdir -p ./ansible_collections/${{env.NAMESPACE}} + - name: Move repository + run: mv ./cisco-en-programmability/dnacenter-ansible ./ansible_collections/${{env.NAMESPACE}}/${{env.COLLECTION_NAME}} + - name: Set up Python + uses: actions/setup-python@v5 + with: + python-version: '3.11' + - name: Install ansible-base (${{ matrix.ansible }}) + run: pip install https://github.com/ansible/ansible/archive/${{ matrix.ansible }}.tar.gz --disable-pip-version-check + - name: Run sanity tests + run: ansible-test sanity --docker -v --color + working-directory: ./ansible_collections/${{env.NAMESPACE}}/${{env.COLLECTION_NAME}} diff --git a/ansible_collections/cisco/dnac/FILES.json b/ansible_collections/cisco/dnac/FILES.json index 3986f5776..7286b9cd5 100644 --- a/ansible_collections/cisco/dnac/FILES.json +++ b/ansible_collections/cisco/dnac/FILES.json @@ -2818,7 +2818,7 @@ "name": "plugins/module_utils/dnac.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "d1e4ec066734657d8a31d57fdf241dfb7b21e88d042db1fea1f65f2f09b7ff24", + "chksum_sha256": "f36fc397baecb8b3936be4de24ebb50c5fc2c7bc3b3ed76d5cde908b715fd0bd", "format": 1 }, { @@ -2832,1085 +2832,1085 @@ "name": "plugins/modules/tag_member.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "203c909628aff2179480a93f6e37ab0a16e075db1c288c024e61455242e7dc81", + "chksum_sha256": "34fdb2053f4dbe10ec14ed19fa2207895d307dba5ea319dff4ec631cd71c589c", "format": 1 }, { "name": "plugins/modules/disasterrecovery_system_operationstatus_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "169d958c1852cf2c344f64539855c6a6b189217d00aaae488df74651596ab5b4", + "chksum_sha256": "338fc2d9fb90e5a71ac2d4c6f8cf7d28dc25869f5d2ef6fdf5757e23b38edb4b", "format": 1 }, { "name": "plugins/modules/network_device_by_serial_number_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "454e39903902ff3ca060d8fde9d8f63109351e9012a6409e9cda63eb018de397", + "chksum_sha256": "333d4019c7c97edb935b5edc2dbf6f31ac01a9fb85edbcc4970cdf10838abf54", "format": 1 }, { "name": "plugins/modules/wireless_enterprise_ssid_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "de5ae304337527808b45223ee75b92ac6e44a745594986860c8dbf534cafe4a0", + "chksum_sha256": "77347253283a1530cd0fad6437990a9fc4324810cd8b32ec6f9eb938d3d9d156", "format": 1 }, { "name": "plugins/modules/sda_count_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "7b3abf7c124506adb650e100e25ff93095e8d44f88970edeac372829f37b301b", + "chksum_sha256": "bb754d9e70ec973e1a807c5725d33c0eda80eb8c5c92cede20dfa29865f90822", "format": 1 }, { "name": "plugins/modules/network_device_custom_prompt.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "6f4ffb70cfcad7ccda83fe1adbc105a687ff29f84158b2eafd310560404ba6cc", + "chksum_sha256": "80d8f21b58d669ec05a6f5d3e9a0cffa4a9acb12497202d5d7f73fa6f178326a", "format": 1 }, { "name": "plugins/modules/configuration_template_deploy_status_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "bb7d0b67ea6d91f6e65a11b06df6b9ea0b3836814e6cb3d4ffa1e769deff4ffa", + "chksum_sha256": "08013512def343c074bf7c61562eb19f7d032e068c9c7490a75ef4f056a745af", "format": 1 }, { "name": "plugins/modules/file_namespaces_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "c317859717dac84425184ebf9b11f48f6cfec9d6104b8a5e09f7fa02d22d7b4f", + "chksum_sha256": "f4321c28883bf4ef2f5c2e2138ba553eef2449a64af6fec22f70f942fd185a10", "format": 1 }, { "name": "plugins/modules/syslog_config_create.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "252947ca52152d098f82596a66adaba99f8a26c96aa5f746eb07d42d99b11a1a", + "chksum_sha256": "64fab4d7ca2e088eec6df77a7b34dad99413db65e0d1e2dc1bc1df087a03f958", "format": 1 }, { "name": "plugins/modules/buildings_planned_access_points_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "904446f88544bfed37ab92855b5b3f05ab0dafad096689e6a45cbaea631d55c6", + "chksum_sha256": "913eac273b931f533e656c155798c8cb6f6470cb162d11ee99b4bc8da3494970", "format": 1 }, { "name": "plugins/modules/reports_view_group_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "6d99b212f111603c01bcc4c7f1bff2ff589825f2e583c8e2559dad43055a0c85", + "chksum_sha256": "851bf33899e8784e2d86d5c1cfb2bdb5694001ee71acb73e0a8386720e2eb399", "format": 1 }, { "name": "plugins/modules/wireless_provision_ssid_create_provision.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "bcc7b579d54ffc26c1def2f4196367b2eb758d18c143249122fb43a9529dd89c", + "chksum_sha256": "cded1c74ad3da8fc10d9ada27632cdd8cc36d904fb1fb8150754160d6539dbf3", "format": 1 }, { "name": "plugins/modules/pnp_device_claim.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "a6371657e6f9fe7e968d118d7a7f5e5bb1da056535daaef24e441b78d381bf16", + "chksum_sha256": "602231c84933ddd1e3ee06b665a6732c14d2789ceed318ab2a45cc7b1d37c554", "format": 1 }, { "name": "plugins/modules/snmpv2_read_community_credential.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "cbe2cebcfc426a79bb8ddf73979d1f089d4c09ce7fac9f98009d4ee9c17bfdca", + "chksum_sha256": "233bb1488321b2efad2aac315fccb11a4ab4ff577638f6a13f368e776346960f", "format": 1 }, { "name": "plugins/modules/snmp_properties.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "19254d3864bc2b7c3b902d500b9dea3c18b394ddcc751ed74f2e3f16fa176f8a", + "chksum_sha256": "696f1758dcdb3a1d7baf721a1d3116f0d1708179ea191a11a3a156e4206234d1", "format": 1 }, { "name": "plugins/modules/wireless_profile_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "02d3c53adadf11257d89c1b9e1d616459358fbac84e6e476070984e9b7b466ee", + "chksum_sha256": "c7b6af622e5a439f772afff88f0d4a08b643539de664e06e04236eadd4947fc8", "format": 1 }, { "name": "plugins/modules/network_device_config_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "05ada1ef97871761da405e8ce7582f2ad7fb743e0c0c6540421e94baa94c9d6a", + "chksum_sha256": "35f355bdab72a72b05cccd892b9f9746aca19892ae563b3d2ae7ba34801baf24", "format": 1 }, { "name": "plugins/modules/tag_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "91a490365698f866a3a5ff9e8ec155137f2cd24b7e197628cb67f16a17cc0a44", + "chksum_sha256": "572dbeaf9d5419df7af96b1d25e4acf37aafafc515b144eb5e2f1718e5e48a5d", "format": 1 }, { "name": "plugins/modules/site_assign_credential.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "0c6afa5b7e46cf956f8bd6d030b5f16e38675a7fe78d84f2f265dcf1a744d419", + "chksum_sha256": "a24bf8e37412386945e0a1285f305c3d00c3dfe546693451cd0eaaf09ea58fbf", "format": 1 }, { "name": "plugins/modules/sda_fabric_control_plane_device.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "81d97f3aa30c6dd3aec636bfee7aeaaa8b3c7e0579ef437917a2c7963f5f460e", + "chksum_sha256": "9e1fc3c6997610fb5eb58da1ff86cac1c2f12fe29f570b04c21f221d8eff08c0", "format": 1 }, { "name": "plugins/modules/profiling_rules_count_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "bca7cbc7c41b1ba80975b3d23fe4c05d42908852a4b81b56461e2342c3db9f99", + "chksum_sha256": "d7ec7710c2e4481aa1380b07cffe76c8d5c5563c6e45b7592a6cad08d3fe71b8", "format": 1 }, { "name": "plugins/modules/roles_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "d62bd99d36a17041da882dcfb46a8c59b9394bf6c794b93d8e63d1a9777f5fcb", + "chksum_sha256": "de94f18450380a4392ddf55fe23341d727d5c38401e9e4bb145768f1f549d312", "format": 1 }, { "name": "plugins/modules/task_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "6e5444016cfeb218c4b6e19d04d0d91094d22d5955f30b412628f030ac91c634", + "chksum_sha256": "c939839ee83d08e2568d652d43cc2dd043f7f4bc45bdf6b643593990b318f5f9", "format": 1 }, { "name": "plugins/modules/wireless_sensor_test_results_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "453c901bb4c12bee21a750e0ef18fd8b031d15ab2c4d26d819c5a23ecf3b1f75", + "chksum_sha256": "2aba1ead06b80720d76b8d2ab036fdda406b4c85bf12520413d3bdfc07b9401a", "format": 1 }, { "name": "plugins/modules/wireless_dynamic_interface.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "6375d7e2d6845946accc418fcdaa8dcfc99df04f8a663df722b023b51ca497c7", + "chksum_sha256": "060b815aa82c2113c3ce30c15d309e5ca171dc20bc8e03b451e758b5804f717a", "format": 1 }, { "name": "plugins/modules/nfv_provision_detail_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "fb031a00e038a41b28c3f79eb4ce5b15d00d45587342ae4b47b55b8ae6165027", + "chksum_sha256": "f22479fd4fd40caef85c62bef81ee9f9d95ec8a38d7fb4d356d333ca9790e148", "format": 1 }, { "name": "plugins/modules/interface_operation_create.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "a6a58a9012fabb20547a7773a84cc4272b7528e870a77928949e13cc0699b50d", + "chksum_sha256": "752c7f20ff323991e808abe801061cbb02fbc322ab7c1291707a5689c87c9bcc", "format": 1 }, { "name": "plugins/modules/tag_member_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "a191cc31927b7aeeddc64eaa65eee654178e1b04d52296e93deee41d4bfe7b06", + "chksum_sha256": "8ed423053ce775e469f32b9082d8fd6a5b4c2a72e122bceca773e2196c5c3b80", "format": 1 }, { "name": "plugins/modules/lan_automation_status_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "94adddc8a9a3631e0f823a5eebf6c79b35dc847863d3d623c4635f4b70915cc0", + "chksum_sha256": "ca3459c865c3cfd1300abbbe00327ad89370e0171dc9db54ceea74bafc69649e", "format": 1 }, { "name": "plugins/modules/endpoint_analytics_profiling_rules.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "d2ccc3c8e87787793ab67415146ab0c593d8d4fc9b4c9930ccaa366806fda0b8", + "chksum_sha256": "0ee09af1955e780d336f71e53f5aade0fef05319a22c0a056a07dd5230c157a4", "format": 1 }, { "name": "plugins/modules/event_syslog_config_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "5ceec8de938e398ad905706ced95bae8f98b372805637b9d095351e57bfb222c", + "chksum_sha256": "97fa31b07f0261b63564720aae6185620f35e7fc86a5a154a8580c497c35c7c6", "format": 1 }, { "name": "plugins/modules/business_sda_wireless_controller_delete.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "4e53deeff2c7302fababc9cb81cd82bb303e745946a70029ea825e1e55f417cf", + "chksum_sha256": "9005bf199793e794b60b820b8a3c35e37d460facfbb78eeac939899ebeb5953d", "format": 1 }, { "name": "plugins/modules/user.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "15816f3c76bdd77734d55c36d2aaf6af8894d63e5191e21f78e1e9cfe4b8a207", + "chksum_sha256": "fc5b1bd717058796844b4c90dbe087fe9b5161b3addd2b73d52bd52f98e29766", "format": 1 }, { "name": "plugins/modules/associate_site_to_network_profile.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "c0678189c515d58820a676a89f138a0d114a598a8058da9d43808587fc2ad1d9", + "chksum_sha256": "602abf01696377306e1a74e83b6fc749a3438adeb6531133a2a57ecfa7325e70", "format": 1 }, { "name": "plugins/modules/compliance_check_run.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "c45f742ec63b5dccfc99b521fa209e5de0751bd3b31dad01112196b122f4912a", + "chksum_sha256": "72ff23d614916219c240716a8201b6db09a5948defa6ca3f84b90bcc74c619d8", "format": 1 }, { "name": "plugins/modules/pnp_device_unclaim.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "4ff71f21b9da847e293450033954de0ed0214c1bf81405dc8a84211e1a8b1941", + "chksum_sha256": "c4bff9d9b35533a014fa68451e2d3ebe6ab2c7298b1c629ab49f78214e0169bc", "format": 1 }, { "name": "plugins/modules/interface_update.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "44124a84201011dd914c4442137dd4ff17eecd755086f9e959cc930371e0975f", + "chksum_sha256": "9d154bfc41b0268be60fc3bfe934d162d6d3c7889f4212c138238fdb59beec62", "format": 1 }, { "name": "plugins/modules/lan_automation_count_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "f3f59906e42a06d33bb7f50a9ef71e42b8f9ebed3272d3c021e8cf9857ae7f20", + "chksum_sha256": "01ce3ce65cc63c09db01ed03b67ec8c6b3a617e9cc47aa6c1cf6315ae3ac7a60", "format": 1 }, { "name": "plugins/modules/pnp_device_authorize.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "0e2b62b5ead00baef86df268bcff38b458e171e2835303261b80d9b8208fbe25", + "chksum_sha256": "48371d790ad877e32f1397e82d42245bc66da1558dade583eca97e303d6f4f2b", "format": 1 }, { "name": "plugins/modules/task_count_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "d5ebbd9c4361b97087aa51846b2806e3122704818b96a6cf5fa2db3b9ff7a328", + "chksum_sha256": "96121154401e39130b0faf0da4714179d91fac8c54ac7b7e0e742a2e4f3bb3c7", "format": 1 }, { "name": "plugins/modules/app_policy_intent_create.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "abb3f3e155c35a773565ea043a23a02e449c3b8d4f09bdd276173cb2721129ae", + "chksum_sha256": "c62d8cfc4d50b9dad0c73184b3e10acfab20ef9267cbde21dd20ade5f913e98a", "format": 1 }, { "name": "plugins/modules/pnp_device_import.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "4af97e486e34b84e313106034f9975fc662621f333dd146e82e70d5213d57ffb", + "chksum_sha256": "60538898d31429714400e1bee616715662a6dc0868c10fe642aaf2c4d8804411", "format": 1 }, { "name": "plugins/modules/authentication_import_certificate_p12.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "be9370de13872b64e89aa4688f426207ad7cb36260c67ae838a6f8e0939188f8", + "chksum_sha256": "cddda97a5a8bb76dfb9913c6ced565b770c5c95b33375e626eeab2f1b588be94", "format": 1 }, { "name": "plugins/modules/sp_profile_delete_v2.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "2db4c0b1df0fb25326f24d9c60c0fe2dbba094d38e355bf96b1f65ecf8ac8c45", + "chksum_sha256": "0111f60a0dd6a58af385bf585064db9679166cf1f2636cb820308791ed2797d1", "format": 1 }, { "name": "plugins/modules/topology_network_health_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "bf2fb1801951e493fba7308a4274be2241b4df4cfb195753b88d1f2749f649ec", + "chksum_sha256": "85f8527871c7e42a00295658f92bb184d284a5755b1e5ee4f21c4d9a3f8b449d", "format": 1 }, { "name": "plugins/modules/wireless_provision_device_create.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "19c1799fc23fbf3fd97a2f3a3ad749d6031931575136fc01637fa855b49b47e8", + "chksum_sha256": "097a942722519fd081a35577b59dd618719156d3cae7b1020e4c089d7836c191", "format": 1 }, { "name": "plugins/modules/discovery_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "08b06425c4819419c08b077df7e8f66066357a54be2364c8888b25a3a06db5b2", + "chksum_sha256": "dd2feb16fbcfe5032e7e1728e28bf8b350ee9db828d94c5aaf55c4e9a92b4e57", "format": 1 }, { "name": "plugins/modules/device_reboot_apreboot_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "3a1b9e994c90c4ade0c9b87e530cc0d090d5df93eef287dbbb8c979deef9f599", + "chksum_sha256": "e22d725706aba70caefdc1734ffd4fc84f98dd4b8f06813147ae00589bd973e1", "format": 1 }, { "name": "plugins/modules/discovery_device_range_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "1f2f3fdb22c9cf5c909dbcdb1475d6b54f82a4a6ea233c3e3fb896e026a300df", + "chksum_sha256": "5849703f79a8c63a95508fd8cc76c37fdbd7ddd554f2d446077f17f06f80ea03", "format": 1 }, { "name": "plugins/modules/event_subscription_email.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "1b2d71eb95c5bb7161305eb06427fc780814251ff09ef7e3640155e04128ed79", + "chksum_sha256": "b20e8d01d362ea518177479564b41475bb22390529bd9e146a43d0b3574cc7f3", "format": 1 }, { "name": "plugins/modules/sensor.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "92ebd09304b9d1a42d2e011fa9b4abfd9bad86382dd8945993bfa7d22d4d483d", + "chksum_sha256": "61a1f62c0323db3cd354dab37154431035575c4d30f56de9526fdfa0e8e95282", "format": 1 }, { "name": "plugins/modules/integration_settings_instances_itsm.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "f69b1536b8496c66d7aba8ad2e681c6e41762106b63a1567e051416ec7e1768f", + "chksum_sha256": "4447c1484dad5ad8b0c6e581a5a79e8a00cd25d5c919960c83a7bc8ec73f0c70", "format": 1 }, { "name": "plugins/modules/site_design_floormap.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "83fe70f63be605e69b1e808223942566a24c6dcffd78c1f008ba3dc9d20d9aa8", + "chksum_sha256": "d602258e6a2793627b1288a73251242d9ffd1ad8e50a0a61414295ea4c77a53b", "format": 1 }, { "name": "plugins/modules/pnp_workflow_manager.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "aa8f6e21144259fab986674b6c92acf78b620297976704f4a93b43a265b67f08", + "chksum_sha256": "01319e51ca12527ac93fff93abecbfe9466a2dc2e9e97517c172a1d3e2d4b7ee", "format": 1 }, { "name": "plugins/modules/global_pool.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "7d49cd0161314e7e14177fa026c94262dc23f43be0490272d7d1ee1e0ecba399", + "chksum_sha256": "e3b5942ca9610d638861c899a28b7edff86176ef90ffb6aa84c74d07398cc12c", "format": 1 }, { "name": "plugins/modules/device_interface_by_ip_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "12100e56b2e3b321eed3abbd9da9a1b7b72bc382828de29a1b44a95e973e5272", + "chksum_sha256": "247b37667e6600267377a09c95d468f263cf393c9269cc3fe7352a86391d7b96", "format": 1 }, { "name": "plugins/modules/network_device_chassis_details_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "9022f3da91c1718d963b207de578bdc23e936e317d8e9c7d6b89e5ec8ff3bffd", + "chksum_sha256": "61e6ae2c6c39475d4e508591966135ac0715bf438868fa6f2421738e3d460899", "format": 1 }, { "name": "plugins/modules/sda_fabric_authentication_profile_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "edbe6c125b774da02e2ddaec0d1209954677a3802c60fde88850b85f71fa7ce0", + "chksum_sha256": "ba207e06e273caafae8ee2031bf163b960f08dfbde7e5211489ea78dafd1d1f5", "format": 1 }, { "name": "plugins/modules/client_detail_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "f114628126b5e913083b833c521fa086ef784fc24e7879cf1d74cb663bd7a4be", + "chksum_sha256": "50d9012553e45a39231c185123ed81d2bc273ff0440f9231f88578efe4ab301a", "format": 1 }, { "name": "plugins/modules/license_term_details_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "4f520a32196e272e231ce166b08afcb91472631a779e8a7fa7e03bacf66682b3", + "chksum_sha256": "93698c9894a43757eef2431a0db6c00ad611440dc70aec7169ebca0cf5875f61", "format": 1 }, { "name": "plugins/modules/license_device_deregistration.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "eeeab2bd24a92035122df2d90216837ea1c661b074b8ef6659ad9f52ebc7cac0", + "chksum_sha256": "ddeed833b64145c5d88b04421115f39d30effab218656bdedeb828c869c50764", "format": 1 }, { "name": "plugins/modules/device_interface_ospf_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "b0060a5eb9b34449bed92581966ea6aa8064594543280d845386250fbeaed033", + "chksum_sha256": "ed30d8d2a7ee30d254452ca157bad1f22117a286d37fe9bef525dbd5582c35f9", "format": 1 }, { "name": "plugins/modules/sda_virtual_network_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "2e0789344a1291f94ae02145fc6b12069ef843f83db8ad235a2ec2a0084c79e7", + "chksum_sha256": "35c830cba1f0a91954ae39b856aecd01ad51dc0d5c1d10d891671af5ed6e4c6e", "format": 1 }, { "name": "plugins/modules/discovery_device_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "2b86177971e4457bb94184fcaa7f18c7f79eabd14f7874e25dfc32768ac910db", + "chksum_sha256": "9503c3fbb9a27e54e0b290ef82ac1255de261218561abdf11ff0204bd7f4517f", "format": 1 }, { "name": "plugins/modules/business_sda_hostonboarding_ssid_ippool_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "cf348fcaecb559dbca49ce5b5d9e540e48812b696f575c192676474c23b46da8", + "chksum_sha256": "02000c3c68ecb37e768d5938da1bb59a84df7a7e252684dc80f5adb287df972c", "format": 1 }, { "name": "plugins/modules/swim_workflow_manager.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "c1e32599b2c25efd5a1be3e66e8ea1bf0b6871218bde74b2e4e828c67d1bf994", + "chksum_sha256": "70b080cb6316ab39cdc8e1d6ace2ff128760698778c49a134c576947c942e515", "format": 1 }, { "name": "plugins/modules/execute_suggested_actions_commands.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "19844c72afef6beaa1d1b72bff597f7a80e73b09ba3a68ea2c5ad042f0c16662", + "chksum_sha256": "f66085b17d99d7819eda3961cf0cfcb7b9dbbc317908c0f01dd61898236f203f", "format": 1 }, { "name": "plugins/modules/business_sda_wireless_controller_create.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "84f5b496f3795549f66eb8a40401e8151e0e0334b3a0ab81afe9833db612a216", + "chksum_sha256": "b08d11477f17e38c0b2227c8ce36413c494d9a50a6a076ae12859cc504d4abee", "format": 1 }, { "name": "plugins/modules/network_settings_workflow_manager.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "c0a00e9cece5905436095add9b58a97e5292f9f941df31af8bd5f77e5a665352", + "chksum_sha256": "e72eded9f5e28624682f928bc3791f830e6964f28d4bb57b76fe8671d44f5fe0", "format": 1 }, { "name": "plugins/modules/wireless_provision_device_update.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "12136ddb30e224adc6d3291346817097d4446fba99bb5eb7e747d8a3d1585a92", + "chksum_sha256": "9db7025f8f65a52d3f0752e767c2c1c9613a80f8007b4e78315fa70e945c6d28", "format": 1 }, { "name": "plugins/modules/network_device_sync.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "70d9cffd145e26f9506673554dcd917054d0514d5876d7e13307c88b290669d3", + "chksum_sha256": "78f9ceb7e7b4371e85c3cd52f71c6e6b307ffd23cdfd37111b544928422757ab", "format": 1 }, { "name": "plugins/modules/wireless_rf_profile.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "4327a68c352ee3a396e3dbf795daf7ed3be99c0b95101d2c0cfb06883c27344e", + "chksum_sha256": "5472514c55110035ba8c47f60313201f8b49b0bf9c2b2bbac47c7c5dc08c5cbf", "format": 1 }, { "name": "plugins/modules/sda_fabric_site_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "78bf22da9023c2d264ac803a007557f506822dea4daab444662366cf56da0f33", + "chksum_sha256": "508c83e7ef73c711338d199b4b05eda7e94bfc4831958ca8f1fcfd62a77f8b5f", "format": 1 }, { "name": "plugins/modules/event_subscription_syslog_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "2f00b770e9beaa154270e9f6484a76a2cd9bab29c121ad80cccf9239a23bf65a", + "chksum_sha256": "37591b77c22a26b1ce79bba87f94dc5e1c96a94da9ac5dd797a74960a646bb05", "format": 1 }, { "name": "plugins/modules/configuration_template_import_project.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "84adb47b58a6d3a6783475832347ad2168d329157d34e3ca2be8ed20c8014a69", + "chksum_sha256": "99a2b7ba0b8cff781db383abcd667cd23d02d1991b27deada9c2802f56870bd7", "format": 1 }, { "name": "plugins/modules/topology_vlan_details_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "db096d3fd5525976db78b3c4a91e7ca8b7d51f69413daadab850cd4ab7fa04c9", + "chksum_sha256": "70aaf59cc3a489a2f4aa5d0b052d7aeb89c09fc4435c0513beeafffeaa0e99de", "format": 1 }, { "name": "plugins/modules/lan_automation_log_by_serial_number_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "fc24198351f08f730bbd6af533d2cee6fcfd8602fb1ffa46cfe79c8cd7105dbb", + "chksum_sha256": "205f22f0ec447a840cafa8b219e22b88636967ae405420cbfc99a99d9c64bbd5", "format": 1 }, { "name": "plugins/modules/service_provider_v2_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "fb76e209b0560eae94118f3145de3459fea00f3ea869b44fd2fd987889f821e8", + "chksum_sha256": "7887050a78e4710122fa71fa4f758063a83b3ea50b6286541dc4c7cef6bed68a", "format": 1 }, { "name": "plugins/modules/site_health_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "4993391714d00efd42500ca81834ecce34a31b559fdee18ec149693528920dd1", + "chksum_sha256": "9b20f00dd0a3fdd8e623c90781e001de3488e082ff7f78d3d0c2a78c2e8cb7dc", "format": 1 }, { "name": "plugins/modules/event_series_count_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "f7bff6806a626c0a80c6440ead86d4136386cac6a166015f145d6d1c1a762ee2", + "chksum_sha256": "e8ccee65b615913c707e66532d126931f8bcac3fbdea044d97151642c57d5423", "format": 1 }, { "name": "plugins/modules/configuration_template_clone.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "476d838d47b3997dc18a371395ff3cb6cce7168726c025cd1c76dab8165f7352", + "chksum_sha256": "7d717330707d9fe6eea2482a6108756b83227fc12c89d0be6133015f5cda28d9", "format": 1 }, { "name": "plugins/modules/swim_image_details_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "cfca9340b6a13a2bd5a087ff3c6e14c4a23c766477e5d31a900deaf0791f882b", + "chksum_sha256": "bdb0d985b3d8e3e87099c574b5c06770159c6b937f86d6aeda7e7d1b6b80cb94", "format": 1 }, { "name": "plugins/modules/sda_provision_device_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "c2739b9dca50d41ea851746d65d3f497974991d2cebad4c5a63f5c14b68bbd5e", + "chksum_sha256": "c368e9b1b79763ca9c1c0ac900b575b13b40463165301e4a50d2505c46cfa4b8", "format": 1 }, { "name": "plugins/modules/pnp_intent.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "46895eac51c54b6786d2d15fabe55a7fe4c38db13f6be4701876ad0db8ca1693", + "chksum_sha256": "63951047324164840c1b84ad51e6861d3015a7cb1d247024a43d725251ddca69", "format": 1 }, { "name": "plugins/modules/system_performance_historical_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "580525d7d40982c76a858fd37f62a9a17cb605eaab0b12f01a68ba007490bd6e", + "chksum_sha256": "db43d9616769582ea8ac005948a39665f274157f4f8e165361f2541a9635de43", "format": 1 }, { "name": "plugins/modules/sda_fabric_control_plane_device_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "c1e486a19e64166bba9aa986e01c9a0627c0b384760f24bfd412e7131a12e42a", + "chksum_sha256": "a01c251bfa7e2011ccd7d311d4dd0c85428790ea78cb3180f878004d22551241", "format": 1 }, { "name": "plugins/modules/eox_status_device_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "b7978f697c8a208f25b7fecd54ec1e9fef590d25dac54f0f31b12db93584d3b1", + "chksum_sha256": "64980b0ccb39275f2b8dd625f90fdd001625be11fb2d4342f60e2fe420af8df9", "format": 1 }, { "name": "plugins/modules/threat_detail.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "ff998c518ece001129362b6e239b1d043d377b6bde90d2dde7899f838d1ffa0c", + "chksum_sha256": "865c8e83860d3a399ae0420597636dc67ae83c826d1ca2f2d40eddcc4c130def", "format": 1 }, { "name": "plugins/modules/configuration_template_version_create.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "d187096538d665d3630c1ed3edae1adf425d093b552e9dc179050ea1f8a53414", + "chksum_sha256": "c1b7aa1f6a2ec4ed5ade524168e4c6804d0694e29f5cbf9acab3502ee4e7ad0c", "format": 1 }, { "name": "plugins/modules/syslog_config_update.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "31516b0a94c60248bb48e8521d6e3f11a52b9465fa4fb76212142d711cfcf6f1", + "chksum_sha256": "26816bb5140d94d96173d69a16b49a0132e6febbb3ff3eb1e856746a77eca271", "format": 1 }, { "name": "plugins/modules/nfv_provision_details.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "fd9f58a5a78e6cf3b9ef4a18828bfd3d3c71bf9067bddeb0f21cbd6257d960e7", + "chksum_sha256": "8d59bcb7f9b05d8a5268472ee86786c1dfe55d168c22f05bb08eb66fb32ceb53", "format": 1 }, { "name": "plugins/modules/event_subscription_details_rest_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "12dc1a8fabe5dae7f1d74727d8c9bb9f0084c774d33131083b32a175c4eb6608", + "chksum_sha256": "39f3ded1e5b9d76cf7e0ea7a54e73bea15bcc76a90ebdfbb78c5295ad86c19d5", "format": 1 }, { "name": "plugins/modules/discovery_range_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "8ba689381e0b1232ccf4d48f2635e19e96b2d217ec30f0d460f21becf1991b93", + "chksum_sha256": "584f18f492f252b82331acf732253ea92bb96fd989cfe2545a73884106fedc4b", "format": 1 }, { "name": "plugins/modules/site_design_floormap_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "16a61115901f52e2c0486eecff5fae808a20a5b5165b451f345c151cec3c02ff", + "chksum_sha256": "22f432894c23601c08b42da3f77b42ca341e3a8075c249c83a046ab97e999404", "format": 1 }, { "name": "plugins/modules/discovery_job_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "74fa4b86bce115c77937388bf8c30dd1c212c51c9359bfb30a22ea347cbe228c", + "chksum_sha256": "f623ef881ce3592e32ea25604dbd075d837b9a5c1e8c1997178bd0474c425cb2", "format": 1 }, { "name": "plugins/modules/global_pool_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "c135645efbd68ff6b09096ba7f37bce0049bcf344133060f5c05a2e58a7c0000", + "chksum_sha256": "b377a33bab9641cb9756c14252cef50419eb6b49f131cf7cb57195a40a1d096a", "format": 1 }, { "name": "plugins/modules/pnp_device_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "f8f235117077b827547ba282ab803569826a3995bd54181520595f11dcdf0ccb", + "chksum_sha256": "69fd7b9a578ff1b2aa1a3832a5b15caa0f53794a28881e2dd210cb8d2a54544e", "format": 1 }, { "name": "plugins/modules/device_replacement.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "c32f6b4a2041ea18f9c199868c982a5a5f4d9c0c857ab95b77ea044f9b925b49", + "chksum_sha256": "76619f7b6f994527b0048eb03b6f197872ae889bb692fd6c5a67ce373610d405", "format": 1 }, { "name": "plugins/modules/sensor_test_template_duplicate.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "94b795d09e7eb4e147aa0d43def6667526f92ae82d09d0826242899df7573721", + "chksum_sha256": "bdcbee1705c8ac319ba71af6725dad6164a78605bdb0da4ebe833539701f196c", "format": 1 }, { "name": "plugins/modules/wireless_dynamic_interface_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "256ec24d864d6e46e1379dd40e292a558a509cc4abb3948af7730a5d01256365", + "chksum_sha256": "47d74bea911de6d0409ee28fdc3a86dd205102460acf1dbe0dc057ccdf09babc", "format": 1 }, { "name": "plugins/modules/discovery.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "2f5200ccf2fe958bf6ea1b31e49ca942e561f763352a8b858a8e86a5058a7319", + "chksum_sha256": "831619571aa2f0c113400c8fa930b69f305fda6fbb8621dcb8dbcd871cd0a279", "format": 1 }, { "name": "plugins/modules/wireless_accespoint_configuration.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "b8289bbf4a1b7aa90fd2b0c3e3f178558a61e5aa5cbe86ee0ab2323c1a96bea6", + "chksum_sha256": "141d3a2c603c8b4f62466e0e6db45672bae260ae1a12f487cfe2c20026dff748", "format": 1 }, { "name": "plugins/modules/qos_device_interface_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "7c8c372defb3175519a0ed18ab65de12f7cdb7d6c42a83096022a163ea1843e8", + "chksum_sha256": "d3a84c0cb694ca3c097b9ff30bc976aa135a2ac91181afe2e38d5b187cb8530d", "format": 1 }, { "name": "plugins/modules/provision_intent.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "1edf799c5bace445ba47dd5ab7edac249819cded67c0c02c86fec3c6573aaf47", + "chksum_sha256": "eee5fd64e6ab7543062b2ec3750196a24c128bbda13be65068d0bd74750bc3d1", "format": 1 }, { "name": "plugins/modules/pnp_workflow_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "51b76732895b15f2c0b44f86a4e4779a7857003a67d61327c375e7c3217bfd97", + "chksum_sha256": "40f26611c60bf2ec8533a82785eee65bb2a247be209105a002f1cb1dcf7081b4", "format": 1 }, { "name": "plugins/modules/license_smart_account_details_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "3445ec738f2b098332069e43a52018612f20776e07fc7180d6a2756a4d67b6c0", + "chksum_sha256": "dd3bffa15d967017ca8313b2e75fa3c467b9282da5baaaac7360b5be9319a5c5", "format": 1 }, { "name": "plugins/modules/network_device_module_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "d3c2dc6102957c2786d7eef87a7125df8a1c6cc6232cc054bcd6701c073cab9d", + "chksum_sha256": "d99ee768d2564d3283b7693b1a9f9ffb30bba6647022d1d4cb41daf1b37cfac0", "format": 1 }, { "name": "plugins/modules/assign_device_to_site.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "66692e2cf30951ef15947042093c7609a875642c8b31559d0653ec95c0834cfc", + "chksum_sha256": "96e597a643befd67693dba086d91ae2fbae6986a98d2956ed112b8dc47ad6378", "format": 1 }, { "name": "plugins/modules/event_config_connector_types_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "534789a3e5be6ce3b9bdf8207b6f59fd2014db754d3a5e5941bd098b46d09f43", + "chksum_sha256": "0cddf97005b6d88a1880b132aecb16ea2e11cd52e1a6fb198f39028a3b961aa2", "format": 1 }, { "name": "plugins/modules/network_device_inventory_insight_link_mismatch_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "314220c437622968514032d5c5e995f9c2685135aab4efc15aabe5112d9e1363", + "chksum_sha256": "4d9fc23291299a4966e404b79d9df1bf8c30b038637111640b565c854a486d7c", "format": 1 }, { "name": "plugins/modules/task_operation_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "c03bb12584fd9811458a83fb3ce3be39d604e5098fa0936e0173caa6f4a0b7ba", + "chksum_sha256": "2ada3350d24c3f06eb24f7878a6d47145d565b9d87dfb5474da61a7c5e592828", "format": 1 }, { "name": "plugins/modules/site_create.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "54ad0d4f3f891b4ebdf0f568834b356ce3fae3a977d8707fefae8b7ae9681338", + "chksum_sha256": "a8389054876e4e0d52709b43e47a559882e808cfae93b3ece582d2854d7ceaa9", "format": 1 }, { "name": "plugins/modules/credential_to_site_by_siteid_create_v2.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "fe62a0861858da8c5534313962518b666bc95b9a9e2e931a29f815faceb16811", + "chksum_sha256": "6fd1eb16206ca007172456bf66824edf8cc86a7a9c21cd40a4497f2ee15347ca", "format": 1 }, { "name": "plugins/modules/sda_virtual_network_v2.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "ef032aeeb0615651230b4170cd3570ed98e1b02fcac89eb7ed1f1c0a5fb6ba62", + "chksum_sha256": "de5463a3e5a8c767a4620f2b0d6959f03e615c1662d9d1277e421df577515ffa", "format": 1 }, { "name": "plugins/modules/network_device_by_ip_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "9ac509acdc4c762cb3e857dfd580416711971ce107996a436319507b1c7cfa5d", + "chksum_sha256": "753ed26c0934c1cca81a58079b45b8a57e3987f8f7428c722ee906b8ffc35d76", "format": 1 }, { "name": "plugins/modules/network_device_lexicographically_sorted_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "94ef35daae89197a574ddc16ce3d40af9fee355571cb60c567d2d789615adb2e", + "chksum_sha256": "1ffa1d43fdac74ed390659d347cd2914d48e622ad97edf07136caf763d9bdeb3", "format": 1 }, { "name": "plugins/modules/pnp_workflow.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "5f6d1953dfc0f6c6e9888e743d725a644936e5a1dbc104638aa7b407d9493767", + "chksum_sha256": "3c927bafdeaeabcee4b03392cb8f833cee992c06df87392bc9850424a9a36f23", "format": 1 }, { "name": "plugins/modules/event_subscription_count_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "38b483efd2cbf485c0e7cf897d00e2d7bed3301ae35b7e7f2fe4735eef9a088a", + "chksum_sha256": "e3726450f73d3d9a369f6e13df3dfef8da2e6d13aad9070a8bf8101f3353f5ba", "format": 1 }, { "name": "plugins/modules/topology_layer_3_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "3be4779df4aca09518d8964f4031591abfd39fdd700b8a01375a9f77f5385cb6", + "chksum_sha256": "763bc8e38e403d4bf06b8168c4eb875928478eba61089dc829de0e0d91160895", "format": 1 }, { "name": "plugins/modules/device_credential_create.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "88f138a794dc5a42197fc455246f35a747fc5733fdecfec34d510813274a6509", + "chksum_sha256": "7d82073fb51ff17af9d0e94ae606ca0a20cad4bad8d0ccdd1fa308a4b4cbfbd8", "format": 1 }, { "name": "plugins/modules/snmpv2_write_community_credential.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "66d40b380a308d0c4d463e6c2afbd7e511401995c5ec6cbb8383c04850171174", + "chksum_sha256": "cd7292c2440f6f5053ef12fbf76b0a1b27989ec6263c20f2664504f88d867582", "format": 1 }, { "name": "plugins/modules/global_credential_update.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "5a29fab81c5dcc34942e0520555106d407c1d5be5ad2350ebe5bb2e3517246dc", + "chksum_sha256": "7eefe1e65619a4de2b2075074b53053b0c99dfa795c1142b28069d4fa71826d2", "format": 1 }, { "name": "plugins/modules/wireless_rf_profile_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "008c3081fa5cdfea7ec1c7c55005006cbd38ec279db7405d9e324fe4c50f3616", + "chksum_sha256": "a6ca9ea355c4df2052d03af05e398cf2d13b971aa7cb492c9fe69069d5fa16db", "format": 1 }, { "name": "plugins/modules/applications_health_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "daa4f710c924bb7cef9c5094f875555c9b805122f8897964e71fc4a685dd8630", + "chksum_sha256": "463b0623e0e944947016aef514f897154ab1eb1848c1b91f9a9a73c122757c50", "format": 1 }, { "name": "plugins/modules/sensor_test_template_edit.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "c61fd70d849e2635aabe7ee0681de73480c563c156852e93e3d6e49706cfe94b", + "chksum_sha256": "4274322757ed2a99ba127d28c92e6cda2f49f4cf031af6e97422a3a2783170d8", "format": 1 }, { "name": "plugins/modules/network_device_stack_details_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "28232e8cbfbc70dca83dd34983d61a61c07710425b037a846553e5102e3e1d03", + "chksum_sha256": "c55fd06561816f1bf354e19c0f8ef97fc2de5d21fe57d30e9953b7caac320df6", "format": 1 }, { "name": "plugins/modules/site_workflow_manager.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "d691b4d29437329a12425232c52a9027819b496ccd47e80e19a44fffcbdafc42", + "chksum_sha256": "4c0530303d930f81006f318ad9e9df5569163153476b53ba4c0a0fcffacb2b1f", "format": 1 }, { "name": "plugins/modules/global_credential_delete.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "5635804686b6c1dcbfdd600187002f55c99a6bb2ce33909b1b20754e773f0698", + "chksum_sha256": "87ca0d16efa2b308878513ca6be96c9d13bfc99c9f5218ca3742ddbb8b83fb60", "format": 1 }, { "name": "plugins/modules/sda_multicast.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "289d7dee1f62e05d7669940ea71920b41ed28aebd07dac84b53503d7c0e7c9cd", + "chksum_sha256": "399e17ea2b5769b4096df6b0a13a2cc0ffc7de4a4f2f75afd7f3240a3750884d", "format": 1 }, { "name": "plugins/modules/sda_device_role_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "f181e587c723787107c7b28b62249b768c61c6b660095bf72e8de1b2b156126e", + "chksum_sha256": "2060f3f260e3c7fca652b67872a6232ab819ba5d773c8a6c4d7036aac7de39eb", "format": 1 }, { "name": "plugins/modules/pnp_virtual_account_devices_sync.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "534814958e8c3ea6fc935dbd08d60571f10ee8ec64f234877a0c36334088b27f", + "chksum_sha256": "f1c8fed58d9c4d513773b7948e03b27765aeceff9a45a74759c07b14af8c4bc1", "format": 1 }, { "name": "plugins/modules/eox_status_summary_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "3596d5ae0791f33cf9f002543a5183b639fce9e502620a5f8ee08145d4c23961", + "chksum_sha256": "5a28ed446010d97b1f21516a3253120c0f0099619c7d033ca97071b20acd7988", "format": 1 }, { "name": "plugins/modules/accesspoint_configuration_details_by_task_id_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "ba466bb29584fc099e2839a25cd635b4807920d2ac6b5032bf5b62678b96ae92", + "chksum_sha256": "b5d2c060f6664ccbf75f82150a414c8a6b18a6eb801346041b3233bffe6f97f6", "format": 1 }, { "name": "plugins/modules/applications.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "3c687ea107d2c34cb1eed2256c3beaf1ec0bc93e9498b860b0260a2903bf4ff9", + "chksum_sha256": "426447a41c87ed84cfbd9c3ae0830ddafcdaa68a3c6aa732c74a27026e936daf", "format": 1 }, { "name": "plugins/modules/itsm_integration_events_failed_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "f2236cbf493a04f2b417951e8fd6c9aa12221a42489679b7b8b6a7afd23458b2", + "chksum_sha256": "407fc6cb6189f1403844e652bc64ff03cbcea66f0eadd3775185b7487f3f986e", "format": 1 }, { "name": "plugins/modules/network_device_user_defined_field.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "0c8f47c86bbb2e877ffe5c6c91c5e717650f66d4f2e86e641cc767c8d2a64d51", + "chksum_sha256": "a3357526777edc63c0663320959ec9c1d087e5602793111abdcb2d0b8602b4b1", "format": 1 }, { "name": "plugins/modules/configuration_template_export_project.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "f077d02ea1cfd2971e35cc6b7e8338e5115f7f6ccaef66d001bdfcd701e0b645", + "chksum_sha256": "58a0750f67b1831b04ad09fb602f4c47c264b817ff995c0c8ca468f3dfe1e2b9", "format": 1 }, { "name": "plugins/modules/reserve_ip_subpool.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "40e4454daa55dc0975a3d1edb6192132274686870f7a30d4e3b78ed746920faf", + "chksum_sha256": "b11c7cc628c5b50c93abca9d675e14acc91074183dd68e6eb4ecedcc093d1747", "format": 1 }, { "name": "plugins/modules/network_device_interface_neighbor_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "859bee561489a592e76de54057ebbc7c566a6c8740051c442d8dd329b67e20f5", + "chksum_sha256": "53b55d54fc692e05378ff615c491c2a4c25fa58520ad616af7fa18831011036c", "format": 1 }, { "name": "plugins/modules/device_credential_workflow_manager.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "f2a4e13de9da183ced28ef4ff11c9036c76fcd474b760af56f4d40caa449f16d", + "chksum_sha256": "1f9eab5ed7aa33debf4b7652aa0b117b7b6786d538c550bb2999878cdd85d29c", "format": 1 }, { "name": "plugins/modules/network_device_polling_interval_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "2c1c47c56f5d792bd03e85ddde3e0a2538a01f31aba0814c34074438aee07255", + "chksum_sha256": "6a8f3d47966abc700d31c6ca0834ec60f94cad60422f3fcbc8d43e7e13ae620c", "format": 1 }, { "name": "plugins/modules/network_v2_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "29b1e3bd4541c270be72ac7819940415855965505e5254723cc5e438835db48c", + "chksum_sha256": "5a831b1065c921dc1a98ab5fff748a83b6322e1ff1d7bf51f4adddd921ea9440", "format": 1 }, { "name": "plugins/modules/tag_membership.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "9d5ec68b09e4009577498372d660f5d7b2e597cd0cad41017553061a1c2cf405", + "chksum_sha256": "85e2d7164b26e761166d4f04343289d331610d2bc62665b1c2521354415a7893", "format": 1 }, { "name": "plugins/modules/profiling_rules_in_bulk_create.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "4dedbb18660f9611d8de15bd78df9b0bff8263e74d67fb5d5f8cb9c6e9bd605c", + "chksum_sha256": "3e79aa1f0409bfdd17aa57ed69a7626daa52c510ebee3a500f760983a4723e25", "format": 1 }, { "name": "plugins/modules/event_artifact_count_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "b6c3f785d839db3db95af4cae1e5a5698bede3dccbb89d69ff9783a37f80121e", + "chksum_sha256": "6121fe9593a6fef7f9870a196e4a201cd138337b90c1726e20a0056cc82552ba", "format": 1 }, { "name": "plugins/modules/network_device_module_count_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "9d7ebf4dd462a77b11d973103227958da46700fae8d9617747297a65a8acc2af", + "chksum_sha256": "988dd211b76c628305d21acdbb3a4f1a59e716d819d3ea5773f1994b79823859", "format": 1 }, { "name": "plugins/modules/global_credential_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "a49f82933150a1a09572081a72c7d2325b29e195b71da8b89f843c83156c59ed", + "chksum_sha256": "bbeb591b1502b1f63b91404301e266e4b66bd157ed4b03934ea77ba4ee096d66", "format": 1 }, { "name": "plugins/modules/pnp_server_profile_update.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "2da8840d0a28503a26353de3b410390f4d65fd6c8980d611dd45e491daa1b7b7", + "chksum_sha256": "1e88323ee47995da579c9263e3442833b08fe47c68de3e86b8d66e3d3e38b2f1", "format": 1 }, { "name": "plugins/modules/projects_details_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "2ab5f34c01ee5d2655d2c5136c12033914c3fab2726dfb8437ee0de5af571aaf", + "chksum_sha256": "8291f865748dab5754228e60da5e2321ca6a1fe8cfb14463b51df1e16427f3b6", "format": 1 }, { "name": "plugins/modules/authentication_policy_servers_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "d82fcf066d29e5d6b758d72a23e9cef7a91ac5f1c631cb77e0ed469b41a2b120", + "chksum_sha256": "1551391c2a66ef1bbad5408128dca9846f792337a583af80269237b310933101", "format": 1 }, { "name": "plugins/modules/pnp_device_claim_to_site.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "a16e99cea123c0bf32450cc3153a826723b95523946f9a293dcb98130fc1f522", + "chksum_sha256": "1362012e0e6134286e284fdbd89fd8493b4fcf6271089de7c40a307340131789", "format": 1 }, { "name": "plugins/modules/applications_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "48b9d8878343b80673ab59b4e95b98a6fd1cc79567f04b5e05c810f848746f4f", + "chksum_sha256": "a821bb44a947903868c0d3fa718b64e09d87825e856aa8512bea8295d55b6b20", "format": 1 }, { "name": "plugins/modules/network_device_wireless_lan_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "e68d7e70c4570b17440581639eea6b46945d54bef49deccf2edf881fb096838e", + "chksum_sha256": "0a5b00d3249e3bf2691cb50f8e6edf843fad6e3a0cdae63a57bf5cd72f33d15b", "format": 1 }, { "name": "plugins/modules/pnp_device_config_preview.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "8e32fb6de985448dc5a125315550f0ee8d8fd2c08d3f9e232782e944d57a4b08", + "chksum_sha256": "019be448c8f8e4a283e68e46cd79aa30a826bd9b83eef9280c60ae617696cf76", "format": 1 }, { "name": "plugins/modules/path_trace.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "9ba78935fec396d6574c33755dd9ff6562f1868a5e49ed80d2bfc844e33a0a0b", + "chksum_sha256": "99068699100cf4e24c2dfaf1caa2d8d6fe150a9762a6bf318af532574ac56148", "format": 1 }, { @@ -3924,1722 +3924,1722 @@ "name": "plugins/modules/device_replacement_deploy.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "7d292b3e8eefaa09cc699f47c6d8dafbbd30ea35397a4b5f31a0ab5bc6cb9548", + "chksum_sha256": "ecdce508fbb0473d0784e3c159cd76ff6b07cdeb999d54c825ed2b25cea9a0d7", "format": 1 }, { "name": "plugins/modules/system_health_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "8006a53552f482b3f3f97188885c6374861761702f5aaebecd8f1e317eeee1d8", + "chksum_sha256": "1f325dcf5afc01848e3d7b1619a670d01c12d0624c7a1ca8db4c2e4a535748ce", "format": 1 }, { "name": "plugins/modules/app_policy_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "3c208b9ec193ffe33c13897aec059032575aabb44c8760379a4896a420e7333e", + "chksum_sha256": "7b625c39fb2a224fe7dd3b91b30646ec3d12b2bd697083fbe05e43271c7081ca", "format": 1 }, { "name": "plugins/modules/event_count_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "d2cf1e4bffddc28c9b92529804c9384b8e64fe4635ebdc7ca8dc4f98cab4d8a4", + "chksum_sha256": "8e3591a1fb3519b884c967564907eb4af42118c1f6c8c91afd311afde2165c41", "format": 1 }, { "name": "plugins/modules/client_proximity_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "074df4c86da99d225d3ebd2d85347c57d9e9d27054d7de171c018cffa286c721", + "chksum_sha256": "9bbbdb160591c895f91d752f917ba887c17f298a6c3f4248af59cd5b09cc8696", "format": 1 }, { "name": "plugins/modules/tag_member_count_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "7906513bcf9e12ae42e8a036e4e7cbeafb95cef6912212f9d0a46aede30ffd21", + "chksum_sha256": "411390492f0e57f70f66d25bdcf722016ff30f769f6afdd849ed2cfbeb67d6d4", "format": 1 }, { "name": "plugins/modules/network_device_global_polling_interval_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "c2d226f1d292ef76f50bcdfa9d41b76f6c052df80eb4b8419f1264705a282f91", + "chksum_sha256": "67732485524ac9a2b11fb8cfa118cfb4b66fcb191fc69d3f372b5c5c49161593", "format": 1 }, { "name": "plugins/modules/application_sets_count_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "87e9f963c750e336fad6c6044849fd70e2ff7657b154d0ea0023df9a3287c6ad", + "chksum_sha256": "829d68acb8ef33ae1eaad98e5391fdb71696b9785f5800779e603a1e4e0c7680", "format": 1 }, { "name": "plugins/modules/wireless_provision_access_point.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "f49c90192930f8c36a2cf691e1fb1fd7fbad63692fcbd0573b51f8d91a151186", + "chksum_sha256": "ad1add88dd3f16ca410cde9be6c97e4f62053ef92fb5b0743fa31227d9b6a473", "format": 1 }, { "name": "plugins/modules/site_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "71b93dad486934d8706d7d854b303fabb9f36316536e1e3b7341303ec2aaa684", + "chksum_sha256": "a51b7f98adbe7d53bb7ca70b73b059ed10c1f1dca1b01677375b506be41a18f1", "format": 1 }, { "name": "plugins/modules/pnp_global_settings_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "ab1409f92e774337e260796212688bddd73804a4f87da25ac5050cc5c15456ce", + "chksum_sha256": "724999fb1b00383d5ade1f29a5ee65c66f9462a26afc04636bf17689b4be6699", "format": 1 }, { "name": "plugins/modules/planned_access_points_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "d8eeae0466c7d4abd531085860fcec1544dff0be9bf6707c2ce133081322d484", + "chksum_sha256": "5425befb5c57fc61d2a57040fb4328b4cc9f208704a1d53d336d4dde18158138", "format": 1 }, { "name": "plugins/modules/event_subscription.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "ca27b7a6a525a197cbf24d682e839a372c988520297d2406093fa1b23269d993", + "chksum_sha256": "8f94beb2a6d694ecceb446365140c0a98b53532947f417eae5a506ca772c9ffb", "format": 1 }, { "name": "plugins/modules/disassociate_site_to_network_profile.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "a57099910d732a1081521b0586f14ba568f38b56f18cdf9f84d7726a25fc6b78", + "chksum_sha256": "9e719471dd45977103c51c3adea0b01296b0952f8229abccb9da232af87fb5c7", "format": 1 }, { "name": "plugins/modules/security_advisories_per_device_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "510a8d32961299a16d6901f64f7a0e4830efb08196d08cd633b1ae4d80595418", + "chksum_sha256": "7b8e497ab8f7a2c4ffc741c01c97b24294c0368afab2ea6a497a1c733f8f5aad", "format": 1 }, { "name": "plugins/modules/wireless_profile.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "bbd0d63fdc3b88a7382790da0d74397f1dbec93156adcf730459d94060bdad90", + "chksum_sha256": "b9a3286b939cee7d41e926459c389371eb71712704f2cc80cc62d5d4c030e12c", "format": 1 }, { "name": "plugins/modules/authentication_import_certificate.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "95ba72943a0e100576a8dca2f24b42024451108d1570e63a01a241274f6e88b8", + "chksum_sha256": "f25ff63970622b3ca833b8d9417934f11ff1a3ce0c67ab48c094f8679c440d2c", "format": 1 }, { "name": "plugins/modules/sda_port_assignment_for_user_device.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "2003691a23f90ba8c744a45d2652c60b9bf2296a61203c1d14cea140f31ecb0f", + "chksum_sha256": "0c5b6bb1caa7a59337c0d2cf2f7189dd89d6d75af96aedda38735d4a57addc17", "format": 1 }, { "name": "plugins/modules/site_delete.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "7f87362a1180c33a0958bd3cc6a9b5282acd363eee262c988470b1b6bdb0aa89", + "chksum_sha256": "136244729cba0e4ee3c153b5f21b303450f51775a19424b9f4ae5e698b827f56", "format": 1 }, { "name": "plugins/modules/nfv_profile.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "fa6d9b1c6d23a665849933dae5d506fbf2f12977d538afe65defd166e7945176", + "chksum_sha256": "a925b77fe717b8b23909239509a9afc244f7df072c5c010207d2a83d8b7bee65", "format": 1 }, { "name": "plugins/modules/network_device_range_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "3a4d0a3e5d09e7a1101073a7f8f77bd740df06fdb9b3156e533fd83edc598475", + "chksum_sha256": "8ea25e0bc3e101c707b72dc2caf814118f067175f3dd28c8dd7c630daf834f23", "format": 1 }, { "name": "plugins/modules/network_device_custom_prompt_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "925594e1d3ab4d227f727dd2ff4f6071ddf7fa3ba370ef89012e727dd03c5b5f", + "chksum_sha256": "ca6368c4d89bdf14c64cb4e719cd206d0758038e3ff50db8ac29c7e7ea037cde", "format": 1 }, { "name": "plugins/modules/pnp_device.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "0315da3f9fc9553e61cd089e24427ca21a4571f93c6903dcdd7eca94de895a26", + "chksum_sha256": "87b4e7b1a8100d3b3165455e59e9a80bb82790ed58167253d8e893abda8292a0", "format": 1 }, { "name": "plugins/modules/license_virtual_account_details_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "4a14f345427186acd7cd817934f77ac1b9a220b9d8b999d747c03f8595d85bac", + "chksum_sha256": "0fd065702a56e2130a33816c8e4fc626cdce32c14785b1c06a20605498c21bd6", "format": 1 }, { "name": "plugins/modules/device_credential_delete.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "e871368c6d1375f33f853132e5f5653d1d25ca48fdb7cb5d5580df72ce197a97", + "chksum_sha256": "73611279350c75b42fb90582f76fefff1ab74f85656f49b715c412cd9eacbeb4", "format": 1 }, { "name": "plugins/modules/topology_layer_2_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "f29d376c210c83aca735d11614f22ed9a4c9ca3fc97998d65b6b84fb95a1d4e7", + "chksum_sha256": "9dea8f1c6b0b8319a453be363cc0162ca525538b313d05c03e5cb8139d4b5ba4", "format": 1 }, { "name": "plugins/modules/threat_detail_count.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "b6d4604c1629ee70e899f9907aad240e7698f1895e5ea0d12b4ddb8b466d3981", + "chksum_sha256": "42588fff16510897afde5d58916f13e4201dc8dbfa0918b01004b96785d6fd95", "format": 1 }, { "name": "plugins/modules/device_credential_update.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "bd2fb6aaee258088a4be03ce7b497590c53079a30d97897665a483001de952c3", + "chksum_sha256": "277c1c63c75d3ed29a244a143e5aca494b04346a27e56692c180f810d4fe43ae", "format": 1 }, { "name": "plugins/modules/device_credential_intent.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "66fa8406e7af3248eef9be43a7e2ce267d81eb478ea00755b9531461aca0d961", + "chksum_sha256": "9c7b1a9f78eac8b641fb6360e573adbd30e4703f93f0d79a994429d425076c7b", "format": 1 }, { "name": "plugins/modules/site_intent.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "81af801ed37704ab603d8d0531a78bef58a8ca2994e4ef0f09d6ab6fd88e97a5", + "chksum_sha256": "b1faa8cc81d9795cc1f818b0af82b399b096d6e1271af4152f9c83ac7ea6e98f", "format": 1 }, { "name": "plugins/modules/site_update.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "e1d4b175913d5f99f4a24e42672c98918d8c524750e97ba97d633d1aaaab0f77", + "chksum_sha256": "73ab43253acb3ae2b8e09d59724d762048c28945898d998f69df3d73610fc6c3", "format": 1 }, { "name": "plugins/modules/network_device_user_defined_field_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "97ac775b499496379b6591c51d6d5ee1dbb3510715234ec127df1935be15ed47", + "chksum_sha256": "c8510f70069c4aea3bb52a4aaa1a5ca8c1aa55d4e31efdb93a9f5c9e12853c36", "format": 1 }, { "name": "plugins/modules/http_read_credential.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "6f974bce513629e3badc474d280670460b34b945815c1dfec75874846c72cec1", + "chksum_sha256": "a9a2195ab6cdb6dc40a885de01e3601ac7553a503a6cf118bd4d0dc1e8d81ba7", "format": 1 }, { "name": "plugins/modules/compliance_device_details_count_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "8883b487fb7f4e894814db5c066ea8d62bcb9bab6eab77c1e65f8f41dcf59dad", + "chksum_sha256": "94fd67bee2ce423dd2be0429769caa55a9ce461541108767f66b44e76a81b4ef", "format": 1 }, { "name": "plugins/modules/swim_import_local.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "8f56e87c5847d17450511876f9b1030e8cd0e389e4fcd26d8197531e649672ef", + "chksum_sha256": "fe5f9c42b91c809caad535b1e7070e531d246018b17bd37122ac2f165d547712", "format": 1 }, { "name": "plugins/modules/dnac_packages_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "d255616ea04f1d4f2d0d3a756b5345a3a76846e07a4fce3939f68e214a7c4e7e", + "chksum_sha256": "78752569cf03879b371c78c9c16803553171fdcc3deaef98505cc77752414ade", "format": 1 }, { "name": "plugins/modules/configuration_template_export_template.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "e035fcfb51ca192b8d1e4b7658e78ee2c336371b02b7ec9f5011819bbb4b73dd", + "chksum_sha256": "5ede848070ed4d186baac3dda19d2a89dbe84221bb4d44d3dee857e1c718034f", "format": 1 }, { "name": "plugins/modules/transit_peer_network_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "feec3917cfa16d8a5d36ca23b0bba5e94347a8d73bcc35647d6c02166bf7a02e", + "chksum_sha256": "563a9bdf5c6166c9e5abf1a8433376eca11180c07f544b302928b3be534dddd9", "format": 1 }, { "name": "plugins/modules/wireless_provision_ssid_delete_reprovision.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "a3fec6fc6428f9488499b493a82f5b511f608229c4d6bf744fd786764045ff8e", + "chksum_sha256": "1c3750918a721cc0820f4a20d127c944952a770968ecbe3dbc64a00d5b559832", "format": 1 }, { "name": "plugins/modules/sda_virtual_network_v2_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "1b0b6479857fbe6389b251c011365a9835d6978b9b773bc2d97a11aed13413bb", + "chksum_sha256": "c50256d12da60d7e78fd69bedbdcb5997616ad8b47f5d326124af10b9d49947f", "format": 1 }, { "name": "plugins/modules/event_subscription_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "32494ddbb9d39f85db2be63c47229e3b05528c542375e51ccf956faced80797b", + "chksum_sha256": "d716dceb1475a191a63d5ccb8d6897102a5bd5d3f345c1fab109fd7056f478be", "format": 1 }, { "name": "plugins/modules/sda_fabric_authentication_profile.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "f369c0441b9669962ed4004da63dd8f917b39d17755d68c1a755d40f6fdc4246", + "chksum_sha256": "0f400cdcf47e1f8a7767554424e50fd5573b8d58fe3c218b54d27ae3f93eecb2", "format": 1 }, { "name": "plugins/modules/discovery_intent.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "5d4d5d62ed389c1286fcbc13ecbb47790cff49e0c7ae12b8ae0dd313963bfd7e", + "chksum_sha256": "9d917e426c5ab41b8346699d99d920e4764d687992add75011f21be9326eee38", "format": 1 }, { "name": "plugins/modules/command_runner_run_command.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "6693edbedb0428d946372c9013ad5e347aed94992308d5617fa1a4cfcc76fb45", + "chksum_sha256": "5eb5992001e9431eb08775d3845169a2062b842aff1b3735a41dcaf470c201aa", "format": 1 }, { "name": "plugins/modules/sda_fabric_edge_device_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "5c78801500b503cbed50ca503b398dcbc0e2329f22be2fc9e8a8abf2c33fed07", + "chksum_sha256": "997a913eae617e9210e6db7efe98cd81284a81bf23f5c3909297c7f389f7c955", "format": 1 }, { "name": "plugins/modules/client_enrichment_details_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "fa48ef333815f9c0d2c1cc17d98c980359463ea002eff33dcfa7858f6ded2329", + "chksum_sha256": "2dcfc9666186dd28a0758aecce6e8ef4c8261f85f4d312b7d9874df8b70ab181", "format": 1 }, { "name": "plugins/modules/discovery_workflow_manager.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "2e4e1f1c128ca5334ed627854e7af56a330e09f7fa7bfd2e20605ad215879e25", + "chksum_sha256": "7dcecd303f5b7e180e64e220ec5c1289e0e97f7257f28292f4863a10174741fd", "format": 1 }, { "name": "plugins/modules/event_syslog_config.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "0e275395b5ae661de22e64c9c21bc10f0f3bc07c88dd0299560d2bdb6e3c2a73", + "chksum_sha256": "0bde247c5caa064449e0633732bbd312497e3e0f69aaede6f9c15f155016e214", "format": 1 }, { "name": "plugins/modules/sda_provision_device.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "285f1ddeca25ad12bf753ee7b7e3ba5ce8749e652da0549a87cc6477b148c8d7", + "chksum_sha256": "16c231a9de2ccbc861b11a5ac41c8e438669a06cd0988eb9db8a406c870d7fe7", "format": 1 }, { "name": "plugins/modules/interface_network_device_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "ad46cfa858fb72bbd15702cc70ccf3d59c2960b601062e2cb1448d5c947d8d05", + "chksum_sha256": "7151fb0da471791cf5ce401fcb5c7779376f045a1e77415752c75f6281b7e700", "format": 1 }, { "name": "plugins/modules/reserve_ip_subpool_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "fb6c6f881f932f4955b0d52a5393dccd1fa1a7f3570f2ccf5219dc0c72fb1fad", + "chksum_sha256": "0e23957ae461ad94694930f6dbcee49f15a66e33a5482b7260c77f0f548a72e2", "format": 1 }, { "name": "plugins/modules/configuration_template_version_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "5c729bdf17c3f58fe8cb07c05abe38b6eb7212f54b780ef862a9613768ea52aa", + "chksum_sha256": "6db9c81a5e9cd3a66121eecc8e5b87b4265cb9a410bfafa294cd080d338ae6a6", "format": 1 }, { "name": "plugins/modules/dna_command_runner_keywords_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "43318675e447145e40a85a72914d396af2d0a28f50e973d04452fc7e74e91866", + "chksum_sha256": "65e79488afa4ef3820aab5e915a0aab9e578bbf7a31a2bbcf908772bbde354f1", "format": 1 }, { "name": "plugins/modules/tag_member_type_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "a27fd34a02e877fbcba7fd2391212254f28990401fdd87de10662b669ca6219d", + "chksum_sha256": "e03ef4a4e4b6b6c4eee059129aeb0a87d675065c9f3289923b3b9db6d8888142", "format": 1 }, { "name": "plugins/modules/cli_credential.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "94eb8979f9fcb0bb622e23ee6d689f4dd067d70e5f92f369f79e5fb270845d98", + "chksum_sha256": "ae8078d2bc7f17fa3946400f9d9f91cbac2122cb0af50814581524065edb4983", "format": 1 }, { "name": "plugins/modules/event_webhook_create.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "cf60d61cae706455b9af76ab05c54186e1dd50ae6f5e0e11f63d642e75179ffa", + "chksum_sha256": "3327f4d0facc8deca05dcf652187bce2e0b853d251febe9a45a6532204d3b54c", "format": 1 }, { "name": "plugins/modules/license_device_license_summary_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "2a77dab6f909264faa05dfbe955a80d85f6f7bd7fc8fc0d903138ac581352e34", + "chksum_sha256": "03459e80c875ce7f99aed01d53b079418711565ff526edf4a4aaaac686a8641e", "format": 1 }, { "name": "plugins/modules/role_permissions_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "58174ea096129749a9c9cdd3659fd71434154e4fb988ae66f556835b286241cf", + "chksum_sha256": "53d012b05cc0d04388db377e9f987708362162becba7af1dbb233502fe8147e2", "format": 1 }, { "name": "plugins/modules/device_interface_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "fa5e221ac6a7c0df2c6ef63401b0457b5647c3aa69ae4b8ae21ddc9bc506a8a1", + "chksum_sha256": "90eacd9d08fd01b5d978f44fcda0d499c6921292a159447b81800c5d17eec4fc", "format": 1 }, { "name": "plugins/modules/disasterrecovery_system_status_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "92f315efa7b89279e8f7b192c09ff8a88289fac4b59cc7691a2e105a69216b0c", + "chksum_sha256": "79a90ecec047649cac72b3f47f3311c4c9f31967bb50d8719e2f995377fcd2fd", "format": 1 }, { "name": "plugins/modules/device_replacement_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "33735267f9937053587282f65594631dedfc3fd9fefcb36736d80f0495507f1c", + "chksum_sha256": "72ffc7e99647b8d75827d26f188dcf5ac046d25205bdfa4f378dc948362de367", "format": 1 }, { "name": "plugins/modules/pnp_virtual_account_deregister.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "e8a6700ff0d2530ea16147dc5e64040202f2ee8e66d953cd8ee05375a3b6e442", + "chksum_sha256": "cc1ec82c0edaa6b470c3b047c52521e927b7b8ce2127802656ccb5cf7a056ff3", "format": 1 }, { "name": "plugins/modules/configuration_template_import_template.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "5667f04a13569fbd8a4b026e6e3f97c4ee2d40928a96fefb560c3e37bc22de8e", + "chksum_sha256": "1f3afd88bfc842a3254fd93bd5c5ac2f77bb3d42e36ced80809454885c54c290", "format": 1 }, { "name": "plugins/modules/pnp_device_count_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "ea228c564b4efc6c40fc9dccf20d8911ac984a954ffd9a6fb9f1d45da7693214", + "chksum_sha256": "05e9933ab8d49d305e4eb8cd975eda7201d0a7907a22fad8c41aa1792e0ec3b0", "format": 1 }, { "name": "plugins/modules/event_series_audit_logs_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "3c9e1a8d9825781f9def1f39c11306f0f9ee54d6edcc9ec797f698ac276d2855", + "chksum_sha256": "83db2fba5b867f93003eef05e77dc06cae596077d8031cb8e4786412835b09ab", "format": 1 }, { "name": "plugins/modules/service_provider_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "0c7c9630a8057f22c4e21b28165db903ab8437dda7d8980158a6feb7b32d907e", + "chksum_sha256": "7d17180dc4cd643a09611991cf2043425189cb9a73c6f59065981d8281b3ae87", "format": 1 }, { "name": "plugins/modules/event_email_config_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "967f7df7906c17e63a36b6389de1778caf882fd7ec68bd2848047503734d81cf", + "chksum_sha256": "a2abdfc66a3d67f00d17e810ee2d13570ca3539a9ba9a9720bd472194317d31d", "format": 1 }, { "name": "plugins/modules/endpoint_analytics_profiling_rules_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "cbd6b5f88a5e9f37a80e02b713ebddd6d493d451370323bfb1b6dbf7a5b1b579", + "chksum_sha256": "1cf4ab1ba574bb96b930fa6d10bfee4a8144bb410ea1411a57a009907e7c273e", "format": 1 }, { "name": "plugins/modules/system_health_count_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "5fafcf66ef848c98360eae0deefb190fcfc26b65332e7285f11d6b31bfef862f", + "chksum_sha256": "bc062d3bcd58caca91751be0e30e482f8922ab7b740a95dfabcb3617abc3eb7b", "format": 1 }, { "name": "plugins/modules/tag_count_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "2b4ef16e18f7349df46dbf9d5ad0ddab34dcc3243d591021c19e363ce1fa45d3", + "chksum_sha256": "84b58cb1ff6b7051130a080d0cc358d184ee463049814ebecdf4b87f0d13c3a8", "format": 1 }, { "name": "plugins/modules/template_preview.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "5e0dbff7da5368bb3e8cddf549478e1a017d3436dce0c7d2eabd6946aaaa64dc", + "chksum_sha256": "0767e4f700a883074575115d80e90a55eca61ecd684f7a581f6a3e449892ecd3", "format": 1 }, { "name": "plugins/modules/sda_device_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "a1863286578d1d7058c66030f5196c6d0d5c31da4b1a769b4c0d86fa6350fc93", + "chksum_sha256": "9ceca94ff68b9cce8a259c9a202302eccabcfb1a6624406cb19d669a8134eaf1", "format": 1 }, { "name": "plugins/modules/network_device_equipment_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "41828a661d23590cc8f7859f8a9cabd4a450ecd413871feaac70cf6a9f080b1d", + "chksum_sha256": "a894f8ad27d154d6bfbb8457a9925bd20efca3313133dce4a6a4f50d3e692a23", "format": 1 }, { "name": "plugins/modules/sda_virtual_network_ip_pool_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "06e5e7b4126e3f5ec10d5beafc32c625c57468272102dc7ace67fb658ec7e993", + "chksum_sha256": "a8ef7391bb0d784b2959a69bad9a6415fee524d07b7088f218d11d9e61ae386e", "format": 1 }, { "name": "plugins/modules/lan_automation_delete.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "3a1c5fc9af9d3a406faacfd220afe0551f229cd79c11a749d10ed70c07f0a6ee", + "chksum_sha256": "fbeb1f2b815cc579dcc630713ccfb5b1683195d17c0002303d9929e73a5d3aa3", "format": 1 }, { "name": "plugins/modules/app_policy_default_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "7bf88c2b9746391d9e7f43dc96ad6dcc1d874426c718031d3eb97d6d97267d3e", + "chksum_sha256": "046a8cc036a2f26035e3f993e5f576648e1bfcb59f651a2f74e724c7bf292395", "format": 1 }, { "name": "plugins/modules/swim_import_via_url.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "d017455247056b195a47ea156a9d6cff5d37f9d77876109af39b64e9f56f2db1", + "chksum_sha256": "5d9113ffafc2a9fcf72f4aa671f970b5b86383e6e582eee1d02c00ccd4d2518c", "format": 1 }, { "name": "plugins/modules/business_sda_hostonboarding_ssid_ippool.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "6bbf473a0e595e7c35cd39b42268bd3a1527160e7badf498a7c4f71d9dad392d", + "chksum_sha256": "5c0381440528dbfc720d6914c6f68260a7ebf3d5aabd832fec9baf3bf4a048fa", "format": 1 }, { "name": "plugins/modules/event_snmp_config_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "8a35d4a47816981688a1c29e20d6c979a96bc4c7dfceb39ec0c03f34489067b6", + "chksum_sha256": "8526121f3e913a218cd02fa7c4e1b03933c00ddf54695823e555db7e4790f15c", "format": 1 }, { "name": "plugins/modules/snmp_properties_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "67fa7347d7fa944367c449e70a381b6b7985d70ebb1d6af1b4b9c04f750b1f23", + "chksum_sha256": "dca676e7508f5ecbe4760a4d25fd75a388cb7088ea113a4368e19af0807cfb16", "format": 1 }, { "name": "plugins/modules/event_email_config_create.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "ddb249265a519600ff736f4aba950bcc74cb19d028a931003fd646a48f9b1f8e", + "chksum_sha256": "5857874a63efdf544c3bd4cfb5a23506e4da8080c05b18ce624086f3286d3e10", "format": 1 }, { "name": "plugins/modules/swim_trigger_activation.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "a73de0abe28f85f254f25b162a90bf6257ce1aad5919d0926c3ea4858bcf4b41", + "chksum_sha256": "6fe55c5f2ba712ff8405ac65db4eebabfe1fbf783eb2384878a93ab9803e2c9a", "format": 1 }, { "name": "plugins/modules/event_artifact_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "b17b5412689f0ba4a9110408bf017008239bbbe59a79ec69090832d2808b1afe", + "chksum_sha256": "0add74d4a9abc68435cfd8f2b2b0a2b12e1e41083734982e74e697c8b10e272e", "format": 1 }, { "name": "plugins/modules/template_workflow_manager.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "9caa9ab726bc593d6f485fbc3ef43c41b614feb8328f91cac1d8367be9fdc49d", + "chksum_sha256": "b1b8ec891e44e539d660034f5f3edd7caf85de970139b74f93addf8e82031f99", "format": 1 }, { "name": "plugins/modules/discovery_count_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "29aa559fd96e7578de9db42769f08911f4c1efc84caf93e217b6572cf9bf7571", + "chksum_sha256": "db50b48430f478eeefcb50eaf426a91bc350069fd637a6fabcca8aaab30970f2", "format": 1 }, { "name": "plugins/modules/nfv_provision.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "b175e23ebc0049879fa5359073468dea940d2a6a3489224346616af87daec898", + "chksum_sha256": "5e161b58a0aae21985735aa16f1c51aaca68993bd7cac8496ccce7caf119bf6a", "format": 1 }, { "name": "plugins/modules/wireless_psk_override.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "ab739b1e46a232a91712806b019ac0dce02cd0fa555e4033c88229b80ae2d334", + "chksum_sha256": "699f9ea5227ec33456bdb9d0f1f87394f8b59962d2668134a4bb69e6088abf20", "format": 1 }, { "name": "plugins/modules/network_create.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "a59bf7039e1388d3ff8cac28791369851aba21465d55c1910663424a3d62daca", + "chksum_sha256": "d84c316a8dceab645376ca2a12c460fc08c131fbe8cd7a09c08442c1e6b707a7", "format": 1 }, { "name": "plugins/modules/event_subscription_rest_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "1f973f0e7a43dced562bfd266f68e66045fe2dd4d14523b5e542c5573728c0e1", + "chksum_sha256": "c183256389b8cd164b134c25172db6fdcd71e87da6e0793fe08c6d7b87afa656", "format": 1 }, { "name": "plugins/modules/reports_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "480d17d062b11d8f274124495b1ebf9b244ba521065b876a25ee402856649055", + "chksum_sha256": "2b8e90dcac98a407cf1f544cd4d204b9f8bb2f6716124f66e915734f3fd90803", "format": 1 }, { "name": "plugins/modules/lan_automation_create.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "c6dcf7b0a91d4cdb01270b635b87bb130b0f27e29505c90571437c8819a1ca3a", + "chksum_sha256": "ef5c835136ea31887795cb4ae057f13b305d34d5cee5fc83e29a4d77d6305e31", "format": 1 }, { "name": "plugins/modules/http_write_credential.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "bb124c888769059679d8464d8ff965d5252ee901c2d054508c9068358280b864", + "chksum_sha256": "a8a0f2c951bf025923aec39680fa8617abac532db668ad2627bed2937dc8084c", "format": 1 }, { "name": "plugins/modules/device_interface_isis_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "931764d35f07b5508e4be6fceb914e7b95fd920e14d7fb3a24aaa95a564563eb", + "chksum_sha256": "297b2c6a01e75055f148b270fef9ec1e3811b1caa4db452a069a1090bb3f7683", "format": 1 }, { "name": "plugins/modules/sda_multicast_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "f20dc250d7217a17a6d59764cc1b8900235beb4aada68965d9563eb3fa7d9a12", + "chksum_sha256": "8625b54c14c546a997b89d8b19b760f53b56acf941c7283786220ea0cf790e3b", "format": 1 }, { "name": "plugins/modules/topology_physical_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "95278a7cf5f0e98e9a4c0ad56e129f4b6703c06ed6fa42f09d51b692687694b0", + "chksum_sha256": "21ea3828b12100cb2d63cca9a180288f62a1bbd7c5dd4bef18317f7f04136210", "format": 1 }, { "name": "plugins/modules/users_external_servers_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "b7276641ce82a3f1b92e1411603569c75668d1693e3d3c2af4cdccf4ffc594e4", + "chksum_sha256": "188dbd8a8d337ac460723c1a0d54b4771acf9185668793df472e3ae123662584", "format": 1 }, { "name": "plugins/modules/security_advisories_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "dd688ec7abba9d0d478735c0881f4939a616107a230993322e5e0037174635f2", + "chksum_sha256": "40b7ac64401d1b2501ee2520c04da1cddbca62562bb6a1be4c4495a092fd417c", "format": 1 }, { "name": "plugins/modules/configuration_template_create.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "96c81ca8e425485289a75311a12658afd145d6d76b17da98d2bcd0e461e9c171", + "chksum_sha256": "cbedabf444a6db5481f4cba8e0f9c15f7785437bcdccd5119364dd2fad886879", "format": 1 }, { "name": "plugins/modules/event_subscription_details_email_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "5497dd36f9a56b8e55392e856e8f8ec26d6dd189e5d0b9668bef5920a1c1ee60", + "chksum_sha256": "405d6770ef140baba4df7d621a67ba686df209a008a7d3b4e8684749f4cb9168", "format": 1 }, { "name": "plugins/modules/lan_automation_log_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "95b934b5426f0046a5033e590f7f55b6240753ac21dbcfa015a75792518b15e3", + "chksum_sha256": "5b3f1532b6effb7aef33e95b0700dbe67df967bb3bd20805410c3854a17269bb", "format": 1 }, { "name": "plugins/modules/network_device_supervisor_card_details_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "9afaa51020eb5fa74db87da8d19d40112445afc0655a6f1246c23e9987307e69", + "chksum_sha256": "c04d35500ec069592a814f98f6d2d3866b2bb3451e5d466981d76e2cc8d763e0", "format": 1 }, { "name": "plugins/modules/global_credential_v2.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "bebf050a44a44da823ae7e260c7373dbe014fd31110497369b11bb2210f95468", + "chksum_sha256": "1f72234ee753cfe8541ceb94f386cf5b1660541161115a36be6c8d966b9fb1c2", "format": 1 }, { "name": "plugins/modules/event_email_config.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "55edb414f78a0465fe21bb8d7df2dcddd790ac166f6a5a3f7c6c32e43fdd8872", + "chksum_sha256": "f757d98a432913e6ffceacb593eb9677f0fa028d7cee487f98dd59fc95734308", "format": 1 }, { "name": "plugins/modules/network_device_interface_poe_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "9114611840309a068f060a6c00005af4d0ce04b5e65b50b2ca1fddb5c1f3e4b9", + "chksum_sha256": "390f24f6873f8f88d0a84fd61f5f804523293b5c9d5a427f1116219e5b676080", "format": 1 }, { "name": "plugins/modules/wireless_enterprise_ssid.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "e1fa4a975fe2bb4cfa7e150851a5daf7e4dddb3cec5bc47f07166d4471f492b6", + "chksum_sha256": "89ae9237888c63505ba6494775d57957c92fe6975112aa4920181be6b4c83812", "format": 1 }, { "name": "plugins/modules/event_email_config_update.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "aeff0928803c45a51f05d548da3ef7d1e8f90787451f548908ab83365eed8015", + "chksum_sha256": "90fc2f8a4e52bac735eeebd13f2c441389eee28567aaeddccdd3aa0b2d0911fd", "format": 1 }, { "name": "plugins/modules/threat_summary.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "76428992312bc00fd67ce567a21d3cbd16328add3f7dd4b4e92945a78441fb8e", + "chksum_sha256": "af2181ffaf29afff92bda27e6ac26918f6996a709335ccdf452ef247c444061a", "format": 1 }, { "name": "plugins/modules/network_update.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "1eaa6bd3a1404450e2cce31639e0a4fb8f21a1770785485af7286e03683bf545", + "chksum_sha256": "1c2c7db40bb76890878a5bbb8eaae4a0bd086ae05440c308e8a2b1ee27db775d", "format": 1 }, { "name": "plugins/modules/network_device_poe_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "95b3e8a26f5cdb60290f3950c51b04388b818752b499dd96e6c2f79b63979091", + "chksum_sha256": "0b3cd9983e422fb5201601e8aa3df0534dea843b7ef390a7ed369afc9ac2aa62", "format": 1 }, { "name": "plugins/modules/pnp_virtual_account_sync_result_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "3780c4c09e88efd6c4683ea5b1d04111c50174274a8e90c642cffbb987c05b69", + "chksum_sha256": "6ceb61016327b35bc8fdb49515026520d78fb2c4cd559d8967c2bb95a287fc91", "format": 1 }, { "name": "plugins/modules/configuration_template_project.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "fcd9a13996f48b4feab768e13b2925575acf73280abf313581235bfa8527366e", + "chksum_sha256": "027056a2cf1ecd0bb2e91caec83465584c0b360bd4921d195f4c0078dc3c2815", "format": 1 }, { "name": "plugins/modules/sda_fabric.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "366eec6b367133778bd16fcd2d0dd59a266886a0909b3090bfbccc6907a8c662", + "chksum_sha256": "01d1c96f6b7ec3b4fc82def191d4bb3ad80cd0d0db695e942f7976843b07db11", "format": 1 }, { "name": "plugins/modules/network_v2.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "daacc64a56ac3033476537951d3303ebe7a27c7dc7d8c8dbe15930aa144a65e5", + "chksum_sha256": "ccc7f8825f7e7dc5447051acbd4a2897d07d0a0c3ea34481d2dc18b31ae8f48d", "format": 1 }, { "name": "plugins/modules/network_device_meraki_organization_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "40160dc893da16f8c56619f25dc0fa91e777160cef7a11afc42521ed1f004aba", + "chksum_sha256": "501b32fad7f0ccc8d12dd4a4ddd19f62e5f5f45414d2c7a4ef9bab388c7936a2", "format": 1 }, { "name": "plugins/modules/event_subscription_email_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "fb1c02841bffb25b95dddac13578bcff433f457fbb07763e1ce4704f72690136", + "chksum_sha256": "6d10e11f72b43f0bdd6f6e0db5bae48d207d43c64822e9270447cdf270415012", "format": 1 }, { "name": "plugins/modules/event_webhook_update.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "47d4b730290b9e01588bdc9a62499d2b9e437b4f117d4ac1c52559f1d08ae548", + "chksum_sha256": "cb5eb2a7db3bd583bc200f3665fdacc2eaa7307463d0727602e06e4bc1e357ec", "format": 1 }, { "name": "plugins/modules/discovery_device_count_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "cd4c79c576ac4e75b87e664fa027d1771802246cfc18d8c0c06455f6ba09fd7c", + "chksum_sha256": "cc143f6f80d9acc2dc9a2f6bbe88b6dc63e37037584752a9c6b97e2d24b469a7", "format": 1 }, { "name": "plugins/modules/dnacaap_management_execution_status_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "7db3814a2dda68a74feaacf7002a854b1c27772745ae22c5fa4f206d35a61b41", + "chksum_sha256": "5ec0a31b09ac3740c66e541cfe4b596db90132248cb0b10e99da48468227bc17", "format": 1 }, { "name": "plugins/modules/network_device_summary_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "fa3aae8a6b2321f03a1b8f9e8baea70bcb43ba39533109e8c7dc3094237b1e34", + "chksum_sha256": "6b6c01df03b984a409eca09ac1507a3f670e44b244ee049bafe485247dd22430", "format": 1 }, { "name": "plugins/modules/device_reboot_apreboot.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "471dd65f4bace5e6315fc451b9707b852675ab5ddb07269d39f1434052c6fa7f", + "chksum_sha256": "44ad5748789d0ab4ec27188c2303b649696853c831c85bf41a31964a4880b037", "format": 1 }, { "name": "plugins/modules/reports.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "337408d4cec040a2addff74f30a07e69e606ddf58e2e909639b4c1843ab346d7", + "chksum_sha256": "b2546d138a874a33e91ed9f70e87f2236c28fa3c9161daf31fbc472876e4c294", "format": 1 }, { "name": "plugins/modules/reports_view_group_view_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "752ebeabef80910863a3d0985b2a17b2aca65b3d7a5420087e8c841fb182aded", + "chksum_sha256": "f89203d7479c24ccea06961c58fa87ca9e0e8d39aa61016aad069fb040d93d3a", "format": 1 }, { "name": "plugins/modules/event_subscription_details_syslog_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "34a78d1be492cb4c226c40e73edc50f80f5e49882475210fa620c2cefb9ede18", + "chksum_sha256": "0d5bf1e319f86e92fbb96e9787aa7ecd6ca539f42c43d24bb09c1915f46d580c", "format": 1 }, { "name": "plugins/modules/license_device_license_details_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "d8469dc9759c5d864d6ad27a882dff4e6c2be3b943f104ee1e2af8b0797aacc6", + "chksum_sha256": "edfae10160a1ff5072ca86e0a10e0043ff22031507bd78f680b5f52537d30470", "format": 1 }, { "name": "plugins/modules/path_trace_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "037be41aee7d682bc0aa8820a2fadce1f4427449685a2d9e3f2f0af22aba25ea", + "chksum_sha256": "505ef505a81ef65b7e3317bc4598f429f39bbdc26cf396f24b7f4a8368307397", "format": 1 }, { "name": "plugins/modules/site_count_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "e678d7592b61991bf88589300a8296c0875e4fb4904b296958c885347a510781", + "chksum_sha256": "a159cab1c0c05979e19a2204e3f8f4f80b28b73b10e58f5ad016fed8eff40858", "format": 1 }, { "name": "plugins/modules/site_membership_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "b1a79242232ff34a88ff9eb277c2dfe7df517f1e5c636a468eed0ff09e07d684", + "chksum_sha256": "c9a7691fb7b4e10cd29df359bc551dab79fc88f78395ccaabf2a0aa5413d5d3b", "format": 1 }, { "name": "plugins/modules/sda_fabric_border_device_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "ae419fcf754093fc399ec8044392411ac06fe535a71219d279a15d3fc23bfc31", + "chksum_sha256": "8c9ee7371b672a4b05e84d8fdad023c028bd7fda42c9c291e8c8c0b8468cbbcc", "format": 1 }, { "name": "plugins/modules/inventory_workflow_manager.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "902aaf3d5251b10cd002f1f24710bd0fd076d5caa203fd64966bbbdd14274d2e", + "chksum_sha256": "4f2eac3c3da7c44477646bb5d283b84381c68b7ddff0f5374e505dd8d5f0506d", "format": 1 }, { "name": "plugins/modules/global_credential_v2_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "ba55055a3bb5e88f63f6f57c2d36573960f09565920eec799cd52c7b2b4bde42", + "chksum_sha256": "4370b9bece6cec8f15fbd34a42a2b06d059f5dd227876d462dce87b10243e0df", "format": 1 }, { "name": "plugins/modules/event_subscription_syslog.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "6834ae5a13322cfecdcb7ca29c9b49923d1d2ac49b9d34c02b12b0ee7df97db6", + "chksum_sha256": "d296e1664e4008d17b54f7e56909c76ec480fafeaa47987956b0b4b7a9205a3b", "format": 1 }, { "name": "plugins/modules/user_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "7d6202b171f91705f0f0b78b0f04293510e3964a05e667a107847d3a26b2b2fe", + "chksum_sha256": "14550e1a3958db5cffe0926f05ff81490e3744077015d5adb31d80af9ede4334", "format": 1 }, { "name": "plugins/modules/device_interface_count_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "76da700b3f3e632bd6ca6eb0ab8e8cc371a430b1caf6807aeb2c4f8a5303d3d2", + "chksum_sha256": "9b87a231ea5513907e7ac5a11ae6689f63443851999b5ae73a07536863065f52", "format": 1 }, { "name": "plugins/modules/event_api_status_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "d602f7466b50c0fd14d86d13018055ce549f2f362e88b1be736f1724378b1f45", + "chksum_sha256": "cbec81ca521399d416024b473f3eeb1fdfcaef7823790529d0fd59e58a3c38d4", "format": 1 }, { "name": "plugins/modules/event_series_audit_logs_summary_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "7dfde6593bc7b750abdd145838eca057fecad629f457dcebda76febaf5bfa192", + "chksum_sha256": "789ee39e43d4f396e82c434df8e2dcb2d35d0490a0fc270a198fc4743816be8f", "format": 1 }, { "name": "plugins/modules/sda_fabric_border_device.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "82cd6ccd601872de901fd2842fbad89bcd2470701667a38eb95f0f1bf26a54de", + "chksum_sha256": "514a9818da32a1b17c218013dfec643b731adf5f9c6b43f503841d906ad9f8c3", "format": 1 }, { "name": "plugins/modules/sda_fabric_site.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "ffc413261e353627541ec37b6c4b89c043864937bc6a46da3289d4369bebe8be", + "chksum_sha256": "4a8ed49cebc8ff4bc66d42e6fffec8ed468a4946f3b0e27810fb6b8f1b356bff", "format": 1 }, { "name": "plugins/modules/application_sets.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "38d2b9077e0aa11c2909ad60982c3e8e98c7baf89889235c23b10adc7b468fa3", + "chksum_sha256": "192769a8af1b5c7f3f336ec63211d092a919039b1654abb98cc0182f83d89e32", "format": 1 }, { "name": "plugins/modules/interface_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "354d7d8448d181aed69034971f105e106319f244291a0f9c1aaf11f705c49c8b", + "chksum_sha256": "a17f013992aab461cc87547571bc824dcbaedf5a535005bb60f9ff8d17376821", "format": 1 }, { "name": "plugins/modules/configuration_template_deploy.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "90dcd2f6eddebc69a201447994e512cebb4c841edd8553949a4137f75e3c8d25", + "chksum_sha256": "25716a8304f6d3d2cf71687dc7fa67a970476462dbd150b197869dd8d79252ce", "format": 1 }, { "name": "plugins/modules/application_sets_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "98fc9a92f6d0c3c7e577566422b026881cfdaf6036d934e5270c5afdae983f18", + "chksum_sha256": "2dd82f908f43a7a9c18e60a76a2e5fff93c5f0f7f2e88dc33580ffc1ab22589d", "format": 1 }, { "name": "plugins/modules/device_family_identifiers_details_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "af0f77c84835c541f674fda8f5e5aec7870509f852f3762a890866fbb9c66969", + "chksum_sha256": "bea4d4ef7a733abe83abcadcd8f3f638aa38f83ebcc53d8c69abf61a0a699144", "format": 1 }, { "name": "plugins/modules/compliance_device_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "e5f5aa666609204c911a9185974570eb25291ad7885dc0b475bc83258f42512c", + "chksum_sha256": "68d11400c2a1460502bf973e8f34d63e8cf668b3158ee0d18332926623fbe908", "format": 1 }, { "name": "plugins/modules/device_configurations_export.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "038af8d5122dee1aa0bcac5eb8fd3eea96d3a1e4da5a5c9fa18dafc8e9cbdc9e", + "chksum_sha256": "1b1bea127f011c75e212a406bec66e6027e9091338f02e4ed63655cb45009953", "format": 1 }, { "name": "plugins/modules/pnp_device_reset.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "b84251ad7277742f47d76491d0e97622ff4ff73cee04a6de7cdb6246671cec3b", + "chksum_sha256": "18f72f928ff064c8be1ffe100036b6e511c6cf4d61341795a5ae44fd25273ce2", "format": 1 }, { "name": "plugins/modules/pnp_device_history_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "63f4e90acc242174dce7f56ad2c47c552d979da967c9ecd23d07a2d7aee5db2c", + "chksum_sha256": "732bf747504e5438618fc356c4c0304a630241f2d66c60e4525c713ff3066725", "format": 1 }, { "name": "plugins/modules/task_tree_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "6211a3d60cbf50d88033d72e71840da812111b698fc28207fcbe308270746a1e", + "chksum_sha256": "59893d9359af8cc27e151b5ed20f645cf7a8b6b638db999ae6fac7c3f48d9a97", "format": 1 }, { "name": "plugins/modules/network_device_vlan_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "8765806aa1b2c2180cae25d4575938df40df8d3bb28d6f18d15cad1222fa699b", + "chksum_sha256": "5930cc396ca55b4d45bd55be12ff4217ce39a7a128cf57086e81a08fe3e4911e", "format": 1 }, { "name": "plugins/modules/itsm_cmdb_sync_status_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "79ace219b614472c6a7d6fea59a45451fad0440136ee94b347f16bf267461fa1", + "chksum_sha256": "2bdc11fb3544154af2c2cc7c6b4a9440c148cbd83dd71b0406cc8b473f7d81cf", "format": 1 }, { "name": "plugins/modules/file_import.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "60d334559e19014077c1548244ef0bcbf69b122fe53bdfca9682c061eeb67e68", + "chksum_sha256": "b50500ed9705cc9aab6d449087985ae9a15b58912610d7d43031171dde180380", "format": 1 }, { "name": "plugins/modules/app_policy_queuing_profile_count_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "89b90def6f4573f56b789007c885a93fb2e6cb0ee7195f586b0ed32549082053", + "chksum_sha256": "764f46f16e0b00ff41d2fadd5b330dd93da4c7b973be4dcedd0403139d94ebcf", "format": 1 }, { "name": "plugins/modules/license_device_count_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "38bad78c0bad7272ef23adafd9d25adc94ed8e01b9bb587436a044513735157c", + "chksum_sha256": "73b123592b5032b2bf01a1a3d07309c3bd72e00babea6a57cec23e4d88770a73", "format": 1 }, { "name": "plugins/modules/sda_port_assignment_for_access_point.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "63fdaa25b5ab63e4413c1429cc4dbd125cd011cdbff3d7ab1b91ce4310f58f39", + "chksum_sha256": "0083dc63ec58196ea6e35b8090c3f0e6129f32a822d22444230b8c908954ea74", "format": 1 }, { "name": "plugins/modules/nfv_profile_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "3deb80367d65aac4b198aea936beb4ab3734348660b53bfff6466b3bfde9e019", + "chksum_sha256": "c221b4a09bd70a6967d2d8112dc9a2b686e06096015ca32f87ff5d946cd0efbc", "format": 1 }, { "name": "plugins/modules/sensor_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "c27aa720f87ca297af307a213cda6c328fa7bbdde8603338c71471b0653d8c70", + "chksum_sha256": "86bf44ebb2ecaeb88dc8c0f38b1aa579fab91f4b4c2d0befbbe0ad25c2fa8456", "format": 1 }, { "name": "plugins/modules/discovery_summary_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "ea537d263922e9274123283489d1900a22189508f0732745c50f77cc8b78c835", + "chksum_sha256": "e427e86af18d037d23dbe7ba001fdc804209faa0a3db0d95a66306cac9703c47", "format": 1 }, { "name": "plugins/modules/reserve_ip_subpool_update.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "e8d7eeca847a7f7aec15c40fa59359f38dbf117bc270a781ceea2a8fb40453d4", + "chksum_sha256": "2c496cdf70d115f1a5eb9aa9d27ca58a914b4e1afdce1e9ed4039c167c5c96c5", "format": 1 }, { "name": "plugins/modules/sda_fabric_edge_device.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "0ade5a67024b69d30c659db3dfa5464b139b8231c665c32f89ace415516237d4", + "chksum_sha256": "da4b7c0c2189805b12502ffee36f981e43f66b64c11d72e9114b44e3dc36ea32", "format": 1 }, { "name": "plugins/modules/issues_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "3552fe99cef7550c3b8e8f0a071eb0864fc63259c2126aeb89facf8cf86ccc94", + "chksum_sha256": "3233a808e2a38a5dcff1c5ac5dae05c3c234ef3867ea579b4325c6308644fee4", "format": 1 }, { "name": "plugins/modules/reserve_ip_subpool_delete.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "84d4aeebbf3ae99ad5704beb229edc2dcdd26013ba963c54edd4eb686efe94d4", + "chksum_sha256": "be838faad1e1cc2132456eef16a45989490e303cf472101662e899ff746d3471", "format": 1 }, { "name": "plugins/modules/system_performance_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "ce0e3e28ad1703d22bd5bba859f83bbfe0160b0587fb9335f6688e4d2ce08675", + "chksum_sha256": "94b84d09630e63de3e78fb401d831c1b575f2b67ab203a9630e73a249e414c23", "format": 1 }, { "name": "plugins/modules/pnp_virtual_accounts_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "d3d000a260fa55c450387c04b85fb4f6f38e231b29797280a5323bf7c7edb913", + "chksum_sha256": "4da458d6f6900281ce72fb7d35efdafce5726c2a7b1ed1fceb96013e39df2a2c", "format": 1 }, { "name": "plugins/modules/qos_device_interface.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "3b1ed49412c7738a1f931e74444b0389393c63f046304fdd2eb165f25c12e286", + "chksum_sha256": "345a0c8ba2460447514eaadd9a4c6c06437a41dd523ac0ee242b438bc5b6fa7d", "format": 1 }, { "name": "plugins/modules/wireless_accesspoint_configuration_summary_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "9cb2a083446c1e18ed6244b83c2202c4e16a6676cc19c18fac3179b564588f99", + "chksum_sha256": "476d76a1dae5fb65ec437614086f4330345337c4a8016143bb4c0e35e70f5394", "format": 1 }, { "name": "plugins/modules/platform_nodes_configuration_summary_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "dffe10b5ee55feb154d6cf7928d528a6973cc82a796f26b65587dedbb7a3aa53", + "chksum_sha256": "425dc1675cc14df2e1a1f106ba82b015efea4dad660efd30e90a85513544fe6e", "format": 1 }, { "name": "plugins/modules/license_usage_details_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "39f4e084e20c4647d22510532eeefc7cf905aed4cae0ff816a4e42679d305d42", + "chksum_sha256": "b4cd3c33a245ad781ca91ed701162be7f153a784fc5074510e6653ffd37eea58", "format": 1 }, { "name": "plugins/modules/swim_trigger_distribution.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "7a5653bebd2c34a0714a01f3d51b99b05410f365e1eede791c20d0cbef500689", + "chksum_sha256": "05301b58c6bd53db105787507b8d95f9146e876c04517da24a2ed7ce93e5ca9e", "format": 1 }, { "name": "plugins/modules/network_device_config_count_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "1bc10f975659b61c052672f75aa014afcee5d50527a77733aa7d65bf269d33d4", + "chksum_sha256": "fdcbd52016db5111340cbe50b352689233b74841792b2ac6e26baee1962dec7e", "format": 1 }, { "name": "plugins/modules/golden_tag_image_details_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "af30f6bb7ef5288c45378e2bf84c95083b6cc24c78b4a3cd4cb0d2927a260fe0", + "chksum_sha256": "fa5190a562a76348af1a487b0fedfeebcdf38420faac0273a0f4c4d7c2d6cb9f", "format": 1 }, { "name": "plugins/modules/app_policy_queuing_profile_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "5db47e0ca40ec28b5e44446ca95ae502b086663fe74e7f230280603ff5fb93d8", + "chksum_sha256": "7901bb6d68d20beacf33d98102b5f4c9a60d04363823ad08eed7199ce413a49c", "format": 1 }, { "name": "plugins/modules/device_enrichment_details_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "d025fb5a1fac7cc308fea73147e225741f80872de1f8a3244431838a5f60ac36", + "chksum_sha256": "573bbc37a473a66dd6917c421cb88b41893400becba54c7445e1c74141854444", "format": 1 }, { "name": "plugins/modules/file_namespace_files_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "b56ee6140cf2f73c2f68c49c93c1271edbcf8483747c5932454a3cc995ec70f1", + "chksum_sha256": "b4b92d8ffd4657da74f40eb67135e126835805a45ccf56b10a734f913dcb14f1", "format": 1 }, { "name": "plugins/modules/service_provider_update.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "df3d1a7041cf1f997b84d85529e3d286910b51586dd1b99f1121c6d587bc10f0", + "chksum_sha256": "01cdb05b3612adcf7492d4c05b7bf341129e6bf945ca8d6e1a7d0c98df1c70e6", "format": 1 }, { "name": "plugins/modules/swim_intent.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "a8b6020f943c3d565d60d2644acd609a03aebe0c4cd8b08799c09c9f13b9745b", + "chksum_sha256": "2496669e06e0ff4439abcb47e8befc98e803b204c75aeec972991ae2216d070a", "format": 1 }, { "name": "plugins/modules/license_device_registration.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "c8a029903f8e77e904867dd24d4e0537ba08208b6158867447ec5f54a593df36", + "chksum_sha256": "8911294bbab15816cf933fa3c99fb99fcc5d59a70a98353e993a5df1fa61913a", "format": 1 }, { "name": "plugins/modules/configuration_template_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "6fcbd071c4834217eb670ef057c6ff73b1b74852e902e7f20e7b9c8ae09da7a7", + "chksum_sha256": "d4329e504a1f1ae60ea74b216f842bc3b1f7425e666f6eab3643f3a01499c275", "format": 1 }, { "name": "plugins/modules/topology_site_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "db630236845f02e3509240826214f5128dccf05d85e8973d09a4161b099119df", + "chksum_sha256": "8013a0732ee984bd7779b6e2fc10eac4a1dd833e8d39bb37161857ae0a9191c5", "format": 1 }, { "name": "plugins/modules/network_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "fc87f5d7778a2fd653e5cab539eddcac1fb16c4b13c1c5df68cf3e75961ddc59", + "chksum_sha256": "f84233f884fb03d3a49de190b30e1dc254fecce2ce839143fc2b21c259ff3141", "format": 1 }, { "name": "plugins/modules/network_device_functional_capability_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "927c87255cacc9d32ffee2930f01925605380a47c0216a545190bfc59cbdf3fc", + "chksum_sha256": "2c970dd0ad71174f2f57047aa0361be3a6cad21743b0d15e1ea944944d5d492e", "format": 1 }, { "name": "plugins/modules/business_sda_virtual_network_summary_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "3d0639bad3ee9594380c5f3ab116df124b4fad607652958e41cb740aa83af4df", + "chksum_sha256": "f0961a8523eec413b3ea8e505b823d54dc47eee05900cd1b5e2aacc04fab8161", "format": 1 }, { "name": "plugins/modules/sda_virtual_network_ip_pool.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "cf15ac131559830c1e130d24b486d8b1e540f7816ac80deb83248084d8c0cb7d", + "chksum_sha256": "30c2f462463ccca7ebb154d7112289b6e4b5dc7b84dbb16184c05946ef545f48", "format": 1 }, { "name": "plugins/modules/sda_port_assignment_for_access_point_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "f756e843fb2f7626eb41a17caf18890c9b86c8810fbd2ff3ec4869a94a07b995", + "chksum_sha256": "36b20fa02a78d3856fc637637ef790a4c6d9fde70df05ba64b6d507833e70033", "format": 1 }, { "name": "plugins/modules/snmpv3_credential.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "a89b8c6e527f99286892d6da87131e4579e68fb056f4b64b1c1370995530394c", + "chksum_sha256": "4986e2f6eb85ab186ec1dba19172866c46c914d89a53fa703e4dcaef2a2002b0", "format": 1 }, { "name": "plugins/modules/configuration_template_deploy_v2.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "86e6e7345b4cfd309247fd956e8ac1b914267dd72bd38389d7a8a14983995e0e", + "chksum_sha256": "cd81da364978b6b07c8b740866b2f0ec5158ec7c121405cdda89b9ccf9827304", "format": 1 }, { "name": "plugins/modules/applications_count_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "13ffffb6e7bfd438badf41dab65af8d3422f1bcbef8d826c7a9420b8e77ab63b", + "chksum_sha256": "95631698e329c64d12a016b29dbcf4503e15142a399d35c865f4a67af9ebb6e1", "format": 1 }, { "name": "plugins/modules/sda_virtual_network.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "aa2981517a9fab531d9f2a31c516be5c127e43deefd2076c3e93f8807647ad92", + "chksum_sha256": "0a9db2f68811fa69d9bc436fd4e2f811d72046610895ab77077c1b3cd40317ff", "format": 1 }, { "name": "plugins/modules/interface_network_device_detail_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "29dec8355faf383532a649f73821328951ccff1d10f779ba816130ed33baf308", + "chksum_sha256": "5180c047f70c067118628a41c0b39cb35a8809aa144d39d69e5fa26f93bde66b", "format": 1 }, { "name": "plugins/modules/security_advisories_ids_per_device_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "5fb0cc73606fa28b9146277c1b89830a9b54abd125a6ae1c28d04e711679bf83", + "chksum_sha256": "ec65ad9dc89bf2383064373c81a8eb380176512b855df4af9a30e37abed9d3b2", "format": 1 }, { "name": "plugins/modules/platform_release_summary_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "58b717afbca97a58833054b8714e07b0aec0cf548146d3479664fb3ee6a985a7", + "chksum_sha256": "8d8908b473417711a0b340aa89c684182c453e0c992780c67d4054ea006404b2", "format": 1 }, { "name": "plugins/modules/network_device_count_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "982923a1bf449cd464aae865f0e9ec778c0fdf9c3f72020acf09ab39043cd81f", + "chksum_sha256": "2c5d2866eb86e0b1b66454231d5f4f97051b69503a9396c5f239e964a08771c0", "format": 1 }, { "name": "plugins/modules/event_series_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "9850fb6a1eae09f739e3c8f066e18c6dafc4b7d7690c79425a1367dbbe4f2ada", + "chksum_sha256": "b6a358d02719db2e816a63eceb647f47065f4bc850417ce3be6cbcd251b52199", "format": 1 }, { "name": "plugins/modules/app_policy_queuing_profile.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "a945521dc0a36557324ba8f735b5319a2362f2803616a6431680aaaf9410229e", + "chksum_sha256": "0a2f9c2eec211c62f7e7e3805c7d79a1bf0487a7c5af795c084366806812ff2b", "format": 1 }, { "name": "plugins/modules/service_provider_profile_delete.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "2b5a0c8eece9d627b97da82ab3b601fc310cf7263731c976120d11541c030876", + "chksum_sha256": "ad7c00fc5747b64f421bb56bf49d69e2a7c602bcde375da4903581fdd9f4f733", "format": 1 }, { "name": "plugins/modules/service_provider_create.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "511825ebbdcd1ad32fbdfdef704bc8018dec865c2c93b16f298cfa4c5c592fd8", + "chksum_sha256": "fcf85ee32ff93d2d080a05983bf9ad5c84e9208186b49cfd2e99fd960e7d6071", "format": 1 }, { "name": "plugins/modules/network_device_update_role.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "eb6c54d7ba3e18879bb08fdf2bc5777f2542bdc880b05b9aeb3512c65cec193b", + "chksum_sha256": "5527bd9efd7c373b2f2bef0c7d9769178dd03da2214d9ec0d8327c75605c9b5a", "format": 1 }, { "name": "plugins/modules/sda_port_assignment_for_user_device_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "943e70b6745a6ab45a025e0f46cbccc3d3d23dcfaad3f8fe1ee013d092f1a559", + "chksum_sha256": "3dae9e1a13f2ef7c64599173440a257c981aa1973e521b2a21ecb19777a4f420", "format": 1 }, { "name": "plugins/modules/transit_peer_network.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "b7d244b17c6c387309ba41609218b233d808ff5f4bdc76ddcddd0d610058c2c7", + "chksum_sha256": "753a85064c256636c3d572a0d95745615caf59d3467d23640c0dfa67609e8508", "format": 1 }, { "name": "plugins/modules/device_details_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "05ba1ddfe43be06e27d2e5c1b50bc0eba78d9af58183b2f1133df1143640e371", + "chksum_sha256": "6edf275ba5c5101305b745ab1da31394f4921ddc7273390dd6d7d9ba68443f71", "format": 1 }, { "name": "plugins/modules/device_replacement_count_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "5c58f1db9957c2bc925cebe668fdc10b4bfb2f12edf674910b886ea35f5f1dad", + "chksum_sha256": "ec372d22e552b584051564f4b2350201d6f100dd15d9d3b8ceec092d7f3662e3", "format": 1 }, { "name": "plugins/modules/service_provider_v2.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "83b487a8fb0060e51894e3969051013ca6fa68c85c69a5d2af459ad15ac0792a", + "chksum_sha256": "0e08a7b59aad648e9080fceae08654318c57de7b3103c49f832938dad61f1e4b", "format": 1 }, { "name": "plugins/modules/sensor_test_run.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "d9ef6a8aecadeae78590a9e9a92d74a288d759617fa004f89a7b32e6cb192a0a", + "chksum_sha256": "fdc7503849a10f9f5250efe5aff1762230f36c307dbb2b9525269dff88741562", "format": 1 }, { "name": "plugins/modules/event_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "e6c8fbfdf60b1cbf35e4ef163250b0ccd13f218ec7b4d35ef358334102ce0ca8", + "chksum_sha256": "d9e1da13a438a4aa0e9789bd0b8a8dd2a62d744a74219d52bdffcf54babe7a90", "format": 1 }, { "name": "plugins/modules/device_health_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "791677d81789ebbed706d0a781a8364f3c236a1a27879d76775e53ac6f11fe7e", + "chksum_sha256": "f9dd5499ad6dbdec5e399ccbde4b4a341d487e2c25abeef9db15c8a822764f38", "format": 1 }, { "name": "plugins/modules/netconf_credential.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "3cc0b590cea4d7911d9f7a4c01c4a04dfcf56cfc52d12525d64cf3f8df8c6d04", + "chksum_sha256": "042123c962929ad1cd28b34d332c32c3762f34b6da174aa9016a5d5076026a1e", "format": 1 }, { "name": "plugins/modules/network_device_register_for_wsa_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "a51c888d705368497962a078aa815be28e390682a020bbd2169f442a839b1ab1", + "chksum_sha256": "90f6f71069aa7cc1ae69ce29872ac0de4abd18f00b3938451440a10e2f9aaf56", "format": 1 }, { "name": "plugins/modules/client_health_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "857c1660250039a5c1741d22b4ade73cfd657eca042dbcf94af746e928ddf26f", + "chksum_sha256": "f19acdcc18536cc0d1481d2f1e599470b2452f535e9a7875fcc561cbd24a3af8", "format": 1 }, { "name": "plugins/modules/provision_workflow_manager.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "ea01d7479f375bd14749bd5b429060015d6749db77c8cdabce553102a87d0001", + "chksum_sha256": "b4022bae7d5a73a4f04189450ed124ec797c1d074188ae2448f781838cca65cf", "format": 1 }, { "name": "plugins/modules/interface_network_device_range_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "19b7c1e2995808459fafb6c690e3f8bc0a64d0bfae83f2e2ec6fa623ff730eed", + "chksum_sha256": "9c0d0e2edb7feb9baae0fea938aa582bb5e12fb5d43ae1e8b073fdfb2f8a3a55", "format": 1 }, { "name": "plugins/modules/inventory_intent.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "3e32ad491d38e58f18dc8f8f91fa6ba179a66486560b0af6b478b77ac7a0d17d", + "chksum_sha256": "ece57506e288379d5617d21514aa1511a81e33a5797c1965ed32edb945c46829", "format": 1 }, { "name": "plugins/modules/compliance_device_details_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "35443e54b6c214c49019c9fab77d82613e933953647a3374403a2cb12184e149", + "chksum_sha256": "dd1ff0a6119295b29da46673213a0a532d43b69fa99dd2350e379aa4211a710f", "format": 1 }, { "name": "plugins/modules/discovery_range_delete.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "ba13da77c7f892c1c399c6c958d1dc6af70093781b233bc76e1b129cf8366fdd", + "chksum_sha256": "57dcb52ea8cb6564b792c1858e50f4c101fd7c200c8e93848963f6d07ed5ba57", "format": 1 }, { "name": "plugins/modules/pnp_workflow_count_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "41f823ef28a342294d766f9522bff57ffe9211a741a62f18dc77681880451b66", + "chksum_sha256": "b510f57488ce208d9b3d50a4228efe565ed55013b2e2fa4a439cdf217a51dd28", "format": 1 }, { "name": "plugins/modules/network_device.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "f02d1b6a2bc7d29c324751ee16f25f3c03738e7b331eb928808e4198299e61e6", + "chksum_sha256": "5745ffb093995318488363a512a318b47e8f5fe848eb29735e01593d4ea4c4d9", "format": 1 }, { "name": "plugins/modules/network_device_export.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "39eb919e626e7499b8673e34a7f09cfef626a25b57b37b1dea12692375bc0c35", + "chksum_sha256": "9fdb9952b2c82440a6d7621254e07990602c70579bbd4c49a9a234e83233a933", "format": 1 }, { "name": "plugins/modules/templates_details_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "80961a246d11701c7960328d29cc92e521e2b7e043fd6afd174e37f6ef70fdfb", + "chksum_sha256": "99c2b3a5172cb9fe26133dca84865f6dba2fb2f663ecc97dd9530141931574e0", "format": 1 }, { "name": "plugins/modules/event_series_audit_logs_parent_records_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "e52bb2cb28598a48a229fef52d69cc9bd3f4a384ce38a92c48c1081c2df88061", + "chksum_sha256": "cc6b6acb562cb233d3073e4d8d9a8fd5947c05feebe45d447270626c887f263d", "format": 1 }, { "name": "plugins/modules/network_device_with_snmp_v3_des_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "4e3f6be580ff6aef59ca86668367bb517cff2e1e9523fc67df92e5098f17c136", + "chksum_sha256": "9680badfaa131c3e8402ed585e1f9f078b24fb0188c87565a3ee5f94c4134587", "format": 1 }, { "name": "plugins/modules/license_virtual_account_change.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "f959b44edf5561390ce868113ac8798bd3fdb62b6a8f813a2af96dacfaef7758", + "chksum_sha256": "c50583679b1731041148b0ba9d5426b6d9f6d22de366ee1d81617be686bb8394", "format": 1 }, { "name": "plugins/modules/compliance_device_by_id_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "99092cfa9ef9757a242cfacfe72bbd4930a5b62cff286c0f3922ae29957a0554", + "chksum_sha256": "2b7d3287a9ebdec1a9e0a3247bb0d26645c810db6188be6a6e019816096fd099", "format": 1 }, { "name": "plugins/modules/pnp_virtual_account_add.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "e3b97f7bf0ed8a871c8abb93526c139f82a106537cabfa8690ebe05106555cd1", + "chksum_sha256": "f4310f4e30db9d98de59b39284f4399711f959d5f9f5a7ed91170b3e22e9abd1", "format": 1 }, { "name": "plugins/modules/template_intent.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "90ad608b3f5bc90983bc7bc913a7faac8179061d5f16d8375d43db5fa8e1129e", + "chksum_sha256": "7ad39ee74214a8463839de83532758e62d11b82196dc9da4ee79090e008fbfb1", "format": 1 }, { "name": "plugins/modules/tag.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "28abf9ac9cd0f7582a16458a2efe213ddefbc0c742ce0cebbf4700dbf53e366b", + "chksum_sha256": "599cb4070ae8d04cdb5c7aa40230cabd02434dd1781fe0cb30edd53f96c91aa7", "format": 1 }, { "name": "plugins/modules/reports_executions_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "49a10ab49f8b0a56e5e83749f6c828406d882fcf61f2cc74bda28ee879fe7bdc", + "chksum_sha256": "8d8d4e2cc1aa4e7eb5cfde98efa1d0c0fd815e0732e25c88052832fec71bad4e", "format": 1 }, { "name": "plugins/modules/sda_fabric_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "567d8c20183935c551e0112032274d9f40f1e0e7d1f12a7729f241e5b324fdc9", + "chksum_sha256": "21d8b6a152f6cf176f988135c026a332e0207dbf527c2d8ce8e4f91fb3a29ce6", "format": 1 }, { "name": "plugins/modules/device_credential_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "19434098bb531f5645cc9dd7ec3ef060fc62eaf8505a4a1afaccb4e4f7a4cd56", + "chksum_sha256": "32c77e4f8bbce95b669e7b633cb634c0ce90f8bc90aa5ba05d88378c1c72b7b4", "format": 1 }, { "name": "plugins/modules/file_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "4cb5ac356f530f121a40f993997abbc4cb011c4fc6336577789315426f79b4f2", + "chksum_sha256": "be00fb30acf461ef13d6f53e64d6566e3373854c4f4b814a068705795ed1466e", "format": 1 }, { "name": "plugins/modules/event_subscription_rest.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "c947933ec1bc1405766e8a4d8dfef9d21343fdfd4ac6600c38b17335a8c4d34d", + "chksum_sha256": "781ca61ab98e39bc744c37e1a49c67cb4145ef0d2ab0ea5d5b72f29053166a8a", "format": 1 }, { "name": "plugins/modules/security_advisories_summary_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "bc882aebe138607d0b303827e205b6697f05bd986071c0d7d49548781b32271a", + "chksum_sha256": "d2427fda49247b452d0a814c785608c30798a6411ab8556a9af5c8fcff2d501d", "format": 1 }, { "name": "plugins/modules/network_device_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "572dadf002c013b3d9b528bbf1e24e94f29aadfb0eb33e0caf42712fd1f77260", + "chksum_sha256": "230805a1eb0dd3ee97a3310492d877cd6782682c785487f62b05d0c392fa3617", "format": 1 }, { "name": "plugins/modules/integration_settings_instances_itsm_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "09265bbe02e7bbcae7fe4d7202d9c0ab97d2e68e24581c238d6bfadd65e91e78", + "chksum_sha256": "d62bb9050400c5eb96b1086e303eafea81a553acd984f837a7f37fa807c078b2", "format": 1 }, { "name": "plugins/modules/pnp_smart_account_domains_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "894a1ce5ae2d4500837070af6d35bfbd0c7cb18ac709e9ff0f8726407bc37b0f", + "chksum_sha256": "d1d5cc0723495f018e760b2307f0a562cb82784ec0a94f9fcdc698570ea2cb48", "format": 1 }, { "name": "plugins/modules/security_advisories_devices_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "09e0461d3ce4c1a16932b8c32bd0bbd387cec9e69e31a256032c2558b7d2338b", + "chksum_sha256": "c46d4671ba23a245e1e394231f7be2aee9431c7b1075beaae8c61b87974bf3a3", "format": 1 }, { "name": "plugins/modules/reserve_ip_subpool_create.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "1c3ac587db4e5fed02cb076ffd58554834ad7077d8a0718d41985059b896469e", + "chksum_sha256": "6a196f4b903c9f46fe96bcb9f413e781b3ff54e6804e498b253f3a4e72059098", "format": 1 }, { "name": "plugins/modules/network_settings_intent.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "85003b655194a3dfdcd2fe1e7780475d8f0d75f602325be07fbc6fd8b5b71988", + "chksum_sha256": "3fb788c847df332d6938200b8e1085e06efb9a52a03eafd6f1bf57ad4cfcd9f7", "format": 1 }, { "name": "plugins/modules/itsm_integration_events_retry.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "2bf7e87de8923919e3b20a4752769ba67b4c74769acf40221405ad386e66c3da", + "chksum_sha256": "b5fff2a26a1bff3739f193a1c8d97bbcfa6b858b0e6724c485decb12848ecade", "format": 1 }, { "name": "plugins/modules/user_enrichment_details_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "7638a42d626129b870405537665e64ee9f9d1215b087ffea389a58ce4b9e1aaa", + "chksum_sha256": "8e9e53d0be84ff2313ade25053b67ef7aff8e10b0494d3a588d2b0bcd3376745", "format": 1 }, { "name": "plugins/modules/site_assign_device.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "fc61bcf87db49d5ab5088e8378c3e7ff4a350c6c175cb63693d430f61fd4c7b5", + "chksum_sha256": "6ea9d0392351b4c14adf24902b22fb610b12eab49398a314a6dcc73fb30641c1", "format": 1 }, { "name": "plugins/modules/golden_tag_image_delete.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "b227ca6d6948a108ff4eaf9335ccc49b19a602f95f784b7dc6cb33fe09edab66", + "chksum_sha256": "9cc5242bf78cac68ab06a508aa7046d6d20de4c3e1d0658f9893e21ddb6a39fc", "format": 1 }, { "name": "plugins/modules/network_device_linecard_details_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "b408a876eefa5939ca6c7b0a05d5aab4fbeab243aa0dff400083bb0e8612f7a6", + "chksum_sha256": "ec2124d0f33ed574f0135698679be01794cab7c5610052899579266dc7994860", "format": 1 }, { "name": "plugins/modules/issues_enrichment_details_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "1a6d4e1e484ffdc78c6227b1f41ceefab0cefcf7ff214f2dfd59b33a1db3f022", + "chksum_sha256": "9ac8965247e64c864374eb781b66398c38deb4e24f366c232c4a04e52dc2e59f", "format": 1 }, { "name": "plugins/modules/golden_image_create.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "b4c425e6a3760f8a0d1ef1e09a71d3bc1d9bbb549593ed358ebae02e70f0062a", + "chksum_sha256": "b7a030e84fb8bfdae750f3b26e44a3ad5a69e6f977ce205ae2c3647065ad70b8", "format": 1 }, { "name": "plugins/modules/qos_device_interface_info_count_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "68de3c82502965a33cb10bcf2b3dc71d0e120e8214ac5905f84ac66acc267e06", + "chksum_sha256": "367f38405567a693e4948efb26b11bcf2c4cf8cc17141c848d96b32f0c39c4fb", "format": 1 }, { "name": "plugins/modules/compliance_device_status_count_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "71ec2207cd2f09326400af3e3336313fff273a6d338a88fe1fe009228ecc2741", + "chksum_sha256": "cc118928a2bf1982387666dbc9f518b089e12d01af303100583072a0da87b383", "format": 1 }, { "name": "plugins/modules/configuration_template_project_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "ceba30f1dc4cc1ea29ab78e89039fc46e4cb25097ff92d75f9fb46102adadb31", + "chksum_sha256": "0628463b729978f221dad948cdf77316e9564dd2f9cdaa7a299a2970658c312e", "format": 1 }, { "name": "plugins/modules/pnp_global_settings.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "5917ba9cf862f97b5973d06d69cfd0585f3a8d9504038a14575da30394c84833", + "chksum_sha256": "42bee25376c6dfcb9043b0e59fc9b104bcb2cfa23a2e150a10dd900c08df0153", "format": 1 }, { "name": "plugins/modules/configuration_template.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "5b5f8797ce134751a5ad59294ad30d1c859fbe7f0255352fad4a3bb45799c981", + "chksum_sha256": "f4ea58c333f46cfbbc93da9bdd06331d9497625009c9d82faf6d384516212adc", "format": 1 }, { @@ -5828,7 +5828,7 @@ "name": "meta/runtime.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "2e182a22d58fcfbca71fbef1992147e1cd87fc67648750e62b5955ec72521520", + "chksum_sha256": "720f48707e16c8707f33f2bc22bbd53207b492502669c2649547d652b5f99dcd", "format": 1 }, { @@ -5856,7 +5856,7 @@ "name": "playbooks/PnP_Workflow_Manager_Playbook.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "376cbea818770893c8c6eb980dcc8a64817ed71fc89808e1877cbbb0d262e810", + "chksum_sha256": "08b8fff76f4d14cb3667114120016e281ea732d831274e1d3b48df1203e6a840", "format": 1 }, { @@ -5891,7 +5891,7 @@ "name": "playbooks/device_provision_workflow.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "28bd738eea40bad4819ae44803c03830e448ae3b750d795572e3872b42bb43cd", + "chksum_sha256": "d7824efea5e33a458e49665dbe08e87acc2978da4925d834592808c495b9e3fc", "format": 1 }, { @@ -5940,7 +5940,7 @@ "name": "playbooks/PnP.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "0ace6a2cfb7cadc96e527dea4dad9616c35769151456271248cdea3c39a6c1df", + "chksum_sha256": "e580e727c566addb668411df8e6f0e8c694b1749f7f77078aad5366a133d18ba", "format": 1 }, { @@ -5968,7 +5968,7 @@ "name": "playbooks/device_details.template", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "92ccdcdfe15f46252c522238c97e5158d18676eccddd3a85f23a8f497b4e0c0d", + "chksum_sha256": "18175a2f86c3e2f5757bab3dcba655146e84383e24c39feb1b1f1404a25aee61", "format": 1 }, { @@ -6129,7 +6129,7 @@ "name": "playbooks/template_workflow_manager.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "1097e1586a9408998c3a1d513ad70492849e26d052b20816e27ebb60b8ee1d94", + "chksum_sha256": "dee57171b4a8bfd5f27f90921febf88baa6ee52f34bf9e88290da2b496ba87cb", "format": 1 }, { @@ -6283,14 +6283,14 @@ "name": "changelogs/changelog.yaml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "bcad14cdf9a6044c9347400ea1cbd6432ddd38c4b5b12e78a54bca57fa96355a", + "chksum_sha256": "0471f143c1a2248a79e6252e9ab2b902aa90ce8c49bade17d94c7840c109a871", "format": 1 }, { "name": "README.md", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "f1c14af9aa1e4bf92f028daab559d8912231284b04beeb34459404d0cc085ef1", + "chksum_sha256": "a22c72a870f94ee00f2b75ea7c907e3bc93d43c3479c8d56841b2bba927ce5db", "format": 1 }, { @@ -6314,18 +6314,25 @@ "chksum_sha256": null, "format": 1 }, + { + "name": ".github/workflows/sanity_tests_devel.yml", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "6c41a530b4e23f25d25005770db0857d676bf605a83386b6d9dbc6d16ce3740a", + "format": 1 + }, { "name": ".github/workflows/sanity_tests.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "5f73c04a8f73f124035ead77d2dfa8418bea6af501ffc3ddaf20eb04abac3bd6", + "chksum_sha256": "54f5ab1ffdbf3ad7f8992fb1f46398304ddaccaeca0ff885bad53be768af855f", "format": 1 }, { "name": ".github/workflows/docs.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "d8611ee91073e25e678934a5f53609f26282966c77c50c38527065bc467eb344", + "chksum_sha256": "f0a547c256a584df7a0a12f1f14604f37775b81f01cca623667a811c9d6ed6af", "format": 1 }, { diff --git a/ansible_collections/cisco/dnac/MANIFEST.json b/ansible_collections/cisco/dnac/MANIFEST.json index 4d4e0c65d..7c31dde5d 100644 --- a/ansible_collections/cisco/dnac/MANIFEST.json +++ b/ansible_collections/cisco/dnac/MANIFEST.json @@ -2,7 +2,7 @@ "collection_info": { "namespace": "cisco", "name": "dnac", - "version": "6.13.1", + "version": "6.13.3", "authors": [ "Rafael Campos ", "William Astorga ", @@ -31,7 +31,7 @@ "license": [], "license_file": "LICENSE", "dependencies": { - "ansible.utils": ">=2.0.0,<4.0" + "ansible.utils": ">=2.0.0,<5.0" }, "repository": "https://github.com/cisco-en-programmability/dnacenter-ansible", "documentation": "https://cisco-en-programmability.github.io/dnacenter-ansible/", @@ -42,7 +42,7 @@ "name": "FILES.json", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "5e6e6d846a1d245059dfee01ac8ee7dbd3af1e69fda28f415a6d670fb8bdbd93", + "chksum_sha256": "d5808375079300aef903ebc6a1308b5535b15fc6d726ea535ee8ff83f05aa969", "format": 1 }, "format": 1 diff --git a/ansible_collections/cisco/dnac/README.md b/ansible_collections/cisco/dnac/README.md index 2492d75b9..4d2835f33 100644 --- a/ansible_collections/cisco/dnac/README.md +++ b/ansible_collections/cisco/dnac/README.md @@ -15,11 +15,11 @@ The following table shows the supported versions. | Cisco DNA Center version | Ansible "cisco.dnac" version | Python "dnacentersdk" version | |--------------------------|------------------------------|-------------------------------| -| 2.1.1 | 3.0.0 | 2.2.5 | -| 2.2.2.3 | 3.3.1 | 2.3.3 | -| 2.2.3.3 | 6.4.0 | 2.4.11 | -| 2.3.3.0 | 6.6.4 | 2.5.5 | -| 2.3.5.3 | 6.13.0 | 2.6.0 | +| 2.1.1 | 3.0.0 | 2.2.5 | +| 2.2.2.3 | 3.3.1 | 2.3.3 | +| 2.2.3.3 | 6.4.0 | 2.4.11 | +| 2.3.3.0 | 6.6.4 | 2.5.5 | +| 2.3.5.3 | ^6.13.0 | ^2.6.0 | If your Ansible collection is older please consider updating it first. @@ -44,9 +44,9 @@ ansible-galaxy collection install cisco.dnac:3.3.1 ``` ## Requirements -- Ansible >= 2.9 -- [Python DNA Center SDK](https://github.com/cisco-en-programmability/dnacentersdk) v2.4.7 or newer -- Python >= 3.6, as the DNA Center SDK doesn't support Python version 2.x +- Ansible >= 2.15 +- [Python DNA Center SDK](https://github.com/cisco-en-programmability/dnacentersdk) v2.6.0 or newer +- Python >= 3.9, as the DNA Center SDK doesn't support Python version 2.x ## Install Ansible must be installed ([Install guide](https://docs.ansible.com/ansible/latest/installation_guide/intro_installation.html)) diff --git a/ansible_collections/cisco/dnac/changelogs/changelog.yaml b/ansible_collections/cisco/dnac/changelogs/changelog.yaml index a3408e7e5..81e4f4348 100644 --- a/ansible_collections/cisco/dnac/changelogs/changelog.yaml +++ b/ansible_collections/cisco/dnac/changelogs/changelog.yaml @@ -849,3 +849,20 @@ releases: - Added attributes 'dnac_api_task_timeout' and 'dnac_task_poll_interval' in intent and workflow_manager modules. - inventory_workflow_manager - Added attributes 'add_user_defined_field', 'update_interface_details', 'export_device_list' and 'admin_status' - inventory_workflow_manager - Removed attributes 'provision_wireless_device', 'reprovision_wired_device' + 6.13.2: + release_date: "2024-04-03" + changes: + release_summary: Enhancements in discovery, site, swim and inventory workflow manager modules. + minor_changes: + - Added the op_modifies=True when calling SDK APIs in the workflow manager modules. + - Added a method to validate IP addresses. + - Fixed a minor issue in the site workflow manager module. + - Updating galaxy.yml ansible.utils dependencies. + 6.13.3: + release_date: "2024-04-08" + changes: + release_summary: Enhancements in discovery, template, swim and inventory workflow manager modules. + minor_changes: + - Adding support to importing a template using JSON file + - Changes in discovery workflow manager modules relating to different states of the discovery job + - Changes in inventory and swim workflow manager modules. diff --git a/ansible_collections/cisco/dnac/meta/runtime.yml b/ansible_collections/cisco/dnac/meta/runtime.yml index bcb6dcedc..9912f4a7d 100644 --- a/ansible_collections/cisco/dnac/meta/runtime.yml +++ b/ansible_collections/cisco/dnac/meta/runtime.yml @@ -1,2 +1,2 @@ --- -requires_ansible: '>=2.14.0' \ No newline at end of file +requires_ansible: '>=2.15.0' \ No newline at end of file diff --git a/ansible_collections/cisco/dnac/playbooks/PnP.yml b/ansible_collections/cisco/dnac/playbooks/PnP.yml index 63bad68e0..31cb11f9b 100644 --- a/ansible_collections/cisco/dnac/playbooks/PnP.yml +++ b/ansible_collections/cisco/dnac/playbooks/PnP.yml @@ -66,7 +66,7 @@ template_name: "Ansible_PNP_Switch" image_name: cat9k_iosxe_npe.17.03.07.SPA.bin project_name: Onboarding Configuration - template_details: + template_params: hostname: SJC-Switch-1 interface: TwoGigabitEthernet1/0/2 device_info: @@ -108,4 +108,4 @@ - device_info: - serial_number: QD2425L8M7 #Will get deleted - serial_number: FTC2320E0HA #Doesn't exist in the inventory - - serial_number: FKC2310E0HB #Doesn't exist in the inventory \ No newline at end of file + - serial_number: FKC2310E0HB #Doesn't exist in the inventory diff --git a/ansible_collections/cisco/dnac/playbooks/PnP_Workflow_Manager_Playbook.yml b/ansible_collections/cisco/dnac/playbooks/PnP_Workflow_Manager_Playbook.yml index 846ebf3a7..0f1ff25c1 100644 --- a/ansible_collections/cisco/dnac/playbooks/PnP_Workflow_Manager_Playbook.yml +++ b/ansible_collections/cisco/dnac/playbooks/PnP_Workflow_Manager_Playbook.yml @@ -66,7 +66,7 @@ template_name: "Ansible_PNP_Switch" image_name: cat9k_iosxe_npe.17.03.07.SPA.bin project_name: Onboarding Configuration - template_details: + template_params: hostname: SJC-Switch-1 interface: TwoGigabitEthernet1/0/2 device_info: diff --git a/ansible_collections/cisco/dnac/playbooks/device_details.template b/ansible_collections/cisco/dnac/playbooks/device_details.template index 38c95c627..bdf58ab61 100644 --- a/ansible_collections/cisco/dnac/playbooks/device_details.template +++ b/ansible_collections/cisco/dnac/playbooks/device_details.template @@ -19,25 +19,7 @@ template_details: import_template: do_version: false project_name: 'Onboarding Configuration' - payload: - - name: 'Platinum-Onboarding-Template-J21' - device_types: - - product_family: 'Switches and Hubs' - productSeries: 'Cisco Catalyst 9300 Series Switches' - software_type: 'IOS' - language: 'JINJA' - - name: 'Platinum-Onboarding-Template-J22' - device_types: - - product_family: 'Switches and Hubs' - productSeries: 'Cisco Catalyst 9300 Series Switches' - software_type: 'IOS' - language: 'JINJA' - - name: 'Platinum-Onboarding-Template-J23' - device_types: - - product_family: 'Switches and Hubs' - productSeries: 'Cisco Catalyst 9300 Series Switches' - software_type: 'IOS' - language: 'JINJA' + template_file: 'JSON template file' device_details: - site_name: 'Global/Chennai/Trill' diff --git a/ansible_collections/cisco/dnac/playbooks/device_provision_workflow.yml b/ansible_collections/cisco/dnac/playbooks/device_provision_workflow.yml index 362556a09..acb3249a5 100644 --- a/ansible_collections/cisco/dnac/playbooks/device_provision_workflow.yml +++ b/ansible_collections/cisco/dnac/playbooks/device_provision_workflow.yml @@ -16,23 +16,23 @@ dnac_port: "{{ dnac_port }}" dnac_version: "{{ dnac_version }}" dnac_debug: "{{ dnac_debug }}" - + tasks: - name: Provision a wired device to a site - cisco.dnac.workflow_manager: + cisco.dnac.provision_workflow_manager: <<: *dnac_login dnac_log: True state: merged config_verify: True config: - site_name_hierarchy: Global/USA/San Francisco/BGL_18 - management_ip_address: 204.1.1.1 + management_ip_address: 204.1.2.2 - name: Unprovision a wired device from a site - cisco.dnac.workflow_manager: + cisco.dnac.provision_workflow_manager: <<: *dnac_login dnac_log: True state: deleted config: - - management_ip_address: 204.1.1.1 + - management_ip_address: 204.1.2.2 diff --git a/ansible_collections/cisco/dnac/playbooks/template_workflow_manager.yml b/ansible_collections/cisco/dnac/playbooks/template_workflow_manager.yml index 25b0ec797..3cfed07e7 100644 --- a/ansible_collections/cisco/dnac/playbooks/template_workflow_manager.yml +++ b/ansible_collections/cisco/dnac/playbooks/template_workflow_manager.yml @@ -13,7 +13,11 @@ dnac_password: "{{ dnac_password }}" dnac_verify: "{{ dnac_verify }}" dnac_debug: "{{ dnac_debug }}" - dnac_log: true + dnac_log: True + dnac_log_level: DEBUG + dnac_log_append: True + dnac_log_file_path: "{{ dnac_log_file_path }}" + validate_response_schema: False state: "merged" config_verify: true #ignore_errors: true #Enable this to continue execution even the task fails @@ -28,6 +32,16 @@ software_variant: "{{ item.variant }}" device_types: - product_family: "{{ item.family }}" + export: + project: + - Ansible_project + - Sample Velocity Templates + template: + - project_name: Onboarding Configuration + template_name: AP_Onboarding + import: + project: "{{ item.import_project }}" + template: "{{ item.import_template }}" register: template_result with_items: '{{ template_details }}' tags: diff --git a/ansible_collections/cisco/dnac/plugins/module_utils/dnac.py b/ansible_collections/cisco/dnac/plugins/module_utils/dnac.py index a12e7eaf4..1d4b804cd 100644 --- a/ansible_collections/cisco/dnac/plugins/module_utils/dnac.py +++ b/ansible_collections/cisco/dnac/plugins/module_utils/dnac.py @@ -27,6 +27,7 @@ import json # import datetime import inspect import re +import socket class DnacBase(): @@ -485,6 +486,66 @@ class DnacBase(): return new_config + def is_valid_ipv4(self, ip_address): + """ + Validates an IPv4 address. + + Parameters: + ip_address - String denoting the IPv4 address passed. + + Returns: + bool - Returns true if the passed IP address value is correct or it returns + false if it is incorrect + """ + + try: + socket.inet_aton(ip_address) + octets = ip_address.split('.') + if len(octets) != 4: + return False + for octet in octets: + if not 0 <= int(octet) <= 255: + return False + return True + except socket.error: + return False + + def is_path_exists(self, file_path): + """ + Check if the file path 'file_path' exists or not. + + Parameters: + file_path (string) - Path of the provided file. + + Returns: + True/False (bool) - True if the file path exists, else False. + """ + + if not os.path.exists(file_path): + return False + + return True + + def is_json(self, file_path): + """ + Check if the file in the file path is JSON or not. + + Parameters: + file_path (string) - Path of the provided file. + + Returns: + True/False (bool) - True if the file is in JSON format, else False. + """ + + try: + with open(file_path, 'r') as file: + json.load(file) + return True + + except (ValueError, FileNotFoundError): + self.log("The provided file '{0}' is not in JSON format".format(file_path), "CRITICAL") + return False + def is_list_complex(x): return isinstance(x[0], dict) or isinstance(x[0], list) diff --git a/ansible_collections/cisco/dnac/plugins/modules/accesspoint_configuration_details_by_task_id_info.py b/ansible_collections/cisco/dnac/plugins/modules/accesspoint_configuration_details_by_task_id_info.py index 63bf5df7e..642034e5c 100644 --- a/ansible_collections/cisco/dnac/plugins/modules/accesspoint_configuration_details_by_task_id_info.py +++ b/ansible_collections/cisco/dnac/plugins/modules/accesspoint_configuration_details_by_task_id_info.py @@ -24,8 +24,8 @@ options: - Task_id path parameter. Task id information of ap config. type: str requirements: -- dnacentersdk >= 2.5.5 -- python >= 3.5 +- dnacentersdk >= 2.6.0 +- python >= 3.9 seealso: - name: Cisco DNA Center documentation for Wireless GetAccessPointConfigurationTaskResult description: Complete reference of the GetAccessPointConfigurationTaskResult API. diff --git a/ansible_collections/cisco/dnac/plugins/modules/app_policy_default_info.py b/ansible_collections/cisco/dnac/plugins/modules/app_policy_default_info.py index 3ad0878fb..921f7a095 100644 --- a/ansible_collections/cisco/dnac/plugins/modules/app_policy_default_info.py +++ b/ansible_collections/cisco/dnac/plugins/modules/app_policy_default_info.py @@ -20,8 +20,8 @@ options: description: Additional headers. type: dict requirements: -- dnacentersdk >= 2.5.5 -- python >= 3.5 +- dnacentersdk >= 2.6.0 +- python >= 3.9 seealso: - name: Cisco DNA Center documentation for Application Policy GetApplicationPolicyDefault description: Complete reference of the GetApplicationPolicyDefault API. diff --git a/ansible_collections/cisco/dnac/plugins/modules/app_policy_info.py b/ansible_collections/cisco/dnac/plugins/modules/app_policy_info.py index d70d8fd44..3479d1ede 100644 --- a/ansible_collections/cisco/dnac/plugins/modules/app_policy_info.py +++ b/ansible_collections/cisco/dnac/plugins/modules/app_policy_info.py @@ -24,8 +24,8 @@ options: - PolicyScope query parameter. Policy scope name. type: str requirements: -- dnacentersdk >= 2.5.5 -- python >= 3.5 +- dnacentersdk >= 2.6.0 +- python >= 3.9 seealso: - name: Cisco DNA Center documentation for Application Policy GetApplicationPolicy description: Complete reference of the GetApplicationPolicy API. diff --git a/ansible_collections/cisco/dnac/plugins/modules/app_policy_intent_create.py b/ansible_collections/cisco/dnac/plugins/modules/app_policy_intent_create.py index 6c1b46832..fd487ca0c 100644 --- a/ansible_collections/cisco/dnac/plugins/modules/app_policy_intent_create.py +++ b/ansible_collections/cisco/dnac/plugins/modules/app_policy_intent_create.py @@ -226,8 +226,8 @@ options: type: dict type: list requirements: -- dnacentersdk >= 2.5.5 -- python >= 3.5 +- dnacentersdk >= 2.6.0 +- python >= 3.9 seealso: - name: Cisco DNA Center documentation for Application Policy ApplicationPolicyIntent description: Complete reference of the ApplicationPolicyIntent API. diff --git a/ansible_collections/cisco/dnac/plugins/modules/app_policy_queuing_profile.py b/ansible_collections/cisco/dnac/plugins/modules/app_policy_queuing_profile.py index 769e87fc1..9260ffbf5 100644 --- a/ansible_collections/cisco/dnac/plugins/modules/app_policy_queuing_profile.py +++ b/ansible_collections/cisco/dnac/plugins/modules/app_policy_queuing_profile.py @@ -89,8 +89,8 @@ options: type: str type: list requirements: -- dnacentersdk >= 2.5.5 -- python >= 3.5 +- dnacentersdk >= 2.6.0 +- python >= 3.9 seealso: - name: Cisco DNA Center documentation for Application Policy CreateApplicationPolicyQueuingProfile description: Complete reference of the CreateApplicationPolicyQueuingProfile API. diff --git a/ansible_collections/cisco/dnac/plugins/modules/app_policy_queuing_profile_count_info.py b/ansible_collections/cisco/dnac/plugins/modules/app_policy_queuing_profile_count_info.py index 5f814ac1d..2a3b2c4df 100644 --- a/ansible_collections/cisco/dnac/plugins/modules/app_policy_queuing_profile_count_info.py +++ b/ansible_collections/cisco/dnac/plugins/modules/app_policy_queuing_profile_count_info.py @@ -20,8 +20,8 @@ options: description: Additional headers. type: dict requirements: -- dnacentersdk >= 2.5.5 -- python >= 3.5 +- dnacentersdk >= 2.6.0 +- python >= 3.9 seealso: - name: Cisco DNA Center documentation for Application Policy GetApplicationPolicyQueuingProfileCount description: Complete reference of the GetApplicationPolicyQueuingProfileCount API. diff --git a/ansible_collections/cisco/dnac/plugins/modules/app_policy_queuing_profile_info.py b/ansible_collections/cisco/dnac/plugins/modules/app_policy_queuing_profile_info.py index 860545f2c..bb89873a6 100644 --- a/ansible_collections/cisco/dnac/plugins/modules/app_policy_queuing_profile_info.py +++ b/ansible_collections/cisco/dnac/plugins/modules/app_policy_queuing_profile_info.py @@ -24,8 +24,8 @@ options: - Name query parameter. Queuing profile name. type: str requirements: -- dnacentersdk >= 2.5.5 -- python >= 3.5 +- dnacentersdk >= 2.6.0 +- python >= 3.9 seealso: - name: Cisco DNA Center documentation for Application Policy GetApplicationPolicyQueuingProfile description: Complete reference of the GetApplicationPolicyQueuingProfile API. diff --git a/ansible_collections/cisco/dnac/plugins/modules/application_sets.py b/ansible_collections/cisco/dnac/plugins/modules/application_sets.py index 1210f90d6..b4c5dd14c 100644 --- a/ansible_collections/cisco/dnac/plugins/modules/application_sets.py +++ b/ansible_collections/cisco/dnac/plugins/modules/application_sets.py @@ -29,8 +29,8 @@ options: type: str type: list requirements: -- dnacentersdk >= 2.5.5 -- python >= 3.5 +- dnacentersdk >= 2.6.0 +- python >= 3.9 seealso: - name: Cisco DNA Center documentation for Application Policy CreateApplicationSet description: Complete reference of the CreateApplicationSet API. diff --git a/ansible_collections/cisco/dnac/plugins/modules/application_sets_count_info.py b/ansible_collections/cisco/dnac/plugins/modules/application_sets_count_info.py index b71923719..bd6336fb7 100644 --- a/ansible_collections/cisco/dnac/plugins/modules/application_sets_count_info.py +++ b/ansible_collections/cisco/dnac/plugins/modules/application_sets_count_info.py @@ -20,8 +20,8 @@ options: description: Additional headers. type: dict requirements: -- dnacentersdk >= 2.5.5 -- python >= 3.5 +- dnacentersdk >= 2.6.0 +- python >= 3.9 seealso: - name: Cisco DNA Center documentation for Application Policy GetApplicationSetsCount description: Complete reference of the GetApplicationSetsCount API. diff --git a/ansible_collections/cisco/dnac/plugins/modules/application_sets_info.py b/ansible_collections/cisco/dnac/plugins/modules/application_sets_info.py index 844341de0..168674c87 100644 --- a/ansible_collections/cisco/dnac/plugins/modules/application_sets_info.py +++ b/ansible_collections/cisco/dnac/plugins/modules/application_sets_info.py @@ -32,8 +32,8 @@ options: - Name query parameter. type: str requirements: -- dnacentersdk >= 2.5.5 -- python >= 3.5 +- dnacentersdk >= 2.6.0 +- python >= 3.9 seealso: - name: Cisco DNA Center documentation for Application Policy GetApplicationSets description: Complete reference of the GetApplicationSets API. diff --git a/ansible_collections/cisco/dnac/plugins/modules/applications.py b/ansible_collections/cisco/dnac/plugins/modules/applications.py index 22c309bd4..43c18a12b 100644 --- a/ansible_collections/cisco/dnac/plugins/modules/applications.py +++ b/ansible_collections/cisco/dnac/plugins/modules/applications.py @@ -133,8 +133,8 @@ options: type: list type: list requirements: -- dnacentersdk >= 2.5.5 -- python >= 3.5 +- dnacentersdk >= 2.6.0 +- python >= 3.9 seealso: - name: Cisco DNA Center documentation for Application Policy CreateApplication description: Complete reference of the CreateApplication API. diff --git a/ansible_collections/cisco/dnac/plugins/modules/applications_count_info.py b/ansible_collections/cisco/dnac/plugins/modules/applications_count_info.py index 1c725cb14..cf4eb7d8d 100644 --- a/ansible_collections/cisco/dnac/plugins/modules/applications_count_info.py +++ b/ansible_collections/cisco/dnac/plugins/modules/applications_count_info.py @@ -20,8 +20,8 @@ options: description: Additional headers. type: dict requirements: -- dnacentersdk >= 2.5.5 -- python >= 3.5 +- dnacentersdk >= 2.6.0 +- python >= 3.9 seealso: - name: Cisco DNA Center documentation for Application Policy GetApplicationsCount description: Complete reference of the GetApplicationsCount API. diff --git a/ansible_collections/cisco/dnac/plugins/modules/applications_health_info.py b/ansible_collections/cisco/dnac/plugins/modules/applications_health_info.py index 4bc998401..883fd5398 100644 --- a/ansible_collections/cisco/dnac/plugins/modules/applications_health_info.py +++ b/ansible_collections/cisco/dnac/plugins/modules/applications_health_info.py @@ -64,8 +64,8 @@ options: - ApplicationName query parameter. The name of the application to get information on. type: str requirements: -- dnacentersdk >= 2.5.5 -- python >= 3.5 +- dnacentersdk >= 2.6.0 +- python >= 3.9 seealso: - name: Cisco DNA Center documentation for Applications Applications description: Complete reference of the Applications API. diff --git a/ansible_collections/cisco/dnac/plugins/modules/applications_info.py b/ansible_collections/cisco/dnac/plugins/modules/applications_info.py index 431d62e37..6570ca75d 100644 --- a/ansible_collections/cisco/dnac/plugins/modules/applications_info.py +++ b/ansible_collections/cisco/dnac/plugins/modules/applications_info.py @@ -32,8 +32,8 @@ options: - Name query parameter. Application's name. type: str requirements: -- dnacentersdk >= 2.5.5 -- python >= 3.5 +- dnacentersdk >= 2.6.0 +- python >= 3.9 seealso: - name: Cisco DNA Center documentation for Application Policy GetApplications description: Complete reference of the GetApplications API. diff --git a/ansible_collections/cisco/dnac/plugins/modules/assign_device_to_site.py b/ansible_collections/cisco/dnac/plugins/modules/assign_device_to_site.py index fbd3cec3d..c1da97fe9 100644 --- a/ansible_collections/cisco/dnac/plugins/modules/assign_device_to_site.py +++ b/ansible_collections/cisco/dnac/plugins/modules/assign_device_to_site.py @@ -31,8 +31,8 @@ options: description: SiteId path parameter. Site id to which site the device to assign. type: str requirements: -- dnacentersdk >= 2.5.5 -- python >= 3.5 +- dnacentersdk >= 2.6.0 +- python >= 3.9 seealso: - name: Cisco DNA Center documentation for AssignDevicesToSite description: Complete reference of the AssignDevicesToSite API. diff --git a/ansible_collections/cisco/dnac/plugins/modules/associate_site_to_network_profile.py b/ansible_collections/cisco/dnac/plugins/modules/associate_site_to_network_profile.py index 7a2aab8e5..b01851556 100644 --- a/ansible_collections/cisco/dnac/plugins/modules/associate_site_to_network_profile.py +++ b/ansible_collections/cisco/dnac/plugins/modules/associate_site_to_network_profile.py @@ -23,8 +23,8 @@ options: description: SiteId path parameter. Site Id to be associated. type: str requirements: -- dnacentersdk >= 2.5.5 -- python >= 3.5 +- dnacentersdk >= 2.6.0 +- python >= 3.9 seealso: - name: Cisco DNA Center documentation for Site Design Associate description: Complete reference of the Associate API. diff --git a/ansible_collections/cisco/dnac/plugins/modules/authentication_import_certificate.py b/ansible_collections/cisco/dnac/plugins/modules/authentication_import_certificate.py index 7cfca0c47..15cb6d2b6 100644 --- a/ansible_collections/cisco/dnac/plugins/modules/authentication_import_certificate.py +++ b/ansible_collections/cisco/dnac/plugins/modules/authentication_import_certificate.py @@ -30,8 +30,8 @@ options: description: PkPassword query parameter. Private Key Passsword. type: str requirements: -- dnacentersdk >= 2.5.5 -- python >= 3.5 +- dnacentersdk >= 2.6.0 +- python >= 3.9 seealso: - name: Cisco DNA Center documentation for Authentication Management ImportCertificate description: Complete reference of the ImportCertificate API. diff --git a/ansible_collections/cisco/dnac/plugins/modules/authentication_import_certificate_p12.py b/ansible_collections/cisco/dnac/plugins/modules/authentication_import_certificate_p12.py index ab19906f7..23d98d277 100644 --- a/ansible_collections/cisco/dnac/plugins/modules/authentication_import_certificate_p12.py +++ b/ansible_collections/cisco/dnac/plugins/modules/authentication_import_certificate_p12.py @@ -30,8 +30,8 @@ options: description: PkPassword query parameter. Private Key Passsword. type: str requirements: -- dnacentersdk >= 2.5.5 -- python >= 3.5 +- dnacentersdk >= 2.6.0 +- python >= 3.9 seealso: - name: Cisco DNA Center documentation for Authentication Management ImportCertificateP12 description: Complete reference of the ImportCertificateP12 API. diff --git a/ansible_collections/cisco/dnac/plugins/modules/authentication_policy_servers_info.py b/ansible_collections/cisco/dnac/plugins/modules/authentication_policy_servers_info.py index cb5124de7..d0366ecc2 100644 --- a/ansible_collections/cisco/dnac/plugins/modules/authentication_policy_servers_info.py +++ b/ansible_collections/cisco/dnac/plugins/modules/authentication_policy_servers_info.py @@ -32,8 +32,8 @@ options: - Role query parameter. Authentication and Policy Server Role (Example primary, secondary). type: str requirements: -- dnacentersdk >= 2.5.5 -- python >= 3.5 +- dnacentersdk >= 2.6.0 +- python >= 3.9 seealso: - name: Cisco DNA Center documentation for System Settings GetAuthenticationAndPolicyServers description: Complete reference of the GetAuthenticationAndPolicyServers API. diff --git a/ansible_collections/cisco/dnac/plugins/modules/buildings_planned_access_points_info.py b/ansible_collections/cisco/dnac/plugins/modules/buildings_planned_access_points_info.py index 07dda3ca9..20aaae21a 100644 --- a/ansible_collections/cisco/dnac/plugins/modules/buildings_planned_access_points_info.py +++ b/ansible_collections/cisco/dnac/plugins/modules/buildings_planned_access_points_info.py @@ -36,8 +36,8 @@ options: - Radios query parameter. Inlcude planned radio details. type: bool requirements: -- dnacentersdk >= 2.5.5 -- python >= 3.5 +- dnacentersdk >= 2.6.0 +- python >= 3.9 seealso: - name: Cisco DNA Center documentation for Devices GetPlannedAccessPointsForBuilding description: Complete reference of the GetPlannedAccessPointsForBuilding API. diff --git a/ansible_collections/cisco/dnac/plugins/modules/business_sda_hostonboarding_ssid_ippool.py b/ansible_collections/cisco/dnac/plugins/modules/business_sda_hostonboarding_ssid_ippool.py index daa0bbc00..53a47bdc9 100644 --- a/ansible_collections/cisco/dnac/plugins/modules/business_sda_hostonboarding_ssid_ippool.py +++ b/ansible_collections/cisco/dnac/plugins/modules/business_sda_hostonboarding_ssid_ippool.py @@ -34,8 +34,8 @@ options: description: VLAN Name. type: str requirements: -- dnacentersdk >= 2.5.5 -- python >= 3.5 +- dnacentersdk >= 2.6.0 +- python >= 3.9 seealso: - name: Cisco DNA Center documentation for Fabric Wireless AddSSIDToIPPoolMapping description: Complete reference of the AddSSIDToIPPoolMapping API. diff --git a/ansible_collections/cisco/dnac/plugins/modules/business_sda_hostonboarding_ssid_ippool_info.py b/ansible_collections/cisco/dnac/plugins/modules/business_sda_hostonboarding_ssid_ippool_info.py index 6ecfdd80f..7de5bd47f 100644 --- a/ansible_collections/cisco/dnac/plugins/modules/business_sda_hostonboarding_ssid_ippool_info.py +++ b/ansible_collections/cisco/dnac/plugins/modules/business_sda_hostonboarding_ssid_ippool_info.py @@ -28,8 +28,8 @@ options: - SiteNameHierarchy query parameter. Site Name Heirarchy. type: str requirements: -- dnacentersdk >= 2.5.5 -- python >= 3.5 +- dnacentersdk >= 2.6.0 +- python >= 3.9 seealso: - name: Cisco DNA Center documentation for Fabric Wireless GetSSIDToIPPoolMapping description: Complete reference of the GetSSIDToIPPoolMapping API. diff --git a/ansible_collections/cisco/dnac/plugins/modules/business_sda_virtual_network_summary_info.py b/ansible_collections/cisco/dnac/plugins/modules/business_sda_virtual_network_summary_info.py index 941822ad5..beb749da6 100644 --- a/ansible_collections/cisco/dnac/plugins/modules/business_sda_virtual_network_summary_info.py +++ b/ansible_collections/cisco/dnac/plugins/modules/business_sda_virtual_network_summary_info.py @@ -24,8 +24,8 @@ options: - SiteNameHierarchy query parameter. Complete fabric siteNameHierarchy Path. type: str requirements: -- dnacentersdk >= 2.5.5 -- python >= 3.5 +- dnacentersdk >= 2.6.0 +- python >= 3.9 seealso: - name: Cisco DNA Center documentation for GetVirtualNetworkSummary description: Complete reference of the GetVirtualNetworkSummary API. diff --git a/ansible_collections/cisco/dnac/plugins/modules/business_sda_wireless_controller_create.py b/ansible_collections/cisco/dnac/plugins/modules/business_sda_wireless_controller_create.py index 1d9993a6c..9b1619f90 100644 --- a/ansible_collections/cisco/dnac/plugins/modules/business_sda_wireless_controller_create.py +++ b/ansible_collections/cisco/dnac/plugins/modules/business_sda_wireless_controller_create.py @@ -23,8 +23,8 @@ options: description: Site Name Hierarchy. type: str requirements: -- dnacentersdk >= 2.5.5 -- python >= 3.5 +- dnacentersdk >= 2.6.0 +- python >= 3.9 seealso: - name: Cisco DNA Center documentation for Fabric Wireless AddWLCToFabricDomain description: Complete reference of the AddWLCToFabricDomain API. diff --git a/ansible_collections/cisco/dnac/plugins/modules/business_sda_wireless_controller_delete.py b/ansible_collections/cisco/dnac/plugins/modules/business_sda_wireless_controller_delete.py index 4ca615500..3231a6e23 100644 --- a/ansible_collections/cisco/dnac/plugins/modules/business_sda_wireless_controller_delete.py +++ b/ansible_collections/cisco/dnac/plugins/modules/business_sda_wireless_controller_delete.py @@ -23,8 +23,8 @@ options: description: Additional headers. type: dict requirements: -- dnacentersdk >= 2.5.5 -- python >= 3.5 +- dnacentersdk >= 2.6.0 +- python >= 3.9 seealso: - name: Cisco DNA Center documentation for Fabric Wireless RemoveWLCFromFabricDomain description: Complete reference of the RemoveWLCFromFabricDomain API. diff --git a/ansible_collections/cisco/dnac/plugins/modules/cli_credential.py b/ansible_collections/cisco/dnac/plugins/modules/cli_credential.py index d7b542962..9a7c0e489 100644 --- a/ansible_collections/cisco/dnac/plugins/modules/cli_credential.py +++ b/ansible_collections/cisco/dnac/plugins/modules/cli_credential.py @@ -45,8 +45,8 @@ options: description: Cli Credential's username. type: str requirements: -- dnacentersdk >= 2.5.5 -- python >= 3.5 +- dnacentersdk >= 2.6.0 +- python >= 3.9 seealso: - name: Cisco DNA Center documentation for Discovery CreateCLICredentials description: Complete reference of the CreateCLICredentials API. diff --git a/ansible_collections/cisco/dnac/plugins/modules/client_detail_info.py b/ansible_collections/cisco/dnac/plugins/modules/client_detail_info.py index a823da7b5..5cc6ca6d9 100644 --- a/ansible_collections/cisco/dnac/plugins/modules/client_detail_info.py +++ b/ansible_collections/cisco/dnac/plugins/modules/client_detail_info.py @@ -28,8 +28,8 @@ options: - MacAddress query parameter. MAC Address of the client. type: str requirements: -- dnacentersdk >= 2.5.5 -- python >= 3.5 +- dnacentersdk >= 2.6.0 +- python >= 3.9 seealso: - name: Cisco DNA Center documentation for Clients GetClientDetail description: Complete reference of the GetClientDetail API. diff --git a/ansible_collections/cisco/dnac/plugins/modules/client_enrichment_details_info.py b/ansible_collections/cisco/dnac/plugins/modules/client_enrichment_details_info.py index da1fd47d2..54be2389a 100644 --- a/ansible_collections/cisco/dnac/plugins/modules/client_enrichment_details_info.py +++ b/ansible_collections/cisco/dnac/plugins/modules/client_enrichment_details_info.py @@ -22,8 +22,8 @@ options: description: Additional headers. type: dict requirements: -- dnacentersdk >= 2.5.5 -- python >= 3.5 +- dnacentersdk >= 2.6.0 +- python >= 3.9 seealso: - name: Cisco DNA Center documentation for Clients GetClientEnrichmentDetails description: Complete reference of the GetClientEnrichmentDetails API. diff --git a/ansible_collections/cisco/dnac/plugins/modules/client_health_info.py b/ansible_collections/cisco/dnac/plugins/modules/client_health_info.py index 2def53c98..f036bb5bd 100644 --- a/ansible_collections/cisco/dnac/plugins/modules/client_health_info.py +++ b/ansible_collections/cisco/dnac/plugins/modules/client_health_info.py @@ -24,8 +24,8 @@ options: - Timestamp query parameter. Epoch time(in milliseconds) when the Client health data is required. type: str requirements: -- dnacentersdk >= 2.5.5 -- python >= 3.5 +- dnacentersdk >= 2.6.0 +- python >= 3.9 seealso: - name: Cisco DNA Center documentation for Clients GetOverallClientHealth description: Complete reference of the GetOverallClientHealth API. diff --git a/ansible_collections/cisco/dnac/plugins/modules/client_proximity_info.py b/ansible_collections/cisco/dnac/plugins/modules/client_proximity_info.py index d65c51e09..7d30d7542 100644 --- a/ansible_collections/cisco/dnac/plugins/modules/client_proximity_info.py +++ b/ansible_collections/cisco/dnac/plugins/modules/client_proximity_info.py @@ -40,8 +40,8 @@ options: with a minimum 5 minutes. type: int requirements: -- dnacentersdk >= 2.5.5 -- python >= 3.5 +- dnacentersdk >= 2.6.0 +- python >= 3.9 seealso: - name: Cisco DNA Center documentation for Clients ClientProximity description: Complete reference of the ClientProximity API. diff --git a/ansible_collections/cisco/dnac/plugins/modules/command_runner_run_command.py b/ansible_collections/cisco/dnac/plugins/modules/command_runner_run_command.py index 34222b28f..5b12002ed 100644 --- a/ansible_collections/cisco/dnac/plugins/modules/command_runner_run_command.py +++ b/ansible_collections/cisco/dnac/plugins/modules/command_runner_run_command.py @@ -34,8 +34,8 @@ options: description: Command Runner Run Command's timeout. type: int requirements: -- dnacentersdk >= 2.5.5 -- python >= 3.5 +- dnacentersdk >= 2.6.0 +- python >= 3.9 seealso: - name: Cisco DNA Center documentation for Command Runner RunReadOnlyCommandsOnDevicesToGetTheirRealTimeConfiguration description: Complete reference of the RunReadOnlyCommandsOnDevicesToGetTheirRealTimeConfiguration API. diff --git a/ansible_collections/cisco/dnac/plugins/modules/compliance_check_run.py b/ansible_collections/cisco/dnac/plugins/modules/compliance_check_run.py index 6d9a5c6bc..c244f41f8 100644 --- a/ansible_collections/cisco/dnac/plugins/modules/compliance_check_run.py +++ b/ansible_collections/cisco/dnac/plugins/modules/compliance_check_run.py @@ -28,8 +28,8 @@ options: description: TriggerFull flag. type: bool requirements: -- dnacentersdk >= 2.5.5 -- python >= 3.5 +- dnacentersdk >= 2.6.0 +- python >= 3.9 seealso: - name: Cisco DNA Center documentation for Compliance RunCompliance description: Complete reference of the RunCompliance API. diff --git a/ansible_collections/cisco/dnac/plugins/modules/compliance_device_by_id_info.py b/ansible_collections/cisco/dnac/plugins/modules/compliance_device_by_id_info.py index 92e2f73bb..99d967c02 100644 --- a/ansible_collections/cisco/dnac/plugins/modules/compliance_device_by_id_info.py +++ b/ansible_collections/cisco/dnac/plugins/modules/compliance_device_by_id_info.py @@ -46,8 +46,8 @@ options: - Value query parameter. Extended attribute value. type: str requirements: -- dnacentersdk >= 2.5.5 -- python >= 3.5 +- dnacentersdk >= 2.6.0 +- python >= 3.9 seealso: - name: Cisco DNA Center documentation for Compliance ComplianceDetailsOfDevice description: Complete reference of the ComplianceDetailsOfDevice API. diff --git a/ansible_collections/cisco/dnac/plugins/modules/compliance_device_details_count_info.py b/ansible_collections/cisco/dnac/plugins/modules/compliance_device_details_count_info.py index 2bc29a305..a51939ed4 100644 --- a/ansible_collections/cisco/dnac/plugins/modules/compliance_device_details_count_info.py +++ b/ansible_collections/cisco/dnac/plugins/modules/compliance_device_details_count_info.py @@ -32,8 +32,8 @@ options: 'IN_PROGRESS', 'NOT_AVAILABLE', 'NOT_APPLICABLE', 'ERROR'. type: str requirements: -- dnacentersdk >= 2.5.5 -- python >= 3.5 +- dnacentersdk >= 2.6.0 +- python >= 3.9 seealso: - name: Cisco DNA Center documentation for Compliance GetComplianceDetailCount description: Complete reference of the GetComplianceDetailCount API. diff --git a/ansible_collections/cisco/dnac/plugins/modules/compliance_device_details_info.py b/ansible_collections/cisco/dnac/plugins/modules/compliance_device_details_info.py index 9eb00777b..bc06458f2 100644 --- a/ansible_collections/cisco/dnac/plugins/modules/compliance_device_details_info.py +++ b/ansible_collections/cisco/dnac/plugins/modules/compliance_device_details_info.py @@ -44,8 +44,8 @@ options: - Limit query parameter. Number of records to be retrieved. type: int requirements: -- dnacentersdk >= 2.5.5 -- python >= 3.5 +- dnacentersdk >= 2.6.0 +- python >= 3.9 seealso: - name: Cisco DNA Center documentation for Compliance GetComplianceDetail description: Complete reference of the GetComplianceDetail API. diff --git a/ansible_collections/cisco/dnac/plugins/modules/compliance_device_info.py b/ansible_collections/cisco/dnac/plugins/modules/compliance_device_info.py index d256f41d8..38eaafb12 100644 --- a/ansible_collections/cisco/dnac/plugins/modules/compliance_device_info.py +++ b/ansible_collections/cisco/dnac/plugins/modules/compliance_device_info.py @@ -40,8 +40,8 @@ options: - Limit query parameter. Number of records to be retrieved. type: int requirements: -- dnacentersdk >= 2.5.5 -- python >= 3.5 +- dnacentersdk >= 2.6.0 +- python >= 3.9 seealso: - name: Cisco DNA Center documentation for Compliance DeviceComplianceStatus description: Complete reference of the DeviceComplianceStatus API. diff --git a/ansible_collections/cisco/dnac/plugins/modules/compliance_device_status_count_info.py b/ansible_collections/cisco/dnac/plugins/modules/compliance_device_status_count_info.py index ef33aae08..6c7897f94 100644 --- a/ansible_collections/cisco/dnac/plugins/modules/compliance_device_status_count_info.py +++ b/ansible_collections/cisco/dnac/plugins/modules/compliance_device_status_count_info.py @@ -26,8 +26,8 @@ options: 'IN_PROGRESS', 'NOT_AVAILABLE', 'NOT_APPLICABLE', 'ERROR'. type: str requirements: -- dnacentersdk >= 2.5.5 -- python >= 3.5 +- dnacentersdk >= 2.6.0 +- python >= 3.9 seealso: - name: Cisco DNA Center documentation for Compliance GetComplianceStatusCount description: Complete reference of the GetComplianceStatusCount API. diff --git a/ansible_collections/cisco/dnac/plugins/modules/configuration_template.py b/ansible_collections/cisco/dnac/plugins/modules/configuration_template.py index 35dc21ac5..05e7acf35 100644 --- a/ansible_collections/cisco/dnac/plugins/modules/configuration_template.py +++ b/ansible_collections/cisco/dnac/plugins/modules/configuration_template.py @@ -512,8 +512,8 @@ options: description: Current version of template. type: str requirements: -- dnacentersdk >= 2.5.5 -- python >= 3.5 +- dnacentersdk >= 2.6.0 +- python >= 3.9 seealso: - name: Cisco DNA Center documentation for Configuration Templates DeletesTheTemplate description: Complete reference of the DeletesTheTemplate API. diff --git a/ansible_collections/cisco/dnac/plugins/modules/configuration_template_clone.py b/ansible_collections/cisco/dnac/plugins/modules/configuration_template_clone.py index be0a5c1cb..c21257ba4 100644 --- a/ansible_collections/cisco/dnac/plugins/modules/configuration_template_clone.py +++ b/ansible_collections/cisco/dnac/plugins/modules/configuration_template_clone.py @@ -28,8 +28,8 @@ options: description: TemplateId path parameter. UUID of the template to clone it. type: str requirements: -- dnacentersdk >= 2.5.5 -- python >= 3.5 +- dnacentersdk >= 2.6.0 +- python >= 3.9 seealso: - name: Cisco DNA Center documentation for Configuration Templates CreatesACloneOfTheGivenTemplate description: Complete reference of the CreatesACloneOfTheGivenTemplate API. diff --git a/ansible_collections/cisco/dnac/plugins/modules/configuration_template_create.py b/ansible_collections/cisco/dnac/plugins/modules/configuration_template_create.py index 4bb6a9a7b..f5beee649 100644 --- a/ansible_collections/cisco/dnac/plugins/modules/configuration_template_create.py +++ b/ansible_collections/cisco/dnac/plugins/modules/configuration_template_create.py @@ -508,8 +508,8 @@ options: description: Current version of template. type: str requirements: -- dnacentersdk >= 2.5.5 -- python >= 3.5 +- dnacentersdk >= 2.6.0 +- python >= 3.9 seealso: - name: Cisco DNA Center documentation for Configuration Templates CreateTemplate description: Complete reference of the CreateTemplate API. diff --git a/ansible_collections/cisco/dnac/plugins/modules/configuration_template_deploy.py b/ansible_collections/cisco/dnac/plugins/modules/configuration_template_deploy.py index 537fa850c..a1b1b5265 100644 --- a/ansible_collections/cisco/dnac/plugins/modules/configuration_template_deploy.py +++ b/ansible_collections/cisco/dnac/plugins/modules/configuration_template_deploy.py @@ -55,8 +55,8 @@ options: description: UUID of template to be provisioned. type: str requirements: -- dnacentersdk >= 2.5.5 -- python >= 3.5 +- dnacentersdk >= 2.6.0 +- python >= 3.9 seealso: - name: Cisco DNA Center documentation for Configuration Templates DeployTemplate description: Complete reference of the DeployTemplate API. diff --git a/ansible_collections/cisco/dnac/plugins/modules/configuration_template_deploy_status_info.py b/ansible_collections/cisco/dnac/plugins/modules/configuration_template_deploy_status_info.py index 21fd83a51..46c7439eb 100644 --- a/ansible_collections/cisco/dnac/plugins/modules/configuration_template_deploy_status_info.py +++ b/ansible_collections/cisco/dnac/plugins/modules/configuration_template_deploy_status_info.py @@ -24,8 +24,8 @@ options: - DeploymentId path parameter. UUID of deployment to retrieve template deployment status. type: str requirements: -- dnacentersdk >= 2.5.5 -- python >= 3.5 +- dnacentersdk >= 2.6.0 +- python >= 3.9 seealso: - name: Cisco DNA Center documentation for Configuration Templates StatusOfTemplateDeployment description: Complete reference of the StatusOfTemplateDeployment API. diff --git a/ansible_collections/cisco/dnac/plugins/modules/configuration_template_deploy_v2.py b/ansible_collections/cisco/dnac/plugins/modules/configuration_template_deploy_v2.py index 399441706..af7f1094d 100644 --- a/ansible_collections/cisco/dnac/plugins/modules/configuration_template_deploy_v2.py +++ b/ansible_collections/cisco/dnac/plugins/modules/configuration_template_deploy_v2.py @@ -55,8 +55,8 @@ options: description: UUID of template to be provisioned. type: str requirements: -- dnacentersdk >= 2.5.5 -- python >= 3.5 +- dnacentersdk >= 2.6.0 +- python >= 3.9 seealso: - name: Cisco DNA Center documentation for Configuration Templates DeployTemplateV2 description: Complete reference of the DeployTemplateV2 API. diff --git a/ansible_collections/cisco/dnac/plugins/modules/configuration_template_export_project.py b/ansible_collections/cisco/dnac/plugins/modules/configuration_template_export_project.py index 377f4fbeb..f41475005 100644 --- a/ansible_collections/cisco/dnac/plugins/modules/configuration_template_export_project.py +++ b/ansible_collections/cisco/dnac/plugins/modules/configuration_template_export_project.py @@ -21,8 +21,8 @@ options: elements: dict type: list requirements: -- dnacentersdk >= 2.5.5 -- python >= 3.5 +- dnacentersdk >= 2.6.0 +- python >= 3.9 seealso: - name: Cisco DNA Center documentation for Configuration Templates ExportsTheProjectsForAGivenCriteria description: Complete reference of the ExportsTheProjectsForAGivenCriteria API. diff --git a/ansible_collections/cisco/dnac/plugins/modules/configuration_template_export_template.py b/ansible_collections/cisco/dnac/plugins/modules/configuration_template_export_template.py index df4a58323..d460cef40 100644 --- a/ansible_collections/cisco/dnac/plugins/modules/configuration_template_export_template.py +++ b/ansible_collections/cisco/dnac/plugins/modules/configuration_template_export_template.py @@ -21,8 +21,8 @@ options: elements: dict type: list requirements: -- dnacentersdk >= 2.5.5 -- python >= 3.5 +- dnacentersdk >= 2.6.0 +- python >= 3.9 seealso: - name: Cisco DNA Center documentation for Configuration Templates ExportsTheTemplatesForAGivenCriteria description: Complete reference of the ExportsTheTemplatesForAGivenCriteria API. diff --git a/ansible_collections/cisco/dnac/plugins/modules/configuration_template_import_project.py b/ansible_collections/cisco/dnac/plugins/modules/configuration_template_import_project.py index 284665863..37b2096e4 100644 --- a/ansible_collections/cisco/dnac/plugins/modules/configuration_template_import_project.py +++ b/ansible_collections/cisco/dnac/plugins/modules/configuration_template_import_project.py @@ -23,8 +23,8 @@ options: fails with 'Template already exists' error. type: bool requirements: -- dnacentersdk >= 2.5.5 -- python >= 3.5 +- dnacentersdk >= 2.6.0 +- python >= 3.9 seealso: - name: Cisco DNA Center documentation for Configuration Templates ImportsTheProjectsProvided description: Complete reference of the ImportsTheProjectsProvided API. diff --git a/ansible_collections/cisco/dnac/plugins/modules/configuration_template_import_template.py b/ansible_collections/cisco/dnac/plugins/modules/configuration_template_import_template.py index fc612c50f..7f9cf31f6 100644 --- a/ansible_collections/cisco/dnac/plugins/modules/configuration_template_import_template.py +++ b/ansible_collections/cisco/dnac/plugins/modules/configuration_template_import_template.py @@ -523,8 +523,8 @@ options: project. type: str requirements: -- dnacentersdk >= 2.5.5 -- python >= 3.5 +- dnacentersdk >= 2.6.0 +- python >= 3.9 seealso: - name: Cisco DNA Center documentation for Configuration Templates ImportsTheTemplatesProvided description: Complete reference of the ImportsTheTemplatesProvided API. diff --git a/ansible_collections/cisco/dnac/plugins/modules/configuration_template_info.py b/ansible_collections/cisco/dnac/plugins/modules/configuration_template_info.py index 993d2e0b5..ad9e264cf 100644 --- a/ansible_collections/cisco/dnac/plugins/modules/configuration_template_info.py +++ b/ansible_collections/cisco/dnac/plugins/modules/configuration_template_info.py @@ -76,8 +76,8 @@ options: - LatestVersion query parameter. LatestVersion flag to get the latest versioned template. type: bool requirements: -- dnacentersdk >= 2.5.5 -- python >= 3.5 +- dnacentersdk >= 2.6.0 +- python >= 3.9 seealso: - name: Cisco DNA Center documentation for Configuration Templates GetsDetailsOfAGivenTemplate description: Complete reference of the GetsDetailsOfAGivenTemplate API. diff --git a/ansible_collections/cisco/dnac/plugins/modules/configuration_template_project.py b/ansible_collections/cisco/dnac/plugins/modules/configuration_template_project.py index 518ac61f9..7678e283c 100644 --- a/ansible_collections/cisco/dnac/plugins/modules/configuration_template_project.py +++ b/ansible_collections/cisco/dnac/plugins/modules/configuration_template_project.py @@ -546,8 +546,8 @@ options: type: str type: list requirements: -- dnacentersdk >= 2.5.5 -- python >= 3.5 +- dnacentersdk >= 2.6.0 +- python >= 3.9 seealso: - name: Cisco DNA Center documentation for Configuration Templates CreateProject description: Complete reference of the CreateProject API. diff --git a/ansible_collections/cisco/dnac/plugins/modules/configuration_template_project_info.py b/ansible_collections/cisco/dnac/plugins/modules/configuration_template_project_info.py index d5d60407f..f200203db 100644 --- a/ansible_collections/cisco/dnac/plugins/modules/configuration_template_project_info.py +++ b/ansible_collections/cisco/dnac/plugins/modules/configuration_template_project_info.py @@ -34,8 +34,8 @@ options: - ProjectId path parameter. ProjectId(UUID) of project to get project details. type: str requirements: -- dnacentersdk >= 2.5.5 -- python >= 3.5 +- dnacentersdk >= 2.6.0 +- python >= 3.9 seealso: - name: Cisco DNA Center documentation for Configuration Templates GetsAListOfProjects description: Complete reference of the GetsAListOfProjects API. diff --git a/ansible_collections/cisco/dnac/plugins/modules/configuration_template_version_create.py b/ansible_collections/cisco/dnac/plugins/modules/configuration_template_version_create.py index b3210a7c4..d0317ea84 100644 --- a/ansible_collections/cisco/dnac/plugins/modules/configuration_template_version_create.py +++ b/ansible_collections/cisco/dnac/plugins/modules/configuration_template_version_create.py @@ -23,8 +23,8 @@ options: description: UUID of template. type: str requirements: -- dnacentersdk >= 2.5.5 -- python >= 3.5 +- dnacentersdk >= 2.6.0 +- python >= 3.9 seealso: - name: Cisco DNA Center documentation for Configuration Templates VersionTemplate description: Complete reference of the VersionTemplate API. diff --git a/ansible_collections/cisco/dnac/plugins/modules/configuration_template_version_info.py b/ansible_collections/cisco/dnac/plugins/modules/configuration_template_version_info.py index 0f6956651..0dfdb8a93 100644 --- a/ansible_collections/cisco/dnac/plugins/modules/configuration_template_version_info.py +++ b/ansible_collections/cisco/dnac/plugins/modules/configuration_template_version_info.py @@ -24,8 +24,8 @@ options: - TemplateId path parameter. TemplateId(UUID) to get list of versioned templates. type: str requirements: -- dnacentersdk >= 2.5.5 -- python >= 3.5 +- dnacentersdk >= 2.6.0 +- python >= 3.9 seealso: - name: Cisco DNA Center documentation for Configuration Templates GetsAllTheVersionsOfAGivenTemplate description: Complete reference of the GetsAllTheVersionsOfAGivenTemplate API. diff --git a/ansible_collections/cisco/dnac/plugins/modules/credential_to_site_by_siteid_create_v2.py b/ansible_collections/cisco/dnac/plugins/modules/credential_to_site_by_siteid_create_v2.py index 44f2a99db..1ee9e33a9 100644 --- a/ansible_collections/cisco/dnac/plugins/modules/credential_to_site_by_siteid_create_v2.py +++ b/ansible_collections/cisco/dnac/plugins/modules/credential_to_site_by_siteid_create_v2.py @@ -38,8 +38,8 @@ options: description: SNMPv3 Credential Id. type: str requirements: -- dnacentersdk >= 2.5.5 -- python >= 3.5 +- dnacentersdk >= 2.6.0 +- python >= 3.9 seealso: - name: Cisco DNA Center documentation for Network Settings AssignDeviceCredentialToSiteV2 description: Complete reference of the AssignDeviceCredentialToSiteV2 API. diff --git a/ansible_collections/cisco/dnac/plugins/modules/device_configurations_export.py b/ansible_collections/cisco/dnac/plugins/modules/device_configurations_export.py index 8f761afc2..4d7ba14db 100644 --- a/ansible_collections/cisco/dnac/plugins/modules/device_configurations_export.py +++ b/ansible_collections/cisco/dnac/plugins/modules/device_configurations_export.py @@ -24,8 +24,8 @@ options: description: Password. type: str requirements: -- dnacentersdk >= 2.5.5 -- python >= 3.5 +- dnacentersdk >= 2.6.0 +- python >= 3.9 seealso: - name: Cisco DNA Center documentation for Configuration Archive ExportDeviceConfigurations description: Complete reference of the ExportDeviceConfigurations API. diff --git a/ansible_collections/cisco/dnac/plugins/modules/device_credential_create.py b/ansible_collections/cisco/dnac/plugins/modules/device_credential_create.py index d5732808b..b26ec83a0 100644 --- a/ansible_collections/cisco/dnac/plugins/modules/device_credential_create.py +++ b/ansible_collections/cisco/dnac/plugins/modules/device_credential_create.py @@ -120,8 +120,8 @@ options: type: list type: dict requirements: -- dnacentersdk >= 2.5.5 -- python >= 3.5 +- dnacentersdk >= 2.6.0 +- python >= 3.9 seealso: - name: Cisco DNA Center documentation for Network Settings CreateDeviceCredentials description: Complete reference of the CreateDeviceCredentials API. diff --git a/ansible_collections/cisco/dnac/plugins/modules/device_credential_delete.py b/ansible_collections/cisco/dnac/plugins/modules/device_credential_delete.py index 42cd7bf9a..73d144997 100644 --- a/ansible_collections/cisco/dnac/plugins/modules/device_credential_delete.py +++ b/ansible_collections/cisco/dnac/plugins/modules/device_credential_delete.py @@ -20,8 +20,8 @@ options: description: Id path parameter. Global credential id. type: str requirements: -- dnacentersdk >= 2.5.5 -- python >= 3.5 +- dnacentersdk >= 2.6.0 +- python >= 3.9 seealso: - name: Cisco DNA Center documentation for Network Settings DeleteDeviceCredential description: Complete reference of the DeleteDeviceCredential API. diff --git a/ansible_collections/cisco/dnac/plugins/modules/device_credential_info.py b/ansible_collections/cisco/dnac/plugins/modules/device_credential_info.py index 184d82056..27175a669 100644 --- a/ansible_collections/cisco/dnac/plugins/modules/device_credential_info.py +++ b/ansible_collections/cisco/dnac/plugins/modules/device_credential_info.py @@ -24,8 +24,8 @@ options: - SiteId query parameter. Site id to retrieve the credential details associated with the site. type: str requirements: -- dnacentersdk >= 2.5.5 -- python >= 3.5 +- dnacentersdk >= 2.6.0 +- python >= 3.9 seealso: - name: Cisco DNA Center documentation for Network Settings GetDeviceCredentialDetails description: Complete reference of the GetDeviceCredentialDetails API. diff --git a/ansible_collections/cisco/dnac/plugins/modules/device_credential_intent.py b/ansible_collections/cisco/dnac/plugins/modules/device_credential_intent.py index 8e2f41384..3b887aa8d 100644 --- a/ansible_collections/cisco/dnac/plugins/modules/device_credential_intent.py +++ b/ansible_collections/cisco/dnac/plugins/modules/device_credential_intent.py @@ -298,8 +298,8 @@ options: description: snmp_v3 Credential Id. Use Description or Id. type: str requirements: -- dnacentersdk >= 2.5.5 -- python >= 3.5 +- dnacentersdk >= 2.6.0 +- python >= 3.9 seealso: - name: Cisco DNA Center documentation for Discovery CreateGlobalCredentialsV2 description: Complete reference of the CreateGlobalCredentialsV2 API. @@ -881,6 +881,7 @@ class DnacCredential(DnacBase): response = self.dnac._exec( family="sites", function='get_site', + op_modifies=True, params={"name": site_name}, ) self.log("Received API response from 'get_site': {0}".format(response), "DEBUG") @@ -891,9 +892,9 @@ class DnacCredential(DnacBase): _id = response.get("response")[0].get("id") self.log("Site ID for the site name {0}: {1}".format(site_name, _id), "INFO") - except Exception as exec: + except Exception as e: self.log("Exception occurred while getting site_id from the site_name: {0}" - .format(exec), "CRITICAL") + .format(e), "CRITICAL") return None return _id @@ -917,9 +918,9 @@ class DnacCredential(DnacBase): global_credentials = global_credentials.get("response") self.log("All global device credentials details: {0}" .format(global_credentials), "DEBUG") - except Exception as exec: + except Exception as e: self.log("Exception occurred while getting global device credentials: {0}" - .format(exec), "CRITICAL") + .format(e), "CRITICAL") return None return global_credentials @@ -2209,6 +2210,7 @@ class DnacCredential(DnacBase): response = self.dnac._exec( family="discovery", function='create_global_credentials_v2', + op_modifies=True, params=credential_params, ) self.log("Received API response from 'create_global_credentials_v2': {0}" @@ -2273,6 +2275,7 @@ class DnacCredential(DnacBase): response = self.dnac._exec( family="discovery", function='update_global_credentials_v2', + op_modifies=True, params=credential_params, ) self.log("Received API response for 'update_global_credentials_v2': {0}" @@ -2328,6 +2331,7 @@ class DnacCredential(DnacBase): response = self.dnac._exec( family="network_settings", function='assign_device_credential_to_site_v2', + op_modifies=True, params=credential_params, ) self.log("Received API response for 'assign_device_credential_to_site_v2': {0}" @@ -2414,6 +2418,7 @@ class DnacCredential(DnacBase): response = self.dnac._exec( family="discovery", function="delete_global_credential_v2", + op_modifies=True, params={"id": _id}, ) self.log("Received API response for 'delete_global_credential_v2': {0}" diff --git a/ansible_collections/cisco/dnac/plugins/modules/device_credential_update.py b/ansible_collections/cisco/dnac/plugins/modules/device_credential_update.py index f17c18fbd..7c5cafd5b 100644 --- a/ansible_collections/cisco/dnac/plugins/modules/device_credential_update.py +++ b/ansible_collections/cisco/dnac/plugins/modules/device_credential_update.py @@ -132,8 +132,8 @@ options: type: dict type: dict requirements: -- dnacentersdk >= 2.5.5 -- python >= 3.5 +- dnacentersdk >= 2.6.0 +- python >= 3.9 seealso: - name: Cisco DNA Center documentation for Network Settings UpdateDeviceCredentials description: Complete reference of the UpdateDeviceCredentials API. diff --git a/ansible_collections/cisco/dnac/plugins/modules/device_credential_workflow_manager.py b/ansible_collections/cisco/dnac/plugins/modules/device_credential_workflow_manager.py index 3db97ce05..a6d188de4 100644 --- a/ansible_collections/cisco/dnac/plugins/modules/device_credential_workflow_manager.py +++ b/ansible_collections/cisco/dnac/plugins/modules/device_credential_workflow_manager.py @@ -298,8 +298,8 @@ options: description: snmp_v3 Credential Id. Use Description or Id. type: str requirements: -- dnacentersdk >= 2.5.5 -- python >= 3.5 +- dnacentersdk >= 2.6.0 +- python >= 3.9 seealso: - name: Cisco Catalyst Center documentation for Discovery CreateGlobalCredentialsV2 description: Complete reference of the CreateGlobalCredentialsV2 API. @@ -880,6 +880,7 @@ class DeviceCredential(DnacBase): response = self.dnac._exec( family="sites", function='get_site', + op_modifies=True, params={"name": site_name}, ) self.log("Received API response from 'get_site': {0}".format(response), "DEBUG") @@ -890,9 +891,9 @@ class DeviceCredential(DnacBase): _id = response.get("response")[0].get("id") self.log("Site ID for the site name {0}: {1}".format(site_name, _id), "INFO") - except Exception as exec: + except Exception as e: self.log("Exception occurred while getting site_id from the site_name: {0}" - .format(exec), "CRITICAL") + .format(e), "CRITICAL") return None return _id @@ -916,9 +917,9 @@ class DeviceCredential(DnacBase): global_credentials = global_credentials.get("response") self.log("All global device credentials details: {0}" .format(global_credentials), "DEBUG") - except Exception as exec: + except Exception as e: self.log("Exception occurred while getting global device credentials: {0}" - .format(exec), "CRITICAL") + .format(e), "CRITICAL") return None return global_credentials @@ -2208,6 +2209,7 @@ class DeviceCredential(DnacBase): response = self.dnac._exec( family="discovery", function='create_global_credentials_v2', + op_modifies=True, params=credential_params, ) self.log("Received API response from 'create_global_credentials_v2': {0}" @@ -2272,6 +2274,7 @@ class DeviceCredential(DnacBase): response = self.dnac._exec( family="discovery", function='update_global_credentials_v2', + op_modifies=True, params=credential_params, ) self.log("Received API response for 'update_global_credentials_v2': {0}" @@ -2327,6 +2330,7 @@ class DeviceCredential(DnacBase): response = self.dnac._exec( family="network_settings", function='assign_device_credential_to_site_v2', + op_modifies=True, params=credential_params, ) self.log("Received API response for 'assign_device_credential_to_site_v2': {0}" @@ -2413,6 +2417,7 @@ class DeviceCredential(DnacBase): response = self.dnac._exec( family="discovery", function="delete_global_credential_v2", + op_modifies=True, params={"id": _id}, ) self.log("Received API response for 'delete_global_credential_v2': {0}" diff --git a/ansible_collections/cisco/dnac/plugins/modules/device_details_info.py b/ansible_collections/cisco/dnac/plugins/modules/device_details_info.py index 108be2c42..05793acd2 100644 --- a/ansible_collections/cisco/dnac/plugins/modules/device_details_info.py +++ b/ansible_collections/cisco/dnac/plugins/modules/device_details_info.py @@ -32,8 +32,8 @@ options: - Identifier query parameter. One of keywords macAddress or uuid or nwDeviceName. type: str requirements: -- dnacentersdk >= 2.5.5 -- python >= 3.5 +- dnacentersdk >= 2.6.0 +- python >= 3.9 seealso: - name: Cisco DNA Center documentation for Devices GetDeviceDetail description: Complete reference of the GetDeviceDetail API. diff --git a/ansible_collections/cisco/dnac/plugins/modules/device_enrichment_details_info.py b/ansible_collections/cisco/dnac/plugins/modules/device_enrichment_details_info.py index c0be8c613..37a46f792 100644 --- a/ansible_collections/cisco/dnac/plugins/modules/device_enrichment_details_info.py +++ b/ansible_collections/cisco/dnac/plugins/modules/device_enrichment_details_info.py @@ -22,8 +22,8 @@ options: description: Additional headers. type: dict requirements: -- dnacentersdk >= 2.5.5 -- python >= 3.5 +- dnacentersdk >= 2.6.0 +- python >= 3.9 seealso: - name: Cisco DNA Center documentation for Devices GetDeviceEnrichmentDetails description: Complete reference of the GetDeviceEnrichmentDetails API. diff --git a/ansible_collections/cisco/dnac/plugins/modules/device_family_identifiers_details_info.py b/ansible_collections/cisco/dnac/plugins/modules/device_family_identifiers_details_info.py index 515a0d94a..97736aa74 100644 --- a/ansible_collections/cisco/dnac/plugins/modules/device_family_identifiers_details_info.py +++ b/ansible_collections/cisco/dnac/plugins/modules/device_family_identifiers_details_info.py @@ -20,8 +20,8 @@ options: description: Additional headers. type: dict requirements: -- dnacentersdk >= 2.5.5 -- python >= 3.5 +- dnacentersdk >= 2.6.0 +- python >= 3.9 seealso: - name: Cisco DNA Center documentation for Software Image Management (SWIM) GetDeviceFamilyIdentifiers description: Complete reference of the GetDeviceFamilyIdentifiers API. diff --git a/ansible_collections/cisco/dnac/plugins/modules/device_health_info.py b/ansible_collections/cisco/dnac/plugins/modules/device_health_info.py index 9b329a7ab..7b0775f33 100644 --- a/ansible_collections/cisco/dnac/plugins/modules/device_health_info.py +++ b/ansible_collections/cisco/dnac/plugins/modules/device_health_info.py @@ -50,8 +50,8 @@ options: - Offset query parameter. The offset of the first device in the returned data. type: int requirements: -- dnacentersdk >= 2.5.5 -- python >= 3.5 +- dnacentersdk >= 2.6.0 +- python >= 3.9 seealso: - name: Cisco DNA Center documentation for Devices Devices description: Complete reference of the Devices API. diff --git a/ansible_collections/cisco/dnac/plugins/modules/device_interface_by_ip_info.py b/ansible_collections/cisco/dnac/plugins/modules/device_interface_by_ip_info.py index 7d5d984f5..df7223b15 100644 --- a/ansible_collections/cisco/dnac/plugins/modules/device_interface_by_ip_info.py +++ b/ansible_collections/cisco/dnac/plugins/modules/device_interface_by_ip_info.py @@ -24,8 +24,8 @@ options: - IpAddress path parameter. IP address of the interface. type: str requirements: -- dnacentersdk >= 2.5.5 -- python >= 3.5 +- dnacentersdk >= 2.6.0 +- python >= 3.9 seealso: - name: Cisco DNA Center documentation for Devices GetInterfaceByIP description: Complete reference of the GetInterfaceByIP API. diff --git a/ansible_collections/cisco/dnac/plugins/modules/device_interface_count_info.py b/ansible_collections/cisco/dnac/plugins/modules/device_interface_count_info.py index 24e0290a6..01d3361fb 100644 --- a/ansible_collections/cisco/dnac/plugins/modules/device_interface_count_info.py +++ b/ansible_collections/cisco/dnac/plugins/modules/device_interface_count_info.py @@ -20,8 +20,8 @@ options: description: Additional headers. type: dict requirements: -- dnacentersdk >= 2.5.5 -- python >= 3.5 +- dnacentersdk >= 2.6.0 +- python >= 3.9 seealso: - name: Cisco DNA Center documentation for Devices GetDeviceInterfaceCount description: Complete reference of the GetDeviceInterfaceCount API. diff --git a/ansible_collections/cisco/dnac/plugins/modules/device_interface_info.py b/ansible_collections/cisco/dnac/plugins/modules/device_interface_info.py index 5f484a520..31b2bc4c6 100644 --- a/ansible_collections/cisco/dnac/plugins/modules/device_interface_info.py +++ b/ansible_collections/cisco/dnac/plugins/modules/device_interface_info.py @@ -42,8 +42,8 @@ options: - Id path parameter. Interface ID. type: str requirements: -- dnacentersdk >= 2.5.5 -- python >= 3.5 +- dnacentersdk >= 2.6.0 +- python >= 3.9 seealso: - name: Cisco DNA Center documentation for Devices GetAllInterfaces description: Complete reference of the GetAllInterfaces API. diff --git a/ansible_collections/cisco/dnac/plugins/modules/device_interface_isis_info.py b/ansible_collections/cisco/dnac/plugins/modules/device_interface_isis_info.py index 242344a18..798c47821 100644 --- a/ansible_collections/cisco/dnac/plugins/modules/device_interface_isis_info.py +++ b/ansible_collections/cisco/dnac/plugins/modules/device_interface_isis_info.py @@ -20,8 +20,8 @@ options: description: Additional headers. type: dict requirements: -- dnacentersdk >= 2.5.5 -- python >= 3.5 +- dnacentersdk >= 2.6.0 +- python >= 3.9 seealso: - name: Cisco DNA Center documentation for Devices GetISISInterfaces description: Complete reference of the GetISISInterfaces API. diff --git a/ansible_collections/cisco/dnac/plugins/modules/device_interface_ospf_info.py b/ansible_collections/cisco/dnac/plugins/modules/device_interface_ospf_info.py index 759f4584a..ed87a4b0c 100644 --- a/ansible_collections/cisco/dnac/plugins/modules/device_interface_ospf_info.py +++ b/ansible_collections/cisco/dnac/plugins/modules/device_interface_ospf_info.py @@ -20,8 +20,8 @@ options: description: Additional headers. type: dict requirements: -- dnacentersdk >= 2.5.5 -- python >= 3.5 +- dnacentersdk >= 2.6.0 +- python >= 3.9 seealso: - name: Cisco DNA Center documentation for Devices GetOSPFInterfaces description: Complete reference of the GetOSPFInterfaces API. diff --git a/ansible_collections/cisco/dnac/plugins/modules/device_reboot_apreboot.py b/ansible_collections/cisco/dnac/plugins/modules/device_reboot_apreboot.py index 78a33dfd4..92e7c41ee 100644 --- a/ansible_collections/cisco/dnac/plugins/modules/device_reboot_apreboot.py +++ b/ansible_collections/cisco/dnac/plugins/modules/device_reboot_apreboot.py @@ -21,8 +21,8 @@ options: elements: str type: list requirements: -- dnacentersdk >= 2.5.5 -- python >= 3.5 +- dnacentersdk >= 2.6.0 +- python >= 3.9 seealso: - name: Cisco DNA Center documentation for Wireless RebootAccessPoints description: Complete reference of the RebootAccessPoints API. diff --git a/ansible_collections/cisco/dnac/plugins/modules/device_reboot_apreboot_info.py b/ansible_collections/cisco/dnac/plugins/modules/device_reboot_apreboot_info.py index 09203ba5e..c4e500062 100644 --- a/ansible_collections/cisco/dnac/plugins/modules/device_reboot_apreboot_info.py +++ b/ansible_collections/cisco/dnac/plugins/modules/device_reboot_apreboot_info.py @@ -24,8 +24,8 @@ options: - ParentTaskId query parameter. Task id of ap reboot request. type: str requirements: -- dnacentersdk >= 2.5.5 -- python >= 3.5 +- dnacentersdk >= 2.6.0 +- python >= 3.9 seealso: - name: Cisco DNA Center documentation for Wireless GetAccessPointRebootTaskResult description: Complete reference of the GetAccessPointRebootTaskResult API. diff --git a/ansible_collections/cisco/dnac/plugins/modules/device_replacement.py b/ansible_collections/cisco/dnac/plugins/modules/device_replacement.py index e6ec8cbdc..a5353ddd0 100644 --- a/ansible_collections/cisco/dnac/plugins/modules/device_replacement.py +++ b/ansible_collections/cisco/dnac/plugins/modules/device_replacement.py @@ -65,8 +65,8 @@ options: type: str type: list requirements: -- dnacentersdk >= 2.5.5 -- python >= 3.5 +- dnacentersdk >= 2.6.0 +- python >= 3.9 seealso: - name: Cisco DNA Center documentation for Device Replacement MarkDeviceForReplacement description: Complete reference of the MarkDeviceForReplacement API. diff --git a/ansible_collections/cisco/dnac/plugins/modules/device_replacement_count_info.py b/ansible_collections/cisco/dnac/plugins/modules/device_replacement_count_info.py index c15cf18df..8aae86979 100644 --- a/ansible_collections/cisco/dnac/plugins/modules/device_replacement_count_info.py +++ b/ansible_collections/cisco/dnac/plugins/modules/device_replacement_count_info.py @@ -27,8 +27,8 @@ options: elements: str type: list requirements: -- dnacentersdk >= 2.5.5 -- python >= 3.5 +- dnacentersdk >= 2.6.0 +- python >= 3.9 seealso: - name: Cisco DNA Center documentation for Device Replacement ReturnReplacementDevicesCount description: Complete reference of the ReturnReplacementDevicesCount API. diff --git a/ansible_collections/cisco/dnac/plugins/modules/device_replacement_deploy.py b/ansible_collections/cisco/dnac/plugins/modules/device_replacement_deploy.py index 14f591d2d..81dfc9251 100644 --- a/ansible_collections/cisco/dnac/plugins/modules/device_replacement_deploy.py +++ b/ansible_collections/cisco/dnac/plugins/modules/device_replacement_deploy.py @@ -25,8 +25,8 @@ options: description: Device Replacement Deploy's replacementDeviceSerialNumber. type: str requirements: -- dnacentersdk >= 2.5.5 -- python >= 3.5 +- dnacentersdk >= 2.6.0 +- python >= 3.9 seealso: - name: Cisco DNA Center documentation for Device Replacement DeployDeviceReplacementWorkflow description: Complete reference of the DeployDeviceReplacementWorkflow API. diff --git a/ansible_collections/cisco/dnac/plugins/modules/device_replacement_info.py b/ansible_collections/cisco/dnac/plugins/modules/device_replacement_info.py index 91977952a..4dd9756d5 100644 --- a/ansible_collections/cisco/dnac/plugins/modules/device_replacement_info.py +++ b/ansible_collections/cisco/dnac/plugins/modules/device_replacement_info.py @@ -71,8 +71,8 @@ options: - Limit query parameter. type: int requirements: -- dnacentersdk >= 2.5.5 -- python >= 3.5 +- dnacentersdk >= 2.6.0 +- python >= 3.9 seealso: - name: Cisco DNA Center documentation for Device Replacement ReturnListOfReplacementDevicesWithReplacementDetails description: Complete reference of the ReturnListOfReplacementDevicesWithReplacementDetails API. diff --git a/ansible_collections/cisco/dnac/plugins/modules/disassociate_site_to_network_profile.py b/ansible_collections/cisco/dnac/plugins/modules/disassociate_site_to_network_profile.py index de80f579b..2972ac7f2 100644 --- a/ansible_collections/cisco/dnac/plugins/modules/disassociate_site_to_network_profile.py +++ b/ansible_collections/cisco/dnac/plugins/modules/disassociate_site_to_network_profile.py @@ -23,8 +23,8 @@ options: description: SiteId path parameter. Site Id to be associated. type: str requirements: -- dnacentersdk >= 2.5.5 -- python >= 3.5 +- dnacentersdk >= 2.6.0 +- python >= 3.9 seealso: - name: Cisco DNA Center documentation for Site Design Disassociate description: Complete reference of the Disassociate API. diff --git a/ansible_collections/cisco/dnac/plugins/modules/disasterrecovery_system_operationstatus_info.py b/ansible_collections/cisco/dnac/plugins/modules/disasterrecovery_system_operationstatus_info.py index 8e05a778e..1c6621afe 100644 --- a/ansible_collections/cisco/dnac/plugins/modules/disasterrecovery_system_operationstatus_info.py +++ b/ansible_collections/cisco/dnac/plugins/modules/disasterrecovery_system_operationstatus_info.py @@ -20,8 +20,8 @@ options: description: Additional headers. type: dict requirements: -- dnacentersdk >= 2.5.5 -- python >= 3.5 +- dnacentersdk >= 2.6.0 +- python >= 3.9 notes: - SDK Method used are disaster_recovery.DisasterRecovery.disaster_recovery_operational_status, diff --git a/ansible_collections/cisco/dnac/plugins/modules/disasterrecovery_system_status_info.py b/ansible_collections/cisco/dnac/plugins/modules/disasterrecovery_system_status_info.py index 40356c0f7..f1c3c318c 100644 --- a/ansible_collections/cisco/dnac/plugins/modules/disasterrecovery_system_status_info.py +++ b/ansible_collections/cisco/dnac/plugins/modules/disasterrecovery_system_status_info.py @@ -20,8 +20,8 @@ options: description: Additional headers. type: dict requirements: -- dnacentersdk >= 2.5.5 -- python >= 3.5 +- dnacentersdk >= 2.6.0 +- python >= 3.9 notes: - SDK Method used are disaster_recovery.DisasterRecovery.disaster_recovery_status, diff --git a/ansible_collections/cisco/dnac/plugins/modules/discovery.py b/ansible_collections/cisco/dnac/plugins/modules/discovery.py index 10e7e37a9..94fca37e0 100644 --- a/ansible_collections/cisco/dnac/plugins/modules/discovery.py +++ b/ansible_collections/cisco/dnac/plugins/modules/discovery.py @@ -214,8 +214,8 @@ options: description: Discovery's userNameList. type: str requirements: -- dnacentersdk >= 2.5.5 -- python >= 3.5 +- dnacentersdk >= 2.6.0 +- python >= 3.9 seealso: - name: Cisco DNA Center documentation for Discovery StartDiscovery description: Complete reference of the StartDiscovery API. diff --git a/ansible_collections/cisco/dnac/plugins/modules/discovery_count_info.py b/ansible_collections/cisco/dnac/plugins/modules/discovery_count_info.py index 6622742f7..59f92499a 100644 --- a/ansible_collections/cisco/dnac/plugins/modules/discovery_count_info.py +++ b/ansible_collections/cisco/dnac/plugins/modules/discovery_count_info.py @@ -20,8 +20,8 @@ options: description: Additional headers. type: dict requirements: -- dnacentersdk >= 2.5.5 -- python >= 3.5 +- dnacentersdk >= 2.6.0 +- python >= 3.9 seealso: - name: Cisco DNA Center documentation for Discovery GetCountOfAllDiscoveryJobs description: Complete reference of the GetCountOfAllDiscoveryJobs API. diff --git a/ansible_collections/cisco/dnac/plugins/modules/discovery_device_count_info.py b/ansible_collections/cisco/dnac/plugins/modules/discovery_device_count_info.py index b258a513d..51da8df80 100644 --- a/ansible_collections/cisco/dnac/plugins/modules/discovery_device_count_info.py +++ b/ansible_collections/cisco/dnac/plugins/modules/discovery_device_count_info.py @@ -30,8 +30,8 @@ options: - TaskId query parameter. type: str requirements: -- dnacentersdk >= 2.5.5 -- python >= 3.5 +- dnacentersdk >= 2.6.0 +- python >= 3.9 seealso: - name: Cisco DNA Center documentation for Discovery GetDevicesDiscoveredById description: Complete reference of the GetDevicesDiscoveredById API. diff --git a/ansible_collections/cisco/dnac/plugins/modules/discovery_device_info.py b/ansible_collections/cisco/dnac/plugins/modules/discovery_device_info.py index 345000ca0..2bc42ae22 100644 --- a/ansible_collections/cisco/dnac/plugins/modules/discovery_device_info.py +++ b/ansible_collections/cisco/dnac/plugins/modules/discovery_device_info.py @@ -30,8 +30,8 @@ options: - TaskId query parameter. type: str requirements: -- dnacentersdk >= 2.5.5 -- python >= 3.5 +- dnacentersdk >= 2.6.0 +- python >= 3.9 seealso: - name: Cisco DNA Center documentation for Discovery GetDiscoveredNetworkDevicesByDiscoveryId description: Complete reference of the GetDiscoveredNetworkDevicesByDiscoveryId API. diff --git a/ansible_collections/cisco/dnac/plugins/modules/discovery_device_range_info.py b/ansible_collections/cisco/dnac/plugins/modules/discovery_device_range_info.py index 47dcb0871..ade1f2828 100644 --- a/ansible_collections/cisco/dnac/plugins/modules/discovery_device_range_info.py +++ b/ansible_collections/cisco/dnac/plugins/modules/discovery_device_range_info.py @@ -38,8 +38,8 @@ options: - TaskId query parameter. type: str requirements: -- dnacentersdk >= 2.5.5 -- python >= 3.5 +- dnacentersdk >= 2.6.0 +- python >= 3.9 seealso: - name: Cisco DNA Center documentation for Discovery GetDiscoveredDevicesByRange description: Complete reference of the GetDiscoveredDevicesByRange API. diff --git a/ansible_collections/cisco/dnac/plugins/modules/discovery_info.py b/ansible_collections/cisco/dnac/plugins/modules/discovery_info.py index 689226938..68d1cc74f 100644 --- a/ansible_collections/cisco/dnac/plugins/modules/discovery_info.py +++ b/ansible_collections/cisco/dnac/plugins/modules/discovery_info.py @@ -24,8 +24,8 @@ options: - Id path parameter. Discovery ID. type: str requirements: -- dnacentersdk >= 2.5.5 -- python >= 3.5 +- dnacentersdk >= 2.6.0 +- python >= 3.9 seealso: - name: Cisco DNA Center documentation for Discovery GetDiscoveryById description: Complete reference of the GetDiscoveryById API. diff --git a/ansible_collections/cisco/dnac/plugins/modules/discovery_intent.py b/ansible_collections/cisco/dnac/plugins/modules/discovery_intent.py index 96759bb9c..a71ef6be8 100644 --- a/ansible_collections/cisco/dnac/plugins/modules/discovery_intent.py +++ b/ansible_collections/cisco/dnac/plugins/modules/discovery_intent.py @@ -59,7 +59,8 @@ options: pass a list with single element like - 10.197.156.22. For CIDR based discovery, we should pass a list with single element like - 10.197.156.22/22. For RANGE based discovery, we should pass a list with single element and range like - 10.197.156.1-10.197.156.100. For MULTI RANGE based discovery, we should pass a list with multiple - elementd like - 10.197.156.1-10.197.156.100 and in next line - 10.197.157.1-10.197.157.100. + elementd like - 10.197.156.1-10.197.156.100 and in next line - 10.197.157.1-10.197.157.100. Maximum of 8 IP address ranges + are allowed. type: list elements: str required: true @@ -328,7 +329,7 @@ options: default: False requirements: - dnacentersdk == 2.6.10 -- python >= 3.5 +- python >= 3.9 notes: - SDK Method used are discovery.Discovery.get_all_global_credentials_v2, @@ -721,6 +722,43 @@ class Discovery(DnacBase): self.status = "success" return self + def validate_ip4_address_list(self): + """ + Validates each ip adress paased in the IP_address_list passed by the user before preprocessing it + """ + + ip_address_list = self.validated_config[0].get('ip_address_list') + for ip in ip_address_list: + if '/' in ip: + ip = ip.split("/")[0] + if '-' in ip: + if len(ip.split('-')) == 2: + ip1, ip2 = ip.split('-') + if self.is_valid_ipv4(ip1) is False: + msg = "IP address {0} is not valid".format(ip1) + self.log(msg, "CRITICAL") + self.module.fail_json(msg=msg) + if self.is_valid_ipv4(ip2) is False: + msg = "IP address {0} is not valid".format(ip2) + self.log(msg, "CRITICAL") + self.module.fail_json(msg=msg) + ip1_parts = list(map(int, ip1.split('.'))) + ip2_parts = list(map(int, ip2.split('.'))) + for part in range(4): + if ip1_parts[part] > ip2_parts[part]: + msg = "Incorrect range passed: {0}. Please pass correct IP address range".format(ip) + self.log(msg, "CRITICAL") + self.module.fail_json(msg=msg) + else: + msg = "Provided range '{0}' is incorrect. IP address range should have only upper and lower limit values".format(ip) + self.log(msg, "CRITICAL") + self.module.fail_json(msg=msg) + if self.is_valid_ipv4(ip) is False and '-' not in ip: + msg = "IP address {0} is not valid".format(ip) + self.log(msg, "CRITICAL") + self.module.fail_json(msg=msg) + self.log("All the IP addresses passed are correct", "INFO") + def get_creds_ids_list(self): """ Retrieve the list of credentials IDs associated with class instance. @@ -934,6 +972,7 @@ class Discovery(DnacBase): family="discovery", function='get_all_global_credentials_v2', params=self.validated_config[0].get('headers'), + op_modifies=True ) response = response.get('response') self.log("The Global credentials response from 'get all global credentials v2' API is {0}".format(str(response)), "DEBUG") @@ -1022,6 +1061,10 @@ class Discovery(DnacBase): else: self.preprocess_device_discovery_handle_error() else: + if len(ip_address_list) > 8: + msg = "Maximum of 8 IP ranges are allowed." + self.log(msg, "CRITICAL") + self.module.fail_json(msg=msg) new_ip_collected = [] for ip in ip_address_list: if len(str(ip).split("-")) != 2: @@ -1267,11 +1310,11 @@ class Discovery(DnacBase): self.log("Task Id of the API task created is {0}".format(result.response.get('taskId')), "INFO") return result.response.get('taskId') - def get_task_status(self, task_id=None): + def get_merged_task_status(self, task_id=None): """ - Monitor the status of a task in the Cisco Catalyst Center. It checks the task - status periodically until the task is no longer 'In Progress'. - If the task encounters an error or fails, it immediately fails the + Monitor the status of a task of creation of dicovery in the Cisco Catalyst Center. + It checks the task status periodically until the task is no longer 'In Progress' + or other states. If the task encounters an error or fails, it immediately fails the module and returns False. Parameters: @@ -1288,9 +1331,10 @@ class Discovery(DnacBase): family="task", function='get_task_by_id', params=params, + op_modifies=True, ) response = response.response - self.log("Task status for the task id {0} is {1}".format(str(task_id), str(response)), "INFO") + self.log("Task status for the task id {0} is {1}, is_error: {2}".format(str(task_id), str(response), str(response.get('isError'))), "INFO") if response.get('isError') or re.search( 'failed', response.get('progress'), flags=re.IGNORECASE ): @@ -1299,17 +1343,62 @@ class Discovery(DnacBase): self.log(msg, "CRITICAL") self.module.fail_json(msg=msg) return False + self.log("Task status for the task id (before checking status) {0} is {1}".format(str(task_id), str(response)), "INFO") progress = response.get('progress') - if progress in ('In Progress', 'Inventory service initiating discovery'): + try: + progress_value = int(progress) + result = True + self.log("The discovery process is completed", "INFO") + self.result.update(dict(discovery_task=response)) + return result + except Exception: + self.log("The progress status is {0}, continue to check the status after 3 seconds. Putting into sleep for 3 seconds".format(progress)) time.sleep(3) - continue - else: + + def get_deleted_task_status(self, task_id=None): + """ + Monitor the status of a task of deletion of dicovery in the Cisco Catalyst Center. + It checks the itask status periodically until the task is 'Discovery deleted successfully'. + If the task encounters an error or fails, it immediately fails the module and returns False. + + Parameters: + - task_id: The ID of the task to monitor. + + Returns: + - result: True if the task completed successfully, False otherwise. + """ + + result = False + params = dict(task_id=task_id) + while True: + response = self.dnac_apply['exec']( + family="task", + function='get_task_by_id', + params=params, + op_modifies=True, + ) + response = response.response + self.log("Task status for the task id {0} is {1}, is_error: {2}".format(str(task_id), str(response), str(response.get('isError'))), "INFO") + if response.get('isError') or re.search( + 'failed', response.get('progress'), flags=re.IGNORECASE + ): + msg = 'Discovery task with id {0} has not completed - Reason: {1}'.format( + task_id, response.get("failureReason")) + self.log(msg, "CRITICAL") + self.module.fail_json(msg=msg) + return False + + self.log("Task status for the task id (before checking status) {0} is {1}".format(str(task_id), str(response)), "INFO") + progress = response.get('progress') + if re.search('Discovery deleted successfully.', response.get('progress')): result = True - self.log("The Process is completed", "INFO") - break - self.result.update(dict(discovery_task=response)) - return result + self.log("The discovery process is completed", "INFO") + self.result.update(dict(discovery_task=response)) + return result + + self.log("The progress status is {0}, continue to check the status after 3 seconds. Putting into sleep for 3 seconds".format(progress)) + time.sleep(3) def lookup_discovery_by_range_via_name(self): """ @@ -1336,7 +1425,8 @@ class Discovery(DnacBase): response_part = self.dnac_apply['exec']( family="discovery", function='get_discoveries_by_range', - params=params + params=params, + op_modifies=True, ) response["response"].extend(response_part["response"]) else: @@ -1349,7 +1439,8 @@ class Discovery(DnacBase): response = self.dnac_apply['exec']( family="discovery", function='get_discoveries_by_range', - params=params + params=params, + op_modifies=True, ) self.log("Response of the get discoveries via range API is {0}".format(str(response)), "DEBUG") @@ -1373,6 +1464,7 @@ class Discovery(DnacBase): """ result = False + aborted = False discovery = self.lookup_discovery_by_range_via_name() if not discovery: @@ -1383,17 +1475,25 @@ class Discovery(DnacBase): while True: discovery = self.lookup_discovery_by_range_via_name() - if discovery.get('discoveryCondition') == 'Complete': + discovery_condition = discovery.get('discoveryCondition') + if discovery_condition == 'Complete': result = True break - + elif discovery_condition == 'Aborted': + aborted = True + break time.sleep(3) if not result: - msg = 'Cannot find any discovery task with name {0} -- Discovery result: {1}'.format( - str(self.validated_config[0].get("discovery_name")), str(discovery)) - self.log(msg, "CRITICAL") - self.module.fail_json(msg=msg) + if aborted is True: + msg = 'Discovery with name {0} is aborted by the user on the GUI'.format(str(self.validated_config[0].get("discovery_name"))) + self.log(msg, "CRITICAL") + self.module.fail_json(msg=msg) + else: + msg = 'Cannot find any discovery task with name {0} -- Discovery result: {1}'.format( + str(self.validated_config[0].get("discovery_name")), str(discovery)) + self.log(msg, "CRITICAL") + self.module.fail_json(msg=msg) self.result.update(dict(discovery_range=discovery)) return discovery @@ -1425,6 +1525,7 @@ class Discovery(DnacBase): family="discovery", function='get_discovered_network_devices_by_discovery_id', params=params, + op_modifies=True, ) devices = response.response @@ -1495,6 +1596,7 @@ class Discovery(DnacBase): family="discovery", function="delete_discovery_by_id", params=params, + op_modifies=True, ) self.log("Response collected from API 'delete_discovery_by_id': {0}".format(str(response)), "DEBUG") @@ -1513,17 +1615,18 @@ class Discovery(DnacBase): - self: The instance of the class with updated attributes. """ + self.validate_ip4_address_list() devices_list_info = self.get_devices_list_info() ip_address_list = self.preprocess_device_discovery(devices_list_info) exist_discovery = self.get_exist_discovery() if exist_discovery: params = dict(id=exist_discovery.get('id')) discovery_task_id = self.delete_exist_discovery(params=params) - complete_discovery = self.get_task_status(task_id=discovery_task_id) + complete_discovery = self.get_deleted_task_status(task_id=discovery_task_id) discovery_task_id = self.create_discovery( ip_address_list=ip_address_list) - complete_discovery = self.get_task_status(task_id=discovery_task_id) + complete_discovery = self.get_merged_task_status(task_id=discovery_task_id) discovery_task_info = self.get_discoveries_by_range_until_success() result = self.get_discovery_device_info(discovery_id=discovery_task_info.get('id')) self.result["changed"] = True @@ -1576,7 +1679,7 @@ class Discovery(DnacBase): params = dict(id=exist_discovery.get('id')) discovery_task_id = self.delete_exist_discovery(params=params) - complete_discovery = self.get_task_status(task_id=discovery_task_id) + complete_discovery = self.get_deleted_task_status(task_id=discovery_task_id) self.result["changed"] = True self.result['msg'] = "Successfully deleted discovery" self.result['diff'] = self.validated_config @@ -1611,7 +1714,8 @@ class Discovery(DnacBase): response = self.dnac_apply['exec']( family="discovery", function='get_discovery_by_id', - params=params + params=params, + op_modifies=True, ) discovery_name = config.get('discovery_name') if response: diff --git a/ansible_collections/cisco/dnac/plugins/modules/discovery_job_info.py b/ansible_collections/cisco/dnac/plugins/modules/discovery_job_info.py index 202f57c80..2e6de4f14 100644 --- a/ansible_collections/cisco/dnac/plugins/modules/discovery_job_info.py +++ b/ansible_collections/cisco/dnac/plugins/modules/discovery_job_info.py @@ -44,8 +44,8 @@ options: - Id path parameter. Discovery ID. type: str requirements: -- dnacentersdk >= 2.5.5 -- python >= 3.5 +- dnacentersdk >= 2.6.0 +- python >= 3.9 seealso: - name: Cisco DNA Center documentation for Discovery GetDiscoveryJobsByIP description: Complete reference of the GetDiscoveryJobsByIP API. diff --git a/ansible_collections/cisco/dnac/plugins/modules/discovery_range_delete.py b/ansible_collections/cisco/dnac/plugins/modules/discovery_range_delete.py index 07c380a17..876881242 100644 --- a/ansible_collections/cisco/dnac/plugins/modules/discovery_range_delete.py +++ b/ansible_collections/cisco/dnac/plugins/modules/discovery_range_delete.py @@ -23,8 +23,8 @@ options: description: StartIndex path parameter. Start index. type: int requirements: -- dnacentersdk >= 2.5.5 -- python >= 3.5 +- dnacentersdk >= 2.6.0 +- python >= 3.9 seealso: - name: Cisco DNA Center documentation for Discovery DeleteDiscoveryBySpecifiedRange description: Complete reference of the DeleteDiscoveryBySpecifiedRange API. diff --git a/ansible_collections/cisco/dnac/plugins/modules/discovery_range_info.py b/ansible_collections/cisco/dnac/plugins/modules/discovery_range_info.py index c08902f8b..c4fc60ba7 100644 --- a/ansible_collections/cisco/dnac/plugins/modules/discovery_range_info.py +++ b/ansible_collections/cisco/dnac/plugins/modules/discovery_range_info.py @@ -28,8 +28,8 @@ options: - RecordsToReturn path parameter. Number of records to return. type: int requirements: -- dnacentersdk >= 2.5.5 -- python >= 3.5 +- dnacentersdk >= 2.6.0 +- python >= 3.9 seealso: - name: Cisco DNA Center documentation for Discovery GetDiscoveriesByRange description: Complete reference of the GetDiscoveriesByRange API. diff --git a/ansible_collections/cisco/dnac/plugins/modules/discovery_summary_info.py b/ansible_collections/cisco/dnac/plugins/modules/discovery_summary_info.py index bd8e6dcf6..9cff8b3ee 100644 --- a/ansible_collections/cisco/dnac/plugins/modules/discovery_summary_info.py +++ b/ansible_collections/cisco/dnac/plugins/modules/discovery_summary_info.py @@ -68,8 +68,8 @@ options: elements: str type: list requirements: -- dnacentersdk >= 2.5.5 -- python >= 3.5 +- dnacentersdk >= 2.6.0 +- python >= 3.9 seealso: - name: Cisco DNA Center documentation for Discovery GetNetworkDevicesFromDiscovery description: Complete reference of the GetNetworkDevicesFromDiscovery API. diff --git a/ansible_collections/cisco/dnac/plugins/modules/discovery_workflow_manager.py b/ansible_collections/cisco/dnac/plugins/modules/discovery_workflow_manager.py index 88ce124a3..758d3cc75 100644 --- a/ansible_collections/cisco/dnac/plugins/modules/discovery_workflow_manager.py +++ b/ansible_collections/cisco/dnac/plugins/modules/discovery_workflow_manager.py @@ -59,7 +59,8 @@ options: pass a list with single element like - 10.197.156.22. For CIDR based discovery, we should pass a list with single element like - 10.197.156.22/22. For RANGE based discovery, we should pass a list with single element and range like - 10.197.156.1-10.197.156.100. For MULTI RANGE based discovery, we should pass a list with multiple - elementd like - 10.197.156.1-10.197.156.100 and in next line - 10.197.157.1-10.197.157.100. + elementd like - 10.197.156.1-10.197.156.100 and in next line - 10.197.157.1-10.197.157.100. Maximum of 8 IP address ranges + are allowed. type: list elements: str required: true @@ -328,7 +329,7 @@ options: default: False requirements: - dnacentersdk == 2.6.10 -- python >= 3.5 +- python >= 3.9 notes: - SDK Method used are discovery.Discovery.get_all_global_credentials_v2, @@ -721,6 +722,43 @@ class Discovery(DnacBase): self.status = "success" return self + def validate_ip4_address_list(self): + """ + Validates each ip adress paased in the IP_address_list passed by the user before preprocessing it + """ + + ip_address_list = self.validated_config[0].get('ip_address_list') + for ip in ip_address_list: + if '/' in ip: + ip = ip.split("/")[0] + if '-' in ip: + if len(ip.split('-')) == 2: + ip1, ip2 = ip.split('-') + if self.is_valid_ipv4(ip1) is False: + msg = "IP address {0} is not valid".format(ip1) + self.log(msg, "CRITICAL") + self.module.fail_json(msg=msg) + if self.is_valid_ipv4(ip2) is False: + msg = "IP address {0} is not valid".format(ip2) + self.log(msg, "CRITICAL") + self.module.fail_json(msg=msg) + ip1_parts = list(map(int, ip1.split('.'))) + ip2_parts = list(map(int, ip2.split('.'))) + for part in range(4): + if ip1_parts[part] > ip2_parts[part]: + msg = "Incorrect range passed: {0}. Please pass correct IP address range".format(ip) + self.log(msg, "CRITICAL") + self.module.fail_json(msg=msg) + else: + msg = "Provided range '{0}' is incorrect. IP address range should have only upper and lower limit values".format(ip) + self.log(msg, "CRITICAL") + self.module.fail_json(msg=msg) + if self.is_valid_ipv4(ip) is False and '-' not in ip: + msg = "IP address {0} is not valid".format(ip) + self.log(msg, "CRITICAL") + self.module.fail_json(msg=msg) + self.log("All the IP addresses passed are correct", "INFO") + def get_creds_ids_list(self): """ Retrieve the list of credentials IDs associated with class instance. @@ -934,6 +972,7 @@ class Discovery(DnacBase): family="discovery", function='get_all_global_credentials_v2', params=self.validated_config[0].get('headers'), + op_modifies=True ) response = response.get('response') self.log("The Global credentials response from 'get all global credentials v2' API is {0}".format(str(response)), "DEBUG") @@ -1022,6 +1061,10 @@ class Discovery(DnacBase): else: self.preprocess_device_discovery_handle_error() else: + if len(ip_address_list) > 8: + msg = "Maximum of 8 IP ranges are allowed." + self.log(msg, "CRITICAL") + self.module.fail_json(msg=msg) new_ip_collected = [] for ip in ip_address_list: if len(str(ip).split("-")) != 2: @@ -1267,11 +1310,11 @@ class Discovery(DnacBase): self.log("Task Id of the API task created is {0}".format(result.response.get('taskId')), "INFO") return result.response.get('taskId') - def get_task_status(self, task_id=None): + def get_merged_task_status(self, task_id=None): """ - Monitor the status of a task in the Cisco Catalyst Center. It checks the task - status periodically until the task is no longer 'In Progress'. - If the task encounters an error or fails, it immediately fails the + Monitor the status of a task of creation of dicovery in the Cisco Catalyst Center. + It checks the task status periodically until the task is no longer 'In Progress' + or other states. If the task encounters an error or fails, it immediately fails the module and returns False. Parameters: @@ -1288,9 +1331,10 @@ class Discovery(DnacBase): family="task", function='get_task_by_id', params=params, + op_modifies=True, ) response = response.response - self.log("Task status for the task id {0} is {1}".format(str(task_id), str(response)), "INFO") + self.log("Task status for the task id {0} is {1}, is_error: {2}".format(str(task_id), str(response), str(response.get('isError'))), "INFO") if response.get('isError') or re.search( 'failed', response.get('progress'), flags=re.IGNORECASE ): @@ -1299,17 +1343,62 @@ class Discovery(DnacBase): self.log(msg, "CRITICAL") self.module.fail_json(msg=msg) return False + self.log("Task status for the task id (before checking status) {0} is {1}".format(str(task_id), str(response)), "INFO") progress = response.get('progress') - if progress in ('In Progress', 'Inventory service initiating discovery'): + try: + progress_value = int(progress) + result = True + self.log("The discovery process is completed", "INFO") + self.result.update(dict(discovery_task=response)) + return result + except Exception: + self.log("The progress status is {0}, continue to check the status after 3 seconds. Putting into sleep for 3 seconds".format(progress)) time.sleep(3) - continue - else: + + def get_deleted_task_status(self, task_id=None): + """ + Monitor the status of a task of deletion of dicovery in the Cisco Catalyst Center. + It checks the itask status periodically until the task is 'Discovery deleted successfully'. + If the task encounters an error or fails, it immediately fails the module and returns False. + + Parameters: + - task_id: The ID of the task to monitor. + + Returns: + - result: True if the task completed successfully, False otherwise. + """ + + result = False + params = dict(task_id=task_id) + while True: + response = self.dnac_apply['exec']( + family="task", + function='get_task_by_id', + params=params, + op_modifies=True, + ) + response = response.response + self.log("Task status for the task id {0} is {1}, is_error: {2}".format(str(task_id), str(response), str(response.get('isError'))), "INFO") + if response.get('isError') or re.search( + 'failed', response.get('progress'), flags=re.IGNORECASE + ): + msg = 'Discovery task with id {0} has not completed - Reason: {1}'.format( + task_id, response.get("failureReason")) + self.log(msg, "CRITICAL") + self.module.fail_json(msg=msg) + return False + + self.log("Task status for the task id (before checking status) {0} is {1}".format(str(task_id), str(response)), "INFO") + progress = response.get('progress') + if re.search('Discovery deleted successfully.', response.get('progress')): result = True - self.log("The Process is completed", "INFO") - break - self.result.update(dict(discovery_task=response)) - return result + self.log("The discovery process is completed", "INFO") + self.result.update(dict(discovery_task=response)) + return result + + self.log("The progress status is {0}, continue to check the status after 3 seconds. Putting into sleep for 3 seconds".format(progress)) + time.sleep(3) def lookup_discovery_by_range_via_name(self): """ @@ -1336,7 +1425,8 @@ class Discovery(DnacBase): response_part = self.dnac_apply['exec']( family="discovery", function='get_discoveries_by_range', - params=params + params=params, + op_modifies=True, ) response["response"].extend(response_part["response"]) else: @@ -1349,7 +1439,8 @@ class Discovery(DnacBase): response = self.dnac_apply['exec']( family="discovery", function='get_discoveries_by_range', - params=params + params=params, + op_modifies=True, ) self.log("Response of the get discoveries via range API is {0}".format(str(response)), "DEBUG") @@ -1373,6 +1464,7 @@ class Discovery(DnacBase): """ result = False + aborted = False discovery = self.lookup_discovery_by_range_via_name() if not discovery: @@ -1383,17 +1475,25 @@ class Discovery(DnacBase): while True: discovery = self.lookup_discovery_by_range_via_name() - if discovery.get('discoveryCondition') == 'Complete': + discovery_condition = discovery.get('discoveryCondition') + if discovery_condition == 'Complete': result = True break - + elif discovery_condition == 'Aborted': + aborted = True + break time.sleep(3) if not result: - msg = 'Cannot find any discovery task with name {0} -- Discovery result: {1}'.format( - str(self.validated_config[0].get("discovery_name")), str(discovery)) - self.log(msg, "CRITICAL") - self.module.fail_json(msg=msg) + if aborted is True: + msg = 'Discovery with name {0} is aborted by the user on the GUI'.format(str(self.validated_config[0].get("discovery_name"))) + self.log(msg, "CRITICAL") + self.module.fail_json(msg=msg) + else: + msg = 'Cannot find any discovery task with name {0} -- Discovery result: {1}'.format( + str(self.validated_config[0].get("discovery_name")), str(discovery)) + self.log(msg, "CRITICAL") + self.module.fail_json(msg=msg) self.result.update(dict(discovery_range=discovery)) return discovery @@ -1425,6 +1525,7 @@ class Discovery(DnacBase): family="discovery", function='get_discovered_network_devices_by_discovery_id', params=params, + op_modifies=True, ) devices = response.response @@ -1495,6 +1596,7 @@ class Discovery(DnacBase): family="discovery", function="delete_discovery_by_id", params=params, + op_modifies=True, ) self.log("Response collected from API 'delete_discovery_by_id': {0}".format(str(response)), "DEBUG") @@ -1513,17 +1615,18 @@ class Discovery(DnacBase): - self: The instance of the class with updated attributes. """ + self.validate_ip4_address_list() devices_list_info = self.get_devices_list_info() ip_address_list = self.preprocess_device_discovery(devices_list_info) exist_discovery = self.get_exist_discovery() if exist_discovery: params = dict(id=exist_discovery.get('id')) discovery_task_id = self.delete_exist_discovery(params=params) - complete_discovery = self.get_task_status(task_id=discovery_task_id) + complete_discovery = self.get_deleted_task_status(task_id=discovery_task_id) discovery_task_id = self.create_discovery( ip_address_list=ip_address_list) - complete_discovery = self.get_task_status(task_id=discovery_task_id) + complete_discovery = self.get_merged_task_status(task_id=discovery_task_id) discovery_task_info = self.get_discoveries_by_range_until_success() result = self.get_discovery_device_info(discovery_id=discovery_task_info.get('id')) self.result["changed"] = True @@ -1576,7 +1679,7 @@ class Discovery(DnacBase): params = dict(id=exist_discovery.get('id')) discovery_task_id = self.delete_exist_discovery(params=params) - complete_discovery = self.get_task_status(task_id=discovery_task_id) + complete_discovery = self.get_deleted_task_status(task_id=discovery_task_id) self.result["changed"] = True self.result['msg'] = "Successfully deleted discovery" self.result['diff'] = self.validated_config @@ -1611,7 +1714,8 @@ class Discovery(DnacBase): response = self.dnac_apply['exec']( family="discovery", function='get_discovery_by_id', - params=params + params=params, + op_modifies=True, ) discovery_name = config.get('discovery_name') if response: diff --git a/ansible_collections/cisco/dnac/plugins/modules/dna_command_runner_keywords_info.py b/ansible_collections/cisco/dnac/plugins/modules/dna_command_runner_keywords_info.py index dee8c3ff2..1e63e6b13 100644 --- a/ansible_collections/cisco/dnac/plugins/modules/dna_command_runner_keywords_info.py +++ b/ansible_collections/cisco/dnac/plugins/modules/dna_command_runner_keywords_info.py @@ -20,8 +20,8 @@ options: description: Additional headers. type: dict requirements: -- dnacentersdk >= 2.5.5 -- python >= 3.5 +- dnacentersdk >= 2.6.0 +- python >= 3.9 seealso: - name: Cisco DNA Center documentation for Command Runner GetAllKeywordsOfCLIsAcceptedByCommandRunner description: Complete reference of the GetAllKeywordsOfCLIsAcceptedByCommandRunner API. diff --git a/ansible_collections/cisco/dnac/plugins/modules/dnac_packages_info.py b/ansible_collections/cisco/dnac/plugins/modules/dnac_packages_info.py index 2d0a0e0dd..ebc2481a5 100644 --- a/ansible_collections/cisco/dnac/plugins/modules/dnac_packages_info.py +++ b/ansible_collections/cisco/dnac/plugins/modules/dnac_packages_info.py @@ -20,8 +20,8 @@ options: description: Additional headers. type: dict requirements: -- dnacentersdk >= 2.5.5 -- python >= 3.5 +- dnacentersdk >= 2.6.0 +- python >= 3.9 seealso: - name: Cisco DNA Center documentation for Platform CiscoDNACenterPackagesSummary description: Complete reference of the CiscoDNACenterPackagesSummary API. diff --git a/ansible_collections/cisco/dnac/plugins/modules/dnacaap_management_execution_status_info.py b/ansible_collections/cisco/dnac/plugins/modules/dnacaap_management_execution_status_info.py index 1afb01dff..3fc122f4d 100644 --- a/ansible_collections/cisco/dnac/plugins/modules/dnacaap_management_execution_status_info.py +++ b/ansible_collections/cisco/dnac/plugins/modules/dnacaap_management_execution_status_info.py @@ -24,8 +24,8 @@ options: - ExecutionId path parameter. Execution Id of API. type: str requirements: -- dnacentersdk >= 2.5.5 -- python >= 3.5 +- dnacentersdk >= 2.6.0 +- python >= 3.9 seealso: - name: Cisco DNA Center documentation for Task GetBusinessAPIExecutionDetails description: Complete reference of the GetBusinessAPIExecutionDetails API. diff --git a/ansible_collections/cisco/dnac/plugins/modules/endpoint_analytics_profiling_rules.py b/ansible_collections/cisco/dnac/plugins/modules/endpoint_analytics_profiling_rules.py index 38e2f47ec..43633824b 100644 --- a/ansible_collections/cisco/dnac/plugins/modules/endpoint_analytics_profiling_rules.py +++ b/ansible_collections/cisco/dnac/plugins/modules/endpoint_analytics_profiling_rules.py @@ -114,8 +114,8 @@ options: elements: str type: list requirements: -- dnacentersdk >= 2.5.5 -- python >= 3.5 +- dnacentersdk >= 2.6.0 +- python >= 3.9 notes: - SDK Method used are policy.Policy.create_a_profiling_rule, diff --git a/ansible_collections/cisco/dnac/plugins/modules/endpoint_analytics_profiling_rules_info.py b/ansible_collections/cisco/dnac/plugins/modules/endpoint_analytics_profiling_rules_info.py index 9c42ee1ea..1e3ca88c2 100644 --- a/ansible_collections/cisco/dnac/plugins/modules/endpoint_analytics_profiling_rules_info.py +++ b/ansible_collections/cisco/dnac/plugins/modules/endpoint_analytics_profiling_rules_info.py @@ -60,8 +60,8 @@ options: - RuleId path parameter. Unique rule identifier. type: str requirements: -- dnacentersdk >= 2.5.5 -- python >= 3.5 +- dnacentersdk >= 2.6.0 +- python >= 3.9 notes: - SDK Method used are policy.Policy.get_details_of_a_single_profiling_rule, diff --git a/ansible_collections/cisco/dnac/plugins/modules/eox_status_device_info.py b/ansible_collections/cisco/dnac/plugins/modules/eox_status_device_info.py index 6843843e8..dc1073450 100644 --- a/ansible_collections/cisco/dnac/plugins/modules/eox_status_device_info.py +++ b/ansible_collections/cisco/dnac/plugins/modules/eox_status_device_info.py @@ -26,8 +26,8 @@ options: - DeviceId path parameter. Device instance UUID. type: str requirements: -- dnacentersdk >= 2.5.5 -- python >= 3.5 +- dnacentersdk >= 2.6.0 +- python >= 3.9 seealso: - name: Cisco DNA Center documentation for EoX GetEoXDetailsPerDevice description: Complete reference of the GetEoXDetailsPerDevice API. diff --git a/ansible_collections/cisco/dnac/plugins/modules/eox_status_summary_info.py b/ansible_collections/cisco/dnac/plugins/modules/eox_status_summary_info.py index 0ec817750..26dc6d99d 100644 --- a/ansible_collections/cisco/dnac/plugins/modules/eox_status_summary_info.py +++ b/ansible_collections/cisco/dnac/plugins/modules/eox_status_summary_info.py @@ -20,8 +20,8 @@ options: description: Additional headers. type: dict requirements: -- dnacentersdk >= 2.5.5 -- python >= 3.5 +- dnacentersdk >= 2.6.0 +- python >= 3.9 seealso: - name: Cisco DNA Center documentation for EoX GetEoXSummary description: Complete reference of the GetEoXSummary API. diff --git a/ansible_collections/cisco/dnac/plugins/modules/event_api_status_info.py b/ansible_collections/cisco/dnac/plugins/modules/event_api_status_info.py index 4ddaaca0a..8c6cf8d13 100644 --- a/ansible_collections/cisco/dnac/plugins/modules/event_api_status_info.py +++ b/ansible_collections/cisco/dnac/plugins/modules/event_api_status_info.py @@ -24,8 +24,8 @@ options: - ExecutionId path parameter. Execution ID. type: str requirements: -- dnacentersdk >= 2.5.5 -- python >= 3.5 +- dnacentersdk >= 2.6.0 +- python >= 3.9 seealso: - name: Cisco DNA Center documentation for Event Management GetStatusAPIForEvents description: Complete reference of the GetStatusAPIForEvents API. diff --git a/ansible_collections/cisco/dnac/plugins/modules/event_artifact_count_info.py b/ansible_collections/cisco/dnac/plugins/modules/event_artifact_count_info.py index f34e77fe8..fb7d3ab7d 100644 --- a/ansible_collections/cisco/dnac/plugins/modules/event_artifact_count_info.py +++ b/ansible_collections/cisco/dnac/plugins/modules/event_artifact_count_info.py @@ -20,8 +20,8 @@ options: description: Additional headers. type: dict requirements: -- dnacentersdk >= 2.5.5 -- python >= 3.5 +- dnacentersdk >= 2.6.0 +- python >= 3.9 seealso: - name: Cisco DNA Center documentation for Event Management EventArtifactCount description: Complete reference of the EventArtifactCount API. diff --git a/ansible_collections/cisco/dnac/plugins/modules/event_artifact_info.py b/ansible_collections/cisco/dnac/plugins/modules/event_artifact_info.py index 6e4f14b6a..196b1233c 100644 --- a/ansible_collections/cisco/dnac/plugins/modules/event_artifact_info.py +++ b/ansible_collections/cisco/dnac/plugins/modules/event_artifact_info.py @@ -48,8 +48,8 @@ options: - Search query parameter. Findd matches in name, description, eventId, type, category. type: str requirements: -- dnacentersdk >= 2.5.5 -- python >= 3.5 +- dnacentersdk >= 2.6.0 +- python >= 3.9 seealso: - name: Cisco DNA Center documentation for Event Management GetEventArtifacts description: Complete reference of the GetEventArtifacts API. diff --git a/ansible_collections/cisco/dnac/plugins/modules/event_config_connector_types_info.py b/ansible_collections/cisco/dnac/plugins/modules/event_config_connector_types_info.py index 8c0958e7e..b30a9659a 100644 --- a/ansible_collections/cisco/dnac/plugins/modules/event_config_connector_types_info.py +++ b/ansible_collections/cisco/dnac/plugins/modules/event_config_connector_types_info.py @@ -20,8 +20,8 @@ options: description: Additional headers. type: dict requirements: -- dnacentersdk >= 2.5.5 -- python >= 3.5 +- dnacentersdk >= 2.6.0 +- python >= 3.9 seealso: - name: Cisco DNA Center documentation for Event Management GetConnectorTypes description: Complete reference of the GetConnectorTypes API. diff --git a/ansible_collections/cisco/dnac/plugins/modules/event_count_info.py b/ansible_collections/cisco/dnac/plugins/modules/event_count_info.py index 131712342..864364655 100644 --- a/ansible_collections/cisco/dnac/plugins/modules/event_count_info.py +++ b/ansible_collections/cisco/dnac/plugins/modules/event_count_info.py @@ -28,8 +28,8 @@ options: - Tags query parameter. The registered Tags should be provided. type: str requirements: -- dnacentersdk >= 2.5.5 -- python >= 3.5 +- dnacentersdk >= 2.6.0 +- python >= 3.9 seealso: - name: Cisco DNA Center documentation for Event Management CountOfEvents description: Complete reference of the CountOfEvents API. diff --git a/ansible_collections/cisco/dnac/plugins/modules/event_email_config.py b/ansible_collections/cisco/dnac/plugins/modules/event_email_config.py index 3b9de49a1..fd5fdb882 100644 --- a/ansible_collections/cisco/dnac/plugins/modules/event_email_config.py +++ b/ansible_collections/cisco/dnac/plugins/modules/event_email_config.py @@ -62,8 +62,8 @@ options: description: To Email. type: str requirements: -- dnacentersdk >= 2.5.5 -- python >= 3.5 +- dnacentersdk >= 2.6.0 +- python >= 3.9 seealso: - name: Cisco DNA Center documentation for Event Management CreateEmailDestination description: Complete reference of the CreateEmailDestination API. diff --git a/ansible_collections/cisco/dnac/plugins/modules/event_email_config_create.py b/ansible_collections/cisco/dnac/plugins/modules/event_email_config_create.py index b207dde21..4be4ec362 100644 --- a/ansible_collections/cisco/dnac/plugins/modules/event_email_config_create.py +++ b/ansible_collections/cisco/dnac/plugins/modules/event_email_config_create.py @@ -61,8 +61,8 @@ options: description: To Email. type: str requirements: -- dnacentersdk >= 2.5.5 -- python >= 3.5 +- dnacentersdk >= 2.6.0 +- python >= 3.9 seealso: - name: Cisco DNA Center documentation for Event Management CreateEmailDestination description: Complete reference of the CreateEmailDestination API. diff --git a/ansible_collections/cisco/dnac/plugins/modules/event_email_config_info.py b/ansible_collections/cisco/dnac/plugins/modules/event_email_config_info.py index 6aa855855..272118cd7 100644 --- a/ansible_collections/cisco/dnac/plugins/modules/event_email_config_info.py +++ b/ansible_collections/cisco/dnac/plugins/modules/event_email_config_info.py @@ -20,8 +20,8 @@ options: description: Additional headers. type: dict requirements: -- dnacentersdk >= 2.5.5 -- python >= 3.5 +- dnacentersdk >= 2.6.0 +- python >= 3.9 seealso: - name: Cisco DNA Center documentation for Event Management GetEmailDestination description: Complete reference of the GetEmailDestination API. diff --git a/ansible_collections/cisco/dnac/plugins/modules/event_email_config_update.py b/ansible_collections/cisco/dnac/plugins/modules/event_email_config_update.py index 2234ae907..c471ff807 100644 --- a/ansible_collections/cisco/dnac/plugins/modules/event_email_config_update.py +++ b/ansible_collections/cisco/dnac/plugins/modules/event_email_config_update.py @@ -61,8 +61,8 @@ options: description: To Email. type: str requirements: -- dnacentersdk >= 2.5.5 -- python >= 3.5 +- dnacentersdk >= 2.6.0 +- python >= 3.9 seealso: - name: Cisco DNA Center documentation for Event Management UpdateEmailDestination description: Complete reference of the UpdateEmailDestination API. diff --git a/ansible_collections/cisco/dnac/plugins/modules/event_info.py b/ansible_collections/cisco/dnac/plugins/modules/event_info.py index ac34fbf25..a3eafb297 100644 --- a/ansible_collections/cisco/dnac/plugins/modules/event_info.py +++ b/ansible_collections/cisco/dnac/plugins/modules/event_info.py @@ -44,8 +44,8 @@ options: - Order query parameter. type: str requirements: -- dnacentersdk >= 2.5.5 -- python >= 3.5 +- dnacentersdk >= 2.6.0 +- python >= 3.9 seealso: - name: Cisco DNA Center documentation for Event Management GetEvents description: Complete reference of the GetEvents API. diff --git a/ansible_collections/cisco/dnac/plugins/modules/event_series_audit_logs_info.py b/ansible_collections/cisco/dnac/plugins/modules/event_series_audit_logs_info.py index dbb7b5320..b5fa297d9 100644 --- a/ansible_collections/cisco/dnac/plugins/modules/event_series_audit_logs_info.py +++ b/ansible_collections/cisco/dnac/plugins/modules/event_series_audit_logs_info.py @@ -122,8 +122,8 @@ options: values asc, desc. type: str requirements: -- dnacentersdk >= 2.5.5 -- python >= 3.5 +- dnacentersdk >= 2.6.0 +- python >= 3.9 seealso: - name: Cisco DNA Center documentation for Event Management GetAuditLogRecords description: Complete reference of the GetAuditLogRecords API. diff --git a/ansible_collections/cisco/dnac/plugins/modules/event_series_audit_logs_parent_records_info.py b/ansible_collections/cisco/dnac/plugins/modules/event_series_audit_logs_parent_records_info.py index 6f6a2b616..26bd96d29 100644 --- a/ansible_collections/cisco/dnac/plugins/modules/event_series_audit_logs_parent_records_info.py +++ b/ansible_collections/cisco/dnac/plugins/modules/event_series_audit_logs_parent_records_info.py @@ -118,8 +118,8 @@ options: values asc, desc. type: str requirements: -- dnacentersdk >= 2.5.5 -- python >= 3.5 +- dnacentersdk >= 2.6.0 +- python >= 3.9 seealso: - name: Cisco DNA Center documentation for Event Management GetAuditLogParentRecords description: Complete reference of the GetAuditLogParentRecords API. diff --git a/ansible_collections/cisco/dnac/plugins/modules/event_series_audit_logs_summary_info.py b/ansible_collections/cisco/dnac/plugins/modules/event_series_audit_logs_summary_info.py index ee2063fa0..2e0d2e133 100644 --- a/ansible_collections/cisco/dnac/plugins/modules/event_series_audit_logs_summary_info.py +++ b/ansible_collections/cisco/dnac/plugins/modules/event_series_audit_logs_summary_info.py @@ -106,8 +106,8 @@ options: mandatory). type: int requirements: -- dnacentersdk >= 2.5.5 -- python >= 3.5 +- dnacentersdk >= 2.6.0 +- python >= 3.9 seealso: - name: Cisco DNA Center documentation for Event Management GetAuditLogSummary description: Complete reference of the GetAuditLogSummary API. diff --git a/ansible_collections/cisco/dnac/plugins/modules/event_series_count_info.py b/ansible_collections/cisco/dnac/plugins/modules/event_series_count_info.py index 6fd07cf4a..ebd6576f0 100644 --- a/ansible_collections/cisco/dnac/plugins/modules/event_series_count_info.py +++ b/ansible_collections/cisco/dnac/plugins/modules/event_series_count_info.py @@ -56,8 +56,8 @@ options: - Source query parameter. type: str requirements: -- dnacentersdk >= 2.5.5 -- python >= 3.5 +- dnacentersdk >= 2.6.0 +- python >= 3.9 seealso: - name: Cisco DNA Center documentation for Event Management CountOfNotifications description: Complete reference of the CountOfNotifications API. diff --git a/ansible_collections/cisco/dnac/plugins/modules/event_series_info.py b/ansible_collections/cisco/dnac/plugins/modules/event_series_info.py index 523e5a708..982aa0cbc 100644 --- a/ansible_collections/cisco/dnac/plugins/modules/event_series_info.py +++ b/ansible_collections/cisco/dnac/plugins/modules/event_series_info.py @@ -84,8 +84,8 @@ options: - SiteId query parameter. Site Id. type: str requirements: -- dnacentersdk >= 2.5.5 -- python >= 3.5 +- dnacentersdk >= 2.6.0 +- python >= 3.9 seealso: - name: Cisco DNA Center documentation for Event Management GetNotifications description: Complete reference of the GetNotifications API. diff --git a/ansible_collections/cisco/dnac/plugins/modules/event_snmp_config_info.py b/ansible_collections/cisco/dnac/plugins/modules/event_snmp_config_info.py index 6ae23c7f3..b87081672 100644 --- a/ansible_collections/cisco/dnac/plugins/modules/event_snmp_config_info.py +++ b/ansible_collections/cisco/dnac/plugins/modules/event_snmp_config_info.py @@ -40,8 +40,8 @@ options: - Order query parameter. type: str requirements: -- dnacentersdk >= 2.5.5 -- python >= 3.5 +- dnacentersdk >= 2.6.0 +- python >= 3.9 seealso: - name: Cisco DNA Center documentation for Event Management GetSNMPDestination description: Complete reference of the GetSNMPDestination API. diff --git a/ansible_collections/cisco/dnac/plugins/modules/event_subscription.py b/ansible_collections/cisco/dnac/plugins/modules/event_subscription.py index 38c2899ae..0aca4d2db 100644 --- a/ansible_collections/cisco/dnac/plugins/modules/event_subscription.py +++ b/ansible_collections/cisco/dnac/plugins/modules/event_subscription.py @@ -94,8 +94,8 @@ options: description: Subscriptions query parameter. List of EventSubscriptionId's for removal. type: str requirements: -- dnacentersdk >= 2.5.5 -- python >= 3.5 +- dnacentersdk >= 2.6.0 +- python >= 3.9 seealso: - name: Cisco DNA Center documentation for Event Management CreateEventSubscriptions description: Complete reference of the CreateEventSubscriptions API. diff --git a/ansible_collections/cisco/dnac/plugins/modules/event_subscription_count_info.py b/ansible_collections/cisco/dnac/plugins/modules/event_subscription_count_info.py index e9eb3e432..daf1a6fdf 100644 --- a/ansible_collections/cisco/dnac/plugins/modules/event_subscription_count_info.py +++ b/ansible_collections/cisco/dnac/plugins/modules/event_subscription_count_info.py @@ -24,8 +24,8 @@ options: - EventIds query parameter. List of subscriptions related to the respective eventIds. type: str requirements: -- dnacentersdk >= 2.5.5 -- python >= 3.5 +- dnacentersdk >= 2.6.0 +- python >= 3.9 seealso: - name: Cisco DNA Center documentation for Event Management CountOfEventSubscriptions description: Complete reference of the CountOfEventSubscriptions API. diff --git a/ansible_collections/cisco/dnac/plugins/modules/event_subscription_details_email_info.py b/ansible_collections/cisco/dnac/plugins/modules/event_subscription_details_email_info.py index 7109b1ac1..b6487d13f 100644 --- a/ansible_collections/cisco/dnac/plugins/modules/event_subscription_details_email_info.py +++ b/ansible_collections/cisco/dnac/plugins/modules/event_subscription_details_email_info.py @@ -44,8 +44,8 @@ options: - Order query parameter. type: str requirements: -- dnacentersdk >= 2.5.5 -- python >= 3.5 +- dnacentersdk >= 2.6.0 +- python >= 3.9 seealso: - name: Cisco DNA Center documentation for Event Management GetEmailSubscriptionDetails description: Complete reference of the GetEmailSubscriptionDetails API. diff --git a/ansible_collections/cisco/dnac/plugins/modules/event_subscription_details_rest_info.py b/ansible_collections/cisco/dnac/plugins/modules/event_subscription_details_rest_info.py index cde6348bf..ee793eff1 100644 --- a/ansible_collections/cisco/dnac/plugins/modules/event_subscription_details_rest_info.py +++ b/ansible_collections/cisco/dnac/plugins/modules/event_subscription_details_rest_info.py @@ -48,8 +48,8 @@ options: - Order query parameter. type: str requirements: -- dnacentersdk >= 2.5.5 -- python >= 3.5 +- dnacentersdk >= 2.6.0 +- python >= 3.9 seealso: - name: Cisco DNA Center documentation for Event Management GetRestWebhookSubscriptionDetails description: Complete reference of the GetRestWebhookSubscriptionDetails API. diff --git a/ansible_collections/cisco/dnac/plugins/modules/event_subscription_details_syslog_info.py b/ansible_collections/cisco/dnac/plugins/modules/event_subscription_details_syslog_info.py index 2d3676759..18e68fa77 100644 --- a/ansible_collections/cisco/dnac/plugins/modules/event_subscription_details_syslog_info.py +++ b/ansible_collections/cisco/dnac/plugins/modules/event_subscription_details_syslog_info.py @@ -46,8 +46,8 @@ options: - Order query parameter. type: str requirements: -- dnacentersdk >= 2.5.5 -- python >= 3.5 +- dnacentersdk >= 2.6.0 +- python >= 3.9 seealso: - name: Cisco DNA Center documentation for Event Management GetSyslogSubscriptionDetails description: Complete reference of the GetSyslogSubscriptionDetails API. diff --git a/ansible_collections/cisco/dnac/plugins/modules/event_subscription_email.py b/ansible_collections/cisco/dnac/plugins/modules/event_subscription_email.py index 56b82b4a8..13dc4cfe8 100644 --- a/ansible_collections/cisco/dnac/plugins/modules/event_subscription_email.py +++ b/ansible_collections/cisco/dnac/plugins/modules/event_subscription_email.py @@ -106,8 +106,8 @@ options: type: str type: list requirements: -- dnacentersdk >= 2.5.5 -- python >= 3.5 +- dnacentersdk >= 2.6.0 +- python >= 3.9 seealso: - name: Cisco DNA Center documentation for Event Management CreateEmailEventSubscription description: Complete reference of the CreateEmailEventSubscription API. diff --git a/ansible_collections/cisco/dnac/plugins/modules/event_subscription_email_info.py b/ansible_collections/cisco/dnac/plugins/modules/event_subscription_email_info.py index 5d20ef478..3eab8992b 100644 --- a/ansible_collections/cisco/dnac/plugins/modules/event_subscription_email_info.py +++ b/ansible_collections/cisco/dnac/plugins/modules/event_subscription_email_info.py @@ -62,8 +62,8 @@ options: - Name query parameter. List of email subscriptions related to the respective name. type: str requirements: -- dnacentersdk >= 2.5.5 -- python >= 3.5 +- dnacentersdk >= 2.6.0 +- python >= 3.9 seealso: - name: Cisco DNA Center documentation for Event Management GetEmailEventSubscriptions description: Complete reference of the GetEmailEventSubscriptions API. diff --git a/ansible_collections/cisco/dnac/plugins/modules/event_subscription_info.py b/ansible_collections/cisco/dnac/plugins/modules/event_subscription_info.py index 7655d9676..9349d81e7 100644 --- a/ansible_collections/cisco/dnac/plugins/modules/event_subscription_info.py +++ b/ansible_collections/cisco/dnac/plugins/modules/event_subscription_info.py @@ -40,8 +40,8 @@ options: - Order query parameter. type: str requirements: -- dnacentersdk >= 2.5.5 -- python >= 3.5 +- dnacentersdk >= 2.6.0 +- python >= 3.9 seealso: - name: Cisco DNA Center documentation for Event Management GetEventSubscriptions description: Complete reference of the GetEventSubscriptions API. diff --git a/ansible_collections/cisco/dnac/plugins/modules/event_subscription_rest.py b/ansible_collections/cisco/dnac/plugins/modules/event_subscription_rest.py index acfc5f9e4..81eea1f2e 100644 --- a/ansible_collections/cisco/dnac/plugins/modules/event_subscription_rest.py +++ b/ansible_collections/cisco/dnac/plugins/modules/event_subscription_rest.py @@ -90,8 +90,8 @@ options: type: str type: list requirements: -- dnacentersdk >= 2.5.5 -- python >= 3.5 +- dnacentersdk >= 2.6.0 +- python >= 3.9 seealso: - name: Cisco DNA Center documentation for Event Management CreateRestWebhookEventSubscription description: Complete reference of the CreateRestWebhookEventSubscription API. diff --git a/ansible_collections/cisco/dnac/plugins/modules/event_subscription_rest_info.py b/ansible_collections/cisco/dnac/plugins/modules/event_subscription_rest_info.py index a26bf7473..06e8dab61 100644 --- a/ansible_collections/cisco/dnac/plugins/modules/event_subscription_rest_info.py +++ b/ansible_collections/cisco/dnac/plugins/modules/event_subscription_rest_info.py @@ -60,8 +60,8 @@ options: - Name query parameter. List of subscriptions related to the respective name. type: str requirements: -- dnacentersdk >= 2.5.5 -- python >= 3.5 +- dnacentersdk >= 2.6.0 +- python >= 3.9 seealso: - name: Cisco DNA Center documentation for Event Management GetRestWebhookEventSubscriptions description: Complete reference of the GetRestWebhookEventSubscriptions API. diff --git a/ansible_collections/cisco/dnac/plugins/modules/event_subscription_syslog.py b/ansible_collections/cisco/dnac/plugins/modules/event_subscription_syslog.py index 802664038..aeff30dd3 100644 --- a/ansible_collections/cisco/dnac/plugins/modules/event_subscription_syslog.py +++ b/ansible_collections/cisco/dnac/plugins/modules/event_subscription_syslog.py @@ -90,8 +90,8 @@ options: type: str type: list requirements: -- dnacentersdk >= 2.5.5 -- python >= 3.5 +- dnacentersdk >= 2.6.0 +- python >= 3.9 seealso: - name: Cisco DNA Center documentation for Event Management CreateSyslogEventSubscription description: Complete reference of the CreateSyslogEventSubscription API. diff --git a/ansible_collections/cisco/dnac/plugins/modules/event_subscription_syslog_info.py b/ansible_collections/cisco/dnac/plugins/modules/event_subscription_syslog_info.py index dcd077007..ef6ffb044 100644 --- a/ansible_collections/cisco/dnac/plugins/modules/event_subscription_syslog_info.py +++ b/ansible_collections/cisco/dnac/plugins/modules/event_subscription_syslog_info.py @@ -60,8 +60,8 @@ options: - Name query parameter. List of subscriptions related to the respective name. type: str requirements: -- dnacentersdk >= 2.5.5 -- python >= 3.5 +- dnacentersdk >= 2.6.0 +- python >= 3.9 seealso: - name: Cisco DNA Center documentation for Event Management GetSyslogEventSubscriptions description: Complete reference of the GetSyslogEventSubscriptions API. diff --git a/ansible_collections/cisco/dnac/plugins/modules/event_syslog_config.py b/ansible_collections/cisco/dnac/plugins/modules/event_syslog_config.py index a59316f39..11c6d9508 100644 --- a/ansible_collections/cisco/dnac/plugins/modules/event_syslog_config.py +++ b/ansible_collections/cisco/dnac/plugins/modules/event_syslog_config.py @@ -36,8 +36,8 @@ options: description: Protocol. type: str requirements: -- dnacentersdk >= 2.5.5 -- python >= 3.5 +- dnacentersdk >= 2.6.0 +- python >= 3.9 seealso: - name: Cisco DNA Center documentation for Event Management CreateSyslogDestination description: Complete reference of the CreateSyslogDestination API. diff --git a/ansible_collections/cisco/dnac/plugins/modules/event_syslog_config_info.py b/ansible_collections/cisco/dnac/plugins/modules/event_syslog_config_info.py index 2c2617128..a2e6009c8 100644 --- a/ansible_collections/cisco/dnac/plugins/modules/event_syslog_config_info.py +++ b/ansible_collections/cisco/dnac/plugins/modules/event_syslog_config_info.py @@ -48,8 +48,8 @@ options: - Order query parameter. type: str requirements: -- dnacentersdk >= 2.5.5 -- python >= 3.5 +- dnacentersdk >= 2.6.0 +- python >= 3.9 seealso: - name: Cisco DNA Center documentation for Event Management GetSyslogDestination description: Complete reference of the GetSyslogDestination API. diff --git a/ansible_collections/cisco/dnac/plugins/modules/event_webhook_create.py b/ansible_collections/cisco/dnac/plugins/modules/event_webhook_create.py index b9c585ee9..2859b7615 100644 --- a/ansible_collections/cisco/dnac/plugins/modules/event_webhook_create.py +++ b/ansible_collections/cisco/dnac/plugins/modules/event_webhook_create.py @@ -52,8 +52,8 @@ options: description: Required only for update webhook configuration. type: str requirements: -- dnacentersdk >= 2.5.5 -- python >= 3.5 +- dnacentersdk >= 2.6.0 +- python >= 3.9 seealso: - name: Cisco DNA Center documentation for Event Management CreateWebhookDestination description: Complete reference of the CreateWebhookDestination API. diff --git a/ansible_collections/cisco/dnac/plugins/modules/event_webhook_update.py b/ansible_collections/cisco/dnac/plugins/modules/event_webhook_update.py index 91d70839b..0c50462ed 100644 --- a/ansible_collections/cisco/dnac/plugins/modules/event_webhook_update.py +++ b/ansible_collections/cisco/dnac/plugins/modules/event_webhook_update.py @@ -52,8 +52,8 @@ options: description: Required only for update webhook configuration. type: str requirements: -- dnacentersdk >= 2.5.5 -- python >= 3.5 +- dnacentersdk >= 2.6.0 +- python >= 3.9 seealso: - name: Cisco DNA Center documentation for Event Management UpdateWebhookDestination description: Complete reference of the UpdateWebhookDestination API. diff --git a/ansible_collections/cisco/dnac/plugins/modules/execute_suggested_actions_commands.py b/ansible_collections/cisco/dnac/plugins/modules/execute_suggested_actions_commands.py index 51df59677..43fce3203 100644 --- a/ansible_collections/cisco/dnac/plugins/modules/execute_suggested_actions_commands.py +++ b/ansible_collections/cisco/dnac/plugins/modules/execute_suggested_actions_commands.py @@ -27,8 +27,8 @@ options: description: Contains the actual value for the entity type that has been defined. type: str requirements: -- dnacentersdk >= 2.5.5 -- python >= 3.5 +- dnacentersdk >= 2.6.0 +- python >= 3.9 seealso: - name: Cisco DNA Center documentation for Issues ExecuteSuggestedActionsCommands description: Complete reference of the ExecuteSuggestedActionsCommands API. diff --git a/ansible_collections/cisco/dnac/plugins/modules/file_import.py b/ansible_collections/cisco/dnac/plugins/modules/file_import.py index f82598e0c..f9909eddd 100644 --- a/ansible_collections/cisco/dnac/plugins/modules/file_import.py +++ b/ansible_collections/cisco/dnac/plugins/modules/file_import.py @@ -23,8 +23,8 @@ options: description: NameSpace path parameter. type: str requirements: -- dnacentersdk >= 2.5.5 -- python >= 3.5 +- dnacentersdk >= 2.6.0 +- python >= 3.9 seealso: - name: Cisco DNA Center documentation for File UploadFile description: Complete reference of the UploadFile API. diff --git a/ansible_collections/cisco/dnac/plugins/modules/file_info.py b/ansible_collections/cisco/dnac/plugins/modules/file_info.py index bf07d1072..b9bdba4b9 100644 --- a/ansible_collections/cisco/dnac/plugins/modules/file_info.py +++ b/ansible_collections/cisco/dnac/plugins/modules/file_info.py @@ -36,8 +36,8 @@ options: - The filename used to save the download file. type: str requirements: -- dnacentersdk >= 2.5.5 -- python >= 3.5 +- dnacentersdk >= 2.6.0 +- python >= 3.9 seealso: - name: Cisco DNA Center documentation for File DownloadAFileByFileId description: Complete reference of the DownloadAFileByFileId API. diff --git a/ansible_collections/cisco/dnac/plugins/modules/file_namespace_files_info.py b/ansible_collections/cisco/dnac/plugins/modules/file_namespace_files_info.py index e28b10c8f..0e16dbc1a 100644 --- a/ansible_collections/cisco/dnac/plugins/modules/file_namespace_files_info.py +++ b/ansible_collections/cisco/dnac/plugins/modules/file_namespace_files_info.py @@ -24,8 +24,8 @@ options: - NameSpace path parameter. A listing of fileId's. type: str requirements: -- dnacentersdk >= 2.5.5 -- python >= 3.5 +- dnacentersdk >= 2.6.0 +- python >= 3.9 seealso: - name: Cisco DNA Center documentation for File GetListOfFiles description: Complete reference of the GetListOfFiles API. diff --git a/ansible_collections/cisco/dnac/plugins/modules/file_namespaces_info.py b/ansible_collections/cisco/dnac/plugins/modules/file_namespaces_info.py index a0fc5682f..849268111 100644 --- a/ansible_collections/cisco/dnac/plugins/modules/file_namespaces_info.py +++ b/ansible_collections/cisco/dnac/plugins/modules/file_namespaces_info.py @@ -20,8 +20,8 @@ options: description: Additional headers. type: dict requirements: -- dnacentersdk >= 2.5.5 -- python >= 3.5 +- dnacentersdk >= 2.6.0 +- python >= 3.9 seealso: - name: Cisco DNA Center documentation for File GetListOfAvailableNamespaces description: Complete reference of the GetListOfAvailableNamespaces API. diff --git a/ansible_collections/cisco/dnac/plugins/modules/global_credential_delete.py b/ansible_collections/cisco/dnac/plugins/modules/global_credential_delete.py index 13c9630c3..3dd9ad1d1 100644 --- a/ansible_collections/cisco/dnac/plugins/modules/global_credential_delete.py +++ b/ansible_collections/cisco/dnac/plugins/modules/global_credential_delete.py @@ -20,8 +20,8 @@ options: description: GlobalCredentialId path parameter. ID of global-credential. type: str requirements: -- dnacentersdk >= 2.5.5 -- python >= 3.5 +- dnacentersdk >= 2.6.0 +- python >= 3.9 seealso: - name: Cisco DNA Center documentation for Discovery DeleteGlobalCredentialsById description: Complete reference of the DeleteGlobalCredentialsById API. diff --git a/ansible_collections/cisco/dnac/plugins/modules/global_credential_info.py b/ansible_collections/cisco/dnac/plugins/modules/global_credential_info.py index 4fe317b6f..2d46ca10f 100644 --- a/ansible_collections/cisco/dnac/plugins/modules/global_credential_info.py +++ b/ansible_collections/cisco/dnac/plugins/modules/global_credential_info.py @@ -40,8 +40,8 @@ options: - Id path parameter. Global Credential ID. type: str requirements: -- dnacentersdk >= 2.5.5 -- python >= 3.5 +- dnacentersdk >= 2.6.0 +- python >= 3.9 seealso: - name: Cisco DNA Center documentation for Discovery GetCredentialSubTypeByCredentialId description: Complete reference of the GetCredentialSubTypeByCredentialId API. diff --git a/ansible_collections/cisco/dnac/plugins/modules/global_credential_update.py b/ansible_collections/cisco/dnac/plugins/modules/global_credential_update.py index 127504846..8f2ea144a 100644 --- a/ansible_collections/cisco/dnac/plugins/modules/global_credential_update.py +++ b/ansible_collections/cisco/dnac/plugins/modules/global_credential_update.py @@ -24,8 +24,8 @@ options: elements: str type: list requirements: -- dnacentersdk >= 2.5.5 -- python >= 3.5 +- dnacentersdk >= 2.6.0 +- python >= 3.9 seealso: - name: Cisco DNA Center documentation for Discovery UpdateGlobalCredentials description: Complete reference of the UpdateGlobalCredentials API. diff --git a/ansible_collections/cisco/dnac/plugins/modules/global_credential_v2.py b/ansible_collections/cisco/dnac/plugins/modules/global_credential_v2.py index 0679fed86..2d27cca33 100644 --- a/ansible_collections/cisco/dnac/plugins/modules/global_credential_v2.py +++ b/ansible_collections/cisco/dnac/plugins/modules/global_credential_v2.py @@ -137,8 +137,8 @@ options: type: str type: dict requirements: -- dnacentersdk >= 2.5.5 -- python >= 3.5 +- dnacentersdk >= 2.6.0 +- python >= 3.9 seealso: - name: Cisco DNA Center documentation for Discovery CreateGlobalCredentialsV2 description: Complete reference of the CreateGlobalCredentialsV2 API. diff --git a/ansible_collections/cisco/dnac/plugins/modules/global_credential_v2_info.py b/ansible_collections/cisco/dnac/plugins/modules/global_credential_v2_info.py index c746964cb..6b0bffd4d 100644 --- a/ansible_collections/cisco/dnac/plugins/modules/global_credential_v2_info.py +++ b/ansible_collections/cisco/dnac/plugins/modules/global_credential_v2_info.py @@ -22,8 +22,8 @@ options: description: Additional headers. type: dict requirements: -- dnacentersdk >= 2.5.5 -- python >= 3.5 +- dnacentersdk >= 2.6.0 +- python >= 3.9 seealso: - name: Cisco DNA Center documentation for Discovery GetAllGlobalCredentialsV2 description: Complete reference of the GetAllGlobalCredentialsV2 API. diff --git a/ansible_collections/cisco/dnac/plugins/modules/global_pool.py b/ansible_collections/cisco/dnac/plugins/modules/global_pool.py index 3c94f9c58..f52c316d6 100644 --- a/ansible_collections/cisco/dnac/plugins/modules/global_pool.py +++ b/ansible_collections/cisco/dnac/plugins/modules/global_pool.py @@ -48,8 +48,8 @@ options: type: list type: dict requirements: -- dnacentersdk >= 2.5.5 -- python >= 3.5 +- dnacentersdk >= 2.6.0 +- python >= 3.9 seealso: - name: Cisco DNA Center documentation for Network Settings CreateGlobalPool description: Complete reference of the CreateGlobalPool API. diff --git a/ansible_collections/cisco/dnac/plugins/modules/global_pool_info.py b/ansible_collections/cisco/dnac/plugins/modules/global_pool_info.py index ed95446be..4d95ba9ea 100644 --- a/ansible_collections/cisco/dnac/plugins/modules/global_pool_info.py +++ b/ansible_collections/cisco/dnac/plugins/modules/global_pool_info.py @@ -28,8 +28,8 @@ options: - Limit query parameter. No of Global Pools to be retrieved. type: int requirements: -- dnacentersdk >= 2.5.5 -- python >= 3.5 +- dnacentersdk >= 2.6.0 +- python >= 3.9 seealso: - name: Cisco DNA Center documentation for Network Settings GetGlobalPool description: Complete reference of the GetGlobalPool API. diff --git a/ansible_collections/cisco/dnac/plugins/modules/golden_image_create.py b/ansible_collections/cisco/dnac/plugins/modules/golden_image_create.py index 1f176f172..95385c59d 100644 --- a/ansible_collections/cisco/dnac/plugins/modules/golden_image_create.py +++ b/ansible_collections/cisco/dnac/plugins/modules/golden_image_create.py @@ -30,8 +30,8 @@ options: description: SiteId in uuid format. For Global Site "-1" to be used. type: str requirements: -- dnacentersdk >= 2.5.5 -- python >= 3.5 +- dnacentersdk >= 2.6.0 +- python >= 3.9 seealso: - name: Cisco DNA Center documentation for Software Image Management (SWIM) TagAsGoldenImage description: Complete reference of the TagAsGoldenImage API. diff --git a/ansible_collections/cisco/dnac/plugins/modules/golden_tag_image_delete.py b/ansible_collections/cisco/dnac/plugins/modules/golden_tag_image_delete.py index 8191e4915..392165663 100644 --- a/ansible_collections/cisco/dnac/plugins/modules/golden_tag_image_delete.py +++ b/ansible_collections/cisco/dnac/plugins/modules/golden_tag_image_delete.py @@ -32,8 +32,8 @@ options: Global site. type: str requirements: -- dnacentersdk >= 2.5.5 -- python >= 3.5 +- dnacentersdk >= 2.6.0 +- python >= 3.9 seealso: - name: Cisco DNA Center documentation for Software Image Management (SWIM) RemoveGoldenTagForImage description: Complete reference of the RemoveGoldenTagForImage API. diff --git a/ansible_collections/cisco/dnac/plugins/modules/golden_tag_image_details_info.py b/ansible_collections/cisco/dnac/plugins/modules/golden_tag_image_details_info.py index 9d41a7610..c92ed9503 100644 --- a/ansible_collections/cisco/dnac/plugins/modules/golden_tag_image_details_info.py +++ b/ansible_collections/cisco/dnac/plugins/modules/golden_tag_image_details_info.py @@ -38,8 +38,8 @@ options: - ImageId path parameter. Image Id in uuid format. type: str requirements: -- dnacentersdk >= 2.5.5 -- python >= 3.5 +- dnacentersdk >= 2.6.0 +- python >= 3.9 seealso: - name: Cisco DNA Center documentation for Software Image Management (SWIM) GetGoldenTagStatusOfAnImage description: Complete reference of the GetGoldenTagStatusOfAnImage API. diff --git a/ansible_collections/cisco/dnac/plugins/modules/http_read_credential.py b/ansible_collections/cisco/dnac/plugins/modules/http_read_credential.py index 63c19d5c4..89a5f7f47 100644 --- a/ansible_collections/cisco/dnac/plugins/modules/http_read_credential.py +++ b/ansible_collections/cisco/dnac/plugins/modules/http_read_credential.py @@ -48,8 +48,8 @@ options: description: Http Read Credential's username. type: str requirements: -- dnacentersdk >= 2.5.5 -- python >= 3.5 +- dnacentersdk >= 2.6.0 +- python >= 3.9 seealso: - name: Cisco DNA Center documentation for Discovery CreateHTTPReadCredentials description: Complete reference of the CreateHTTPReadCredentials API. diff --git a/ansible_collections/cisco/dnac/plugins/modules/http_write_credential.py b/ansible_collections/cisco/dnac/plugins/modules/http_write_credential.py index 2db38bb61..611f40716 100644 --- a/ansible_collections/cisco/dnac/plugins/modules/http_write_credential.py +++ b/ansible_collections/cisco/dnac/plugins/modules/http_write_credential.py @@ -48,8 +48,8 @@ options: description: Http Write Credential's username. type: str requirements: -- dnacentersdk >= 2.5.5 -- python >= 3.5 +- dnacentersdk >= 2.6.0 +- python >= 3.9 seealso: - name: Cisco DNA Center documentation for Discovery CreateHTTPWriteCredentials description: Complete reference of the CreateHTTPWriteCredentials API. diff --git a/ansible_collections/cisco/dnac/plugins/modules/integration_settings_instances_itsm.py b/ansible_collections/cisco/dnac/plugins/modules/integration_settings_instances_itsm.py index 1bc569d9f..86fa8bd76 100644 --- a/ansible_collections/cisco/dnac/plugins/modules/integration_settings_instances_itsm.py +++ b/ansible_collections/cisco/dnac/plugins/modules/integration_settings_instances_itsm.py @@ -48,8 +48,8 @@ options: description: Name of the setting instance. type: str requirements: -- dnacentersdk >= 2.5.5 -- python >= 3.5 +- dnacentersdk >= 2.6.0 +- python >= 3.9 seealso: - name: Cisco DNA Center documentation for ITSM Integration CreateITSMIntegrationSetting description: Complete reference of the CreateITSMIntegrationSetting API. diff --git a/ansible_collections/cisco/dnac/plugins/modules/integration_settings_instances_itsm_info.py b/ansible_collections/cisco/dnac/plugins/modules/integration_settings_instances_itsm_info.py index fc6a5de7a..0519f5e5a 100644 --- a/ansible_collections/cisco/dnac/plugins/modules/integration_settings_instances_itsm_info.py +++ b/ansible_collections/cisco/dnac/plugins/modules/integration_settings_instances_itsm_info.py @@ -24,8 +24,8 @@ options: - InstanceId path parameter. Instance Id of the Integration setting instance. type: str requirements: -- dnacentersdk >= 2.5.5 -- python >= 3.5 +- dnacentersdk >= 2.6.0 +- python >= 3.9 seealso: - name: Cisco DNA Center documentation for ITSM Integration GetITSMIntegrationSettingById description: Complete reference of the GetITSMIntegrationSettingById API. diff --git a/ansible_collections/cisco/dnac/plugins/modules/interface_info.py b/ansible_collections/cisco/dnac/plugins/modules/interface_info.py index 02d4dd14e..a6f0706ad 100644 --- a/ansible_collections/cisco/dnac/plugins/modules/interface_info.py +++ b/ansible_collections/cisco/dnac/plugins/modules/interface_info.py @@ -24,8 +24,8 @@ options: - InterfaceUuid path parameter. Interface ID. type: str requirements: -- dnacentersdk >= 2.5.5 -- python >= 3.5 +- dnacentersdk >= 2.6.0 +- python >= 3.9 seealso: - name: Cisco DNA Center documentation for Devices LegitOperationsForInterface description: Complete reference of the LegitOperationsForInterface API. diff --git a/ansible_collections/cisco/dnac/plugins/modules/interface_network_device_detail_info.py b/ansible_collections/cisco/dnac/plugins/modules/interface_network_device_detail_info.py index 344f22a2f..81a3203d6 100644 --- a/ansible_collections/cisco/dnac/plugins/modules/interface_network_device_detail_info.py +++ b/ansible_collections/cisco/dnac/plugins/modules/interface_network_device_detail_info.py @@ -28,8 +28,8 @@ options: - Name query parameter. Interface name. type: str requirements: -- dnacentersdk >= 2.5.5 -- python >= 3.5 +- dnacentersdk >= 2.6.0 +- python >= 3.9 seealso: - name: Cisco DNA Center documentation for Devices GetInterfaceDetailsByDeviceIdAndInterfaceName description: Complete reference of the GetInterfaceDetailsByDeviceIdAndInterfaceName API. diff --git a/ansible_collections/cisco/dnac/plugins/modules/interface_network_device_info.py b/ansible_collections/cisco/dnac/plugins/modules/interface_network_device_info.py index 8fdc0e226..62bb64e03 100644 --- a/ansible_collections/cisco/dnac/plugins/modules/interface_network_device_info.py +++ b/ansible_collections/cisco/dnac/plugins/modules/interface_network_device_info.py @@ -24,8 +24,8 @@ options: - DeviceId path parameter. Device ID. type: str requirements: -- dnacentersdk >= 2.5.5 -- python >= 3.5 +- dnacentersdk >= 2.6.0 +- python >= 3.9 seealso: - name: Cisco DNA Center documentation for Devices GetInterfaceInfoById description: Complete reference of the GetInterfaceInfoById API. diff --git a/ansible_collections/cisco/dnac/plugins/modules/interface_network_device_range_info.py b/ansible_collections/cisco/dnac/plugins/modules/interface_network_device_range_info.py index 0a3f1448b..2f2e3a6ea 100644 --- a/ansible_collections/cisco/dnac/plugins/modules/interface_network_device_range_info.py +++ b/ansible_collections/cisco/dnac/plugins/modules/interface_network_device_range_info.py @@ -32,8 +32,8 @@ options: - RecordsToReturn path parameter. Number of records to return. type: int requirements: -- dnacentersdk >= 2.5.5 -- python >= 3.5 +- dnacentersdk >= 2.6.0 +- python >= 3.9 seealso: - name: Cisco DNA Center documentation for Devices GetDeviceInterfacesBySpecifiedRange description: Complete reference of the GetDeviceInterfacesBySpecifiedRange API. diff --git a/ansible_collections/cisco/dnac/plugins/modules/interface_operation_create.py b/ansible_collections/cisco/dnac/plugins/modules/interface_operation_create.py index 98995c1dc..1bc065c31 100644 --- a/ansible_collections/cisco/dnac/plugins/modules/interface_operation_create.py +++ b/ansible_collections/cisco/dnac/plugins/modules/interface_operation_create.py @@ -33,8 +33,8 @@ options: description: Payload. type: dict requirements: -- dnacentersdk >= 2.5.5 -- python >= 3.5 +- dnacentersdk >= 2.6.0 +- python >= 3.9 seealso: - name: Cisco DNA Center documentation for Devices ClearMacAddressTable description: Complete reference of the ClearMacAddressTable API. diff --git a/ansible_collections/cisco/dnac/plugins/modules/interface_update.py b/ansible_collections/cisco/dnac/plugins/modules/interface_update.py index 20d7435e4..261703d48 100644 --- a/ansible_collections/cisco/dnac/plugins/modules/interface_update.py +++ b/ansible_collections/cisco/dnac/plugins/modules/interface_update.py @@ -39,8 +39,8 @@ options: description: Voice Vlan Id. type: int requirements: -- dnacentersdk >= 2.5.5 -- python >= 3.5 +- dnacentersdk >= 2.6.0 +- python >= 3.9 seealso: - name: Cisco DNA Center documentation for Devices UpdateInterfaceDetails description: Complete reference of the UpdateInterfaceDetails API. diff --git a/ansible_collections/cisco/dnac/plugins/modules/inventory_intent.py b/ansible_collections/cisco/dnac/plugins/modules/inventory_intent.py index 675c11c91..af2572486 100644 --- a/ansible_collections/cisco/dnac/plugins/modules/inventory_intent.py +++ b/ansible_collections/cisco/dnac/plugins/modules/inventory_intent.py @@ -307,8 +307,8 @@ options: version_added: 6.12.0 requirements: -- dnacentersdk >= 2.5.5 -- python >= 3.5 +- dnacentersdk >= 2.6.0 +- python >= 3.9 seealso: - name: Cisco Catalyst Center documentation for Devices AddDevice2 description: Complete reference of the AddDevice2 API. @@ -522,7 +522,7 @@ EXAMPLES = r""" - device_ip: "1.1.1.1" site_name: "Global/USA/San Francisco/BGL_18/floor_pnp" resync_retry_count: 200 - resync_interval: 2 + resync_retry_interval: 2 - device_ip: "2.2.2.2" site_name: "Global/USA/San Francisco/BGL_18/floor_test" resync_retry_count: 200 @@ -913,6 +913,7 @@ class DnacDevice(DnacBase): response = self.dnac._exec( family="devices", function='get_all_user_defined_fields', + op_modifies=True, params={"name": field_name}, ) @@ -943,6 +944,7 @@ class DnacDevice(DnacBase): response = self.dnac._exec( family="devices", function='create_user_defined_field', + op_modifies=True, params=udf, ) self.log("Received API response from 'create_user_defined_field': {0}".format(str(response)), "DEBUG") @@ -986,6 +988,7 @@ class DnacDevice(DnacBase): response = self.dnac._exec( family="devices", function='add_user_defined_field_to_device', + op_modifies=True, params=udf_param_dict, ) self.log("Received API response from 'add_user_defined_field_to_device': {0}".format(str(response)), "DEBUG") @@ -1226,6 +1229,7 @@ class DnacDevice(DnacBase): response = self.dnac._exec( family="devices", function='get_device_list', + op_modifies=True, params={"managementIpAddress": device_ip} ) response = response.get('response', []) @@ -1360,6 +1364,7 @@ class DnacDevice(DnacBase): response = self.dnac._exec( family="devices", function='get_device_list', + op_modifies=True, params={"managementIpAddress": device_ip} ) response = response.get('response') @@ -1905,6 +1910,7 @@ class DnacDevice(DnacBase): response = self.dnac._exec( family="devices", function='get_all_user_defined_fields', + op_modifies=True, params={"name": field_name}, ) self.log("Received API response from 'get_all_user_defined_fields': {0}".format(str(response)), "DEBUG") @@ -1918,11 +1924,12 @@ class DnacDevice(DnacBase): return udf_id - def mandatory_parameter(self): + def mandatory_parameter(self, device_to_add_in_ccc): """ Check for and validate mandatory parameters for adding network devices in Cisco Catalyst Center. Parameters: self (object): An instance of a class used for interacting with Cisco Cisco Catalyst Center. + device_to_add_in_ccc(list): List to device ip addresses to be added in Cisco Catalyst Center. Returns: dict: The input `config` dictionary if all mandatory parameters are present. Description: @@ -1947,12 +1954,12 @@ class DnacDevice(DnacBase): if mandatory_params_absent: self.status = "failed" - self.msg = "Required parameters {0} for adding devices are not present".format(str(mandatory_params_absent)) + self.msg = "Required parameters {0} for adding devices '{1}' are not present".format(str(mandatory_params_absent), str(device_to_add_in_ccc)) self.result['msg'] = self.msg self.log(self.msg, "ERROR") else: self.status = "success" - self.msg = "Required parameter for Adding the devices in Inventory are present." + self.msg = "Required parameters for adding the devices '{0}' to inventory are present.".format(str(device_to_add_in_ccc)) self.log(self.msg, "INFO") return self @@ -2091,6 +2098,7 @@ class DnacDevice(DnacBase): response = self.dnac._exec( family="devices", function='get_device_list', + op_modifies=True, params={"managementIpAddress": device_ip} ) @@ -2127,6 +2135,7 @@ class DnacDevice(DnacBase): response = self.dnac._exec( family="devices", function='get_device_list', + op_modifies=True, params={"hostname": hostname} ) if response: @@ -2161,6 +2170,7 @@ class DnacDevice(DnacBase): response = self.dnac._exec( family="devices", function='get_device_list', + op_modifies=True, params={"serialNumber": serial_number} ) if response: @@ -2195,6 +2205,7 @@ class DnacDevice(DnacBase): response = self.dnac._exec( family="devices", function='get_device_list', + op_modifies=True, params={"macAddress": mac_address} ) if response: @@ -2233,6 +2244,7 @@ class DnacDevice(DnacBase): response = self.dnac._exec( family="devices", function='get_interface_details', + op_modifies=True, params=interface_detail_params ) self.log("Received API response from 'get_interface_details': {0}".format(str(response)), "DEBUG") @@ -2246,44 +2258,44 @@ class DnacDevice(DnacBase): return interface_id except Exception as e: - error_message = "Error while fetching interface id for interface({0}) from Cisco Catalyst Center: {1}".format(interface_name, str(e)) - self.log(error_message, "ERROR") - self.msg = error_message self.status = "failed" + self.msg = "Failed to retrieve interface ID for interface({0}) from Cisco Catalyst Center: {1}".format(interface_name, str(e)) + self.log(self.msg, "ERROR") return self - def get_interface_from_ip(self, device_ip): - """ - Get the interface ID for a device in Cisco Catalyst Center based on its IP address. - Parameters: - self (object): An instance of a class used for interacting with Cisco Catalyst Center. - device_ip (str): The IP address of the device. - Returns: - str: The interface ID for the specified device. - Description: - The function sends a request to Cisco Catalyst Center to retrieve the interface information - for the device with the provided IP address and extracts the interface ID from the - response, and returns the interface ID. - """ + def get_interface_from_ip(self, device_ip): + """ + Get the interface ID for a device in Cisco Catalyst Center based on its IP address. + Parameters: + self (object): An instance of a class used for interacting with Cisco Catalyst Center. + device_ip (str): The IP address of the device. + Returns: + str: The interface ID for the specified device. + Description: + The function sends a request to Cisco Catalyst Center to retrieve the interface information + for the device with the provided IP address and extracts the interface ID from the + response, and returns the interface ID. + """ - try: - response = self.dnac._exec( - family="devices", - function='get_interface_by_ip', - params={"ip_address": device_ip} - ) - self.log("Received API response from 'get_interface_by_ip': {0}".format(str(response)), "DEBUG") - response = response.get("response") + try: + response = self.dnac._exec( + family="devices", + function='get_interface_by_ip', + op_modifies=True, + params={"ip_address": device_ip} + ) + self.log("Received API response from 'get_interface_by_ip': {0}".format(str(response)), "DEBUG") + response = response.get("response") - if response: - interface_id = response[0]["id"] - self.log("Fetch Interface Id for device '{0}' successfully !!".format(device_ip)) - return interface_id + if response: + interface_id = response[0]["id"] + self.log("Successfully retrieved Interface Id '{0}' for device '{1}'.".format(interface_id, device_ip), "DEBUG") + return interface_id - except Exception as e: - error_message = "Error while fetching Interface Id for device '{0}' from Cisco Catalyst Center: {1}".format(device_ip, str(e)) - self.log(error_message, "ERROR") - raise Exception(error_message) + except Exception as e: + error_message = "Error while fetching Interface Id for device '{0}' from Cisco Catalyst Center: {1}".format(device_ip, str(e)) + self.log(error_message, "ERROR") + raise Exception(error_message) def get_device_response(self, device_ip): """ @@ -2302,6 +2314,7 @@ class DnacDevice(DnacBase): response = self.dnac._exec( family="devices", function='get_device_list', + op_modifies=True, params={"managementIpAddress": device_ip} ) response = response.get('response')[0] @@ -2360,6 +2373,7 @@ class DnacDevice(DnacBase): response = self.dnac._exec( family="devices", function='get_interface_details', + op_modifies=True, params=interface_detail_params ) self.log("Received API response from 'get_interface_details': {0}".format(str(response)), "DEBUG") @@ -2555,12 +2569,23 @@ class DnacDevice(DnacBase): """ # Call the Get interface details by device IP API and fetch the interface Id + is_update_occurred = False + response_list = [] for device_ip in device_to_update: interface_params = self.config[0].get('update_interface_details') interface_names_list = interface_params.get('interface_name') for interface_name in interface_names_list: device_id = self.get_device_ids([device_ip]) - interface_id = self.get_interface_from_id_and_name(device_id[0], interface_name) + interface_details = self.get_interface_from_id_and_name(device_id[0], interface_name) + # Check if interface_details is None or does not contain the 'id' key. + if interface_details is None or not interface_details.get('id'): + self.status = "failed" + self.msg = """Failed to retrieve interface details or the 'id' is missing for the device with identifier + '{0}' and interface '{1}'""".format(device_id[0], interface_name) + self.log(self.msg, "WARNING") + return self + + interface_id = interface_details['id'] self.check_return_status() # Now we call update interface details api with required parameter @@ -2574,11 +2599,11 @@ class DnacDevice(DnacBase): if response.get('role').upper() != "ACCESS": self.msg = "The action to clear the MAC Address table is only supported for devices with the ACCESS role." self.log(self.msg, "WARNING") - self.result['response'] = self.msg + response_list.append(self.msg) + self.result['changed'] = False else: deploy_mode = interface_params.get('deployment_mode', 'Deploy') - self.clear_mac_address(interface_id, deploy_mode, interface_name) - self.check_return_status() + self.clear_mac_address(interface_id, deploy_mode, interface_name).check_return_status() temp_params = { 'description': interface_params.get('description', ''), @@ -2591,6 +2616,25 @@ class DnacDevice(DnacBase): if value is not None: payload_params[key] = value + # Check if interface need update or not here + interface_needs_update = False + for key, value in payload_params.items(): + if key == "voiceVlanId": + if str(value) != interface_details['voiceVlan']: + interface_needs_update = True + else: + if str(value) != str(interface_details.get(key)): + interface_needs_update = True + + if not interface_needs_update: + self.status = "success" + self.result['changed'] = False + self.msg = """Interface details for the given interface '{0}' are already updated in the Cisco Catalyst Center for the + device '{1}'.""".format(interface_name, device_ip) + self.log(self.msg, "INFO") + self.result['response'] = self.msg + continue + update_interface_params = { 'payload': payload_params, 'interface_uuid': interface_id, @@ -2605,16 +2649,23 @@ class DnacDevice(DnacBase): self.log("Received API response from 'update_interface_details': {0}".format(str(response)), "DEBUG") if response and isinstance(response, dict): - task_id = response.get('response').get('taskId') + response = response.get('response') + if not response: + self.status = "failed" + self.msg = "Failed to update the interface because the 'update_interface_details' API returned an empty response." + self.log(self.msg, "ERROR") + continue + + task_id = response.get('taskId') while True: execution_details = self.get_task_details(task_id) if 'SUCCESS' in execution_details.get("progress"): self.status = "success" - self.result['changed'] = True - self.result['response'] = execution_details - self.msg = "Updated Interface Details for device '{0}' successfully".format(device_ip) + is_update_occurred = True + self.msg = "Successfully updated the Interface Details for device '{0}'.".format(device_ip) + response_list.append(self.msg) self.log(self.msg, "INFO") break elif execution_details.get("isError"): @@ -2634,6 +2685,10 @@ class DnacDevice(DnacBase): self.result['changed'] = False self.msg = "Port actions are only supported on user facing/access ports as it's not allowed or No Updation required" self.log(self.msg, "INFO") + response_list.append(self.msg) + + self.result['changed'] = is_update_occurred + self.result['response'] = response_list return self @@ -2711,8 +2766,8 @@ class DnacDevice(DnacBase): elif execution_details.get("endTime"): self.status = "success" self.result['changed'] = True - self.result['response'] = execution_details self.msg = "Device '{0}' present in Cisco Catalyst Center and have been updated successfully".format(device_ip) + self.result['response'] = self.msg self.log(self.msg, "INFO") break @@ -2737,6 +2792,7 @@ class DnacDevice(DnacBase): response = self.dnac._exec( family="devices", function='get_device_list', + op_modifies=True, params={"managementIpAddress": device_ip} ) response = response.get('response') @@ -2924,7 +2980,8 @@ class DnacDevice(DnacBase): device_params.pop('snmpPrivPassphrase', None) device_params.pop('snmpPrivProtocol', None) - self.mandatory_parameter().check_return_status() + device_to_add_in_ccc = device_params['ipAddress'] + self.mandatory_parameter(device_to_add_in_ccc).check_return_status() try: response = self.dnac._exec( family="devices", @@ -2982,6 +3039,7 @@ class DnacDevice(DnacBase): response = self.dnac._exec( family="devices", function='get_device_list', + op_modifies=True, params={"managementIpAddress": device_ip} ) response = response.get('response')[0] @@ -3161,6 +3219,15 @@ class DnacDevice(DnacBase): if not playbook_params['snmpROCommunity']: playbook_params['snmpROCommunity'] = device_data.get('snmp_community', None) + if not playbook_params['snmpRWCommunity']: + playbook_params['snmpRWCommunity'] = device_data.get('snmp_write_community', None) + + if not playbook_params['httpUserName']: + playbook_params['httpUserName'] = device_data.get('http_config_username', None) + if not playbook_params['httpPassword']: + playbook_params['httpPassword'] = device_data.get('http_config_password', None) + if not playbook_params['httpPort']: + playbook_params['httpPort'] = device_data.get('http_port', None) try: if playbook_params['updateMgmtIPaddressList']: @@ -3306,6 +3373,7 @@ class DnacDevice(DnacBase): response = self.dnac._exec( family="devices", function='delete_user_defined_field', + op_modifies=True, params={"id": udf_id}, ) if response and isinstance(response, dict): @@ -3356,6 +3424,7 @@ class DnacDevice(DnacBase): prov_respone = self.dnac._exec( family="sda", function='get_provisioned_wired_device', + op_modifies=True, params=provision_params, ) @@ -3363,6 +3432,7 @@ class DnacDevice(DnacBase): response = self.dnac._exec( family="sda", function='delete_provisioned_wired_device', + op_modifies=True, params=provision_params, ) executionid = response.get("executionId") @@ -3389,6 +3459,7 @@ class DnacDevice(DnacBase): response = self.dnac._exec( family="devices", function='delete_device_by_id', + op_modifies=True, params=delete_params, ) diff --git a/ansible_collections/cisco/dnac/plugins/modules/inventory_workflow_manager.py b/ansible_collections/cisco/dnac/plugins/modules/inventory_workflow_manager.py index 3eda0e2cc..17f63f475 100644 --- a/ansible_collections/cisco/dnac/plugins/modules/inventory_workflow_manager.py +++ b/ansible_collections/cisco/dnac/plugins/modules/inventory_workflow_manager.py @@ -307,8 +307,8 @@ options: version_added: 6.12.0 requirements: -- dnacentersdk >= 2.5.5 -- python >= 3.5 +- dnacentersdk >= 2.6.0 +- python >= 3.9 seealso: - name: Cisco Catalyst Center documentation for Devices AddDevice2 description: Complete reference of the AddDevice2 API. @@ -522,7 +522,7 @@ EXAMPLES = r""" - device_ip: "1.1.1.1" site_name: "Global/USA/San Francisco/BGL_18/floor_pnp" resync_retry_count: 200 - resync_interval: 2 + resync_retry_interval: 2 - device_ip: "2.2.2.2" site_name: "Global/USA/San Francisco/BGL_18/floor_test" resync_retry_count: 200 @@ -752,7 +752,7 @@ class Inventory(DnacBase): 'mac_address_list': {'type': 'list', 'elements': 'str'}, 'netconf_port': {'type': 'str'}, 'password': {'type': 'str'}, - 'serial_number': {'type': 'str'}, + 'serial_number_list': {'type': 'list', 'elements': 'str'}, 'snmp_auth_passphrase': {'type': 'str'}, 'snmp_auth_protocol': {'default': "SHA", 'type': 'str'}, 'snmp_mode': {'type': 'str'}, @@ -912,6 +912,7 @@ class Inventory(DnacBase): response = self.dnac._exec( family="devices", function='get_all_user_defined_fields', + op_modifies=True, params={"name": field_name}, ) @@ -942,6 +943,7 @@ class Inventory(DnacBase): response = self.dnac._exec( family="devices", function='create_user_defined_field', + op_modifies=True, params=udf, ) self.log("Received API response from 'create_user_defined_field': {0}".format(str(response)), "DEBUG") @@ -984,6 +986,7 @@ class Inventory(DnacBase): response = self.dnac._exec( family="devices", function='add_user_defined_field_to_device', + op_modifies=True, params=udf_param_dict, ) self.log("Received API response from 'add_user_defined_field_to_device': {0}".format(str(response)), "DEBUG") @@ -1224,6 +1227,7 @@ class Inventory(DnacBase): response = self.dnac._exec( family="devices", function='get_device_list', + op_modifies=True, params={"managementIpAddress": device_ip} ) response = response.get('response', []) @@ -1358,6 +1362,7 @@ class Inventory(DnacBase): response = self.dnac._exec( family="devices", function='get_device_list', + op_modifies=True, params={"managementIpAddress": device_ip} ) response = response.get('response') @@ -1897,6 +1902,7 @@ class Inventory(DnacBase): response = self.dnac._exec( family="devices", function='get_all_user_defined_fields', + op_modifies=True, params={"name": field_name}, ) self.log("Received API response from 'get_all_user_defined_fields': {0}".format(str(response)), "DEBUG") @@ -1910,11 +1916,12 @@ class Inventory(DnacBase): return udf_id - def mandatory_parameter(self): + def mandatory_parameter(self, device_to_add_in_ccc): """ Check for and validate mandatory parameters for adding network devices in Cisco Catalyst Center. Parameters: self (object): An instance of a class used for interacting with Cisco Cisco Catalyst Center. + device_to_add_in_ccc(list): List to device ip addresses to be added in Cisco Catalyst Center. Returns: dict: The input `config` dictionary if all mandatory parameters are present. Description: @@ -1939,12 +1946,12 @@ class Inventory(DnacBase): if mandatory_params_absent: self.status = "failed" - self.msg = "Required parameters {0} for adding devices are not present".format(str(mandatory_params_absent)) + self.msg = "Required parameters {0} for adding devices '{1}' are not present".format(str(mandatory_params_absent), str(device_to_add_in_ccc)) self.result['msg'] = self.msg self.log(self.msg, "ERROR") else: self.status = "success" - self.msg = "Required parameter for Adding the devices in Inventory are present." + self.msg = "Required parameters for adding the devices '{0}' to inventory are present.".format(str(device_to_add_in_ccc)) self.log(self.msg, "INFO") return self @@ -2044,7 +2051,6 @@ class Inventory(DnacBase): "httpSecure": params.get("http_secure"), "httpUserName": params.get("http_username"), "netconfPort": params.get("netconf_port"), - "serialNumber": params.get("serial_number"), "snmpVersion": params.get("snmp_version"), "type": params.get("type"), "updateMgmtIPaddressList": params.get("update_mgmt_ipaddresslist"), @@ -2084,6 +2090,7 @@ class Inventory(DnacBase): response = self.dnac._exec( family="devices", function='get_device_list', + op_modifies=True, params={"managementIpAddress": device_ip} ) @@ -2120,6 +2127,7 @@ class Inventory(DnacBase): response = self.dnac._exec( family="devices", function='get_device_list', + op_modifies=True, params={"hostname": hostname} ) if response: @@ -2154,6 +2162,7 @@ class Inventory(DnacBase): response = self.dnac._exec( family="devices", function='get_device_list', + op_modifies=True, params={"serialNumber": serial_number} ) if response: @@ -2188,6 +2197,7 @@ class Inventory(DnacBase): response = self.dnac._exec( family="devices", function='get_device_list', + op_modifies=True, params={"macAddress": mac_address} ) if response: @@ -2226,6 +2236,7 @@ class Inventory(DnacBase): response = self.dnac._exec( family="devices", function='get_interface_details', + op_modifies=True, params=interface_detail_params ) self.log("Received API response from 'get_interface_details': {0}".format(str(response)), "DEBUG") @@ -2236,47 +2247,47 @@ class Inventory(DnacBase): interface_id = response["id"] self.log("""Successfully fetched interface ID ({0}) by using device id {1} and interface name {2}.""" .format(interface_id, device_id, interface_name), "INFO") - return interface_id + return response except Exception as e: - error_message = "Error while fetching interface id for interface({0}) from Cisco Catalyst Center: {1}".format(interface_name, str(e)) - self.log(error_message, "ERROR") - self.msg = error_message self.status = "failed" + self.msg = "Failed to retrieve interface ID for interface({0}) from Cisco Catalyst Center: {1}".format(interface_name, str(e)) + self.log(self.msg, "ERROR") return self - def get_interface_from_ip(self, device_ip): - """ - Get the interface ID for a device in Cisco Catalyst Center based on its IP address. - Parameters: - self (object): An instance of a class used for interacting with Cisco Catalyst Center. - device_ip (str): The IP address of the device. - Returns: - str: The interface ID for the specified device. - Description: - The function sends a request to Cisco Catalyst Center to retrieve the interface information - for the device with the provided IP address and extracts the interface ID from the - response, and returns the interface ID. - """ + def get_interface_from_ip(self, device_ip): + """ + Get the interface ID for a device in Cisco Catalyst Center based on its IP address. + Parameters: + self (object): An instance of a class used for interacting with Cisco Catalyst Center. + device_ip (str): The IP address of the device. + Returns: + str: The interface ID for the specified device. + Description: + The function sends a request to Cisco Catalyst Center to retrieve the interface information + for the device with the provided IP address and extracts the interface ID from the + response, and returns the interface ID. + """ - try: - response = self.dnac._exec( - family="devices", - function='get_interface_by_ip', - params={"ip_address": device_ip} - ) - self.log("Received API response from 'get_interface_by_ip': {0}".format(str(response)), "DEBUG") - response = response.get("response") + try: + response = self.dnac._exec( + family="devices", + function='get_interface_by_ip', + op_modifies=True, + params={"ip_address": device_ip} + ) + self.log("Received API response from 'get_interface_by_ip': {0}".format(str(response)), "DEBUG") + response = response.get("response") - if response: - interface_id = response[0]["id"] - self.log("Fetch Interface Id for device '{0}' successfully !!".format(device_ip)) - return interface_id + if response: + interface_id = response[0]["id"] + self.log("Successfully retrieved Interface Id '{0}' for device '{1}'.".format(interface_id, device_ip), "DEBUG") + return interface_id - except Exception as e: - error_message = "Error while fetching Interface Id for device '{0}' from Cisco Catalyst Center: {1}".format(device_ip, str(e)) - self.log(error_message, "ERROR") - raise Exception(error_message) + except Exception as e: + error_message = "Error while fetching Interface Id for device '{0}' from Cisco Catalyst Center: {1}".format(device_ip, str(e)) + self.log(error_message, "ERROR") + raise Exception(error_message) def get_device_response(self, device_ip): """ @@ -2295,6 +2306,7 @@ class Inventory(DnacBase): response = self.dnac._exec( family="devices", function='get_device_list', + op_modifies=True, params={"managementIpAddress": device_ip} ) response = response.get('response')[0] @@ -2353,6 +2365,7 @@ class Inventory(DnacBase): response = self.dnac._exec( family="devices", function='get_interface_details', + op_modifies=True, params=interface_detail_params ) self.log("Received API response from 'get_interface_details': {0}".format(str(response)), "DEBUG") @@ -2548,12 +2561,23 @@ class Inventory(DnacBase): """ # Call the Get interface details by device IP API and fetch the interface Id + is_update_occurred = False + response_list = [] for device_ip in device_to_update: interface_params = self.config[0].get('update_interface_details') interface_names_list = interface_params.get('interface_name') for interface_name in interface_names_list: device_id = self.get_device_ids([device_ip]) - interface_id = self.get_interface_from_id_and_name(device_id[0], interface_name) + interface_details = self.get_interface_from_id_and_name(device_id[0], interface_name) + # Check if interface_details is None or does not contain the 'id' key. + if interface_details is None or not interface_details.get('id'): + self.status = "failed" + self.msg = """Failed to retrieve interface details or the 'id' is missing for the device with identifier + '{0}' and interface '{1}'""".format(device_id[0], interface_name) + self.log(self.msg, "WARNING") + return self + + interface_id = interface_details['id'] self.check_return_status() # Now we call update interface details api with required parameter @@ -2567,11 +2591,11 @@ class Inventory(DnacBase): if response.get('role').upper() != "ACCESS": self.msg = "The action to clear the MAC Address table is only supported for devices with the ACCESS role." self.log(self.msg, "WARNING") - self.result['response'] = self.msg + response_list.append(self.msg) + self.result['changed'] = False else: deploy_mode = interface_params.get('deployment_mode', 'Deploy') - self.clear_mac_address(interface_id, deploy_mode, interface_name) - self.check_return_status() + self.clear_mac_address(interface_id, deploy_mode, interface_name).check_return_status() temp_params = { 'description': interface_params.get('description', ''), @@ -2584,6 +2608,25 @@ class Inventory(DnacBase): if value is not None: payload_params[key] = value + # Check if interface need update or not here + interface_needs_update = False + for key, value in payload_params.items(): + if key == "voiceVlanId": + if str(value) != interface_details['voiceVlan']: + interface_needs_update = True + else: + if str(value) != str(interface_details.get(key)): + interface_needs_update = True + + if not interface_needs_update: + self.status = "success" + self.result['changed'] = False + self.msg = """Interface details for the given interface '{0}' are already updated in the Cisco Catalyst Center for the + device '{1}'.""".format(interface_name, device_ip) + self.log(self.msg, "INFO") + response_list.append(self.msg) + continue + update_interface_params = { 'payload': payload_params, 'interface_uuid': interface_id, @@ -2598,16 +2641,23 @@ class Inventory(DnacBase): self.log("Received API response from 'update_interface_details': {0}".format(str(response)), "DEBUG") if response and isinstance(response, dict): - task_id = response.get('response').get('taskId') + response = response.get('response') + if not response: + self.status = "failed" + self.msg = "Failed to update the interface because the 'update_interface_details' API returned an empty response." + self.log(self.msg, "ERROR") + continue + + task_id = response.get('taskId') while True: execution_details = self.get_task_details(task_id) if 'SUCCESS' in execution_details.get("progress"): self.status = "success" - self.result['changed'] = True - self.result['response'] = execution_details - self.msg = "Updated Interface Details for device '{0}' successfully".format(device_ip) + is_update_occurred = True + self.msg = "Successfully updated the Interface Details for device '{0}'.".format(device_ip) + response_list.append(self.msg) self.log(self.msg, "INFO") break elif execution_details.get("isError"): @@ -2627,6 +2677,10 @@ class Inventory(DnacBase): self.result['changed'] = False self.msg = "Port actions are only supported on user facing/access ports as it's not allowed or No Updation required" self.log(self.msg, "INFO") + response_list.append(self.msg) + + self.result['changed'] = is_update_occurred + self.result['response'] = response_list return self @@ -2704,8 +2758,8 @@ class Inventory(DnacBase): elif execution_details.get("endTime"): self.status = "success" self.result['changed'] = True - self.result['response'] = execution_details self.msg = "Device '{0}' present in Cisco Catalyst Center and have been updated successfully".format(device_ip) + self.result['response'] = self.msg self.log(self.msg, "INFO") break @@ -2730,6 +2784,7 @@ class Inventory(DnacBase): response = self.dnac._exec( family="devices", function='get_device_list', + op_modifies=True, params={"managementIpAddress": device_ip} ) response = response.get('response') @@ -2916,7 +2971,8 @@ class Inventory(DnacBase): device_params.pop('snmpPrivPassphrase', None) device_params.pop('snmpPrivProtocol', None) - self.mandatory_parameter().check_return_status() + device_to_add_in_ccc = device_params['ipAddress'] + self.mandatory_parameter(device_to_add_in_ccc).check_return_status() try: response = self.dnac._exec( family="devices", @@ -2974,6 +3030,7 @@ class Inventory(DnacBase): response = self.dnac._exec( family="devices", function='get_device_list', + op_modifies=True, params={"managementIpAddress": device_ip} ) response = response.get('response')[0] @@ -3154,6 +3211,15 @@ class Inventory(DnacBase): if not playbook_params['snmpROCommunity']: playbook_params['snmpROCommunity'] = device_data.get('snmp_community', None) + if not playbook_params['snmpRWCommunity']: + playbook_params['snmpRWCommunity'] = device_data.get('snmp_write_community', None) + + if not playbook_params['httpUserName']: + playbook_params['httpUserName'] = device_data.get('http_config_username', None) + if not playbook_params['httpPassword']: + playbook_params['httpPassword'] = device_data.get('http_config_password', None) + if not playbook_params['httpPort']: + playbook_params['httpPort'] = device_data.get('http_port', None) try: if playbook_params['updateMgmtIPaddressList']: @@ -3299,6 +3365,7 @@ class Inventory(DnacBase): response = self.dnac._exec( family="devices", function='delete_user_defined_field', + op_modifies=True, params={"id": udf_id}, ) if response and isinstance(response, dict): @@ -3349,6 +3416,7 @@ class Inventory(DnacBase): prov_respone = self.dnac._exec( family="sda", function='get_provisioned_wired_device', + op_modifies=True, params=provision_params, ) @@ -3356,6 +3424,7 @@ class Inventory(DnacBase): response = self.dnac._exec( family="sda", function='delete_provisioned_wired_device', + op_modifies=True, params=provision_params, ) executionid = response.get("executionId") @@ -3383,6 +3452,7 @@ class Inventory(DnacBase): response = self.dnac._exec( family="devices", function='delete_device_by_id', + op_modifies=True, params=delete_params, ) diff --git a/ansible_collections/cisco/dnac/plugins/modules/issues_enrichment_details_info.py b/ansible_collections/cisco/dnac/plugins/modules/issues_enrichment_details_info.py index e81d3f2d9..58d5c787c 100644 --- a/ansible_collections/cisco/dnac/plugins/modules/issues_enrichment_details_info.py +++ b/ansible_collections/cisco/dnac/plugins/modules/issues_enrichment_details_info.py @@ -22,8 +22,8 @@ options: description: Additional headers. type: dict requirements: -- dnacentersdk >= 2.5.5 -- python >= 3.5 +- dnacentersdk >= 2.6.0 +- python >= 3.9 seealso: - name: Cisco DNA Center documentation for Issues GetIssueEnrichmentDetails description: Complete reference of the GetIssueEnrichmentDetails API. diff --git a/ansible_collections/cisco/dnac/plugins/modules/issues_info.py b/ansible_collections/cisco/dnac/plugins/modules/issues_info.py index b94e0f1cf..f6131d2b8 100644 --- a/ansible_collections/cisco/dnac/plugins/modules/issues_info.py +++ b/ansible_collections/cisco/dnac/plugins/modules/issues_info.py @@ -58,8 +58,8 @@ options: - IssueStatus query parameter. The issue's status value (One of ACTIVE, IGNORED, RESOLVED). type: str requirements: -- dnacentersdk >= 2.5.5 -- python >= 3.5 +- dnacentersdk >= 2.6.0 +- python >= 3.9 seealso: - name: Cisco DNA Center documentation for Issues Issues description: Complete reference of the Issues API. diff --git a/ansible_collections/cisco/dnac/plugins/modules/itsm_cmdb_sync_status_info.py b/ansible_collections/cisco/dnac/plugins/modules/itsm_cmdb_sync_status_info.py index ba5721124..2b3a47ea2 100644 --- a/ansible_collections/cisco/dnac/plugins/modules/itsm_cmdb_sync_status_info.py +++ b/ansible_collections/cisco/dnac/plugins/modules/itsm_cmdb_sync_status_info.py @@ -34,8 +34,8 @@ options: - Date query parameter. Provide date in "YYYY-MM-DD" format. type: str requirements: -- dnacentersdk >= 2.5.5 -- python >= 3.5 +- dnacentersdk >= 2.6.0 +- python >= 3.9 seealso: - name: Cisco DNA Center documentation for ITSM GetCMDBSyncStatus description: Complete reference of the GetCMDBSyncStatus API. diff --git a/ansible_collections/cisco/dnac/plugins/modules/itsm_integration_events_failed_info.py b/ansible_collections/cisco/dnac/plugins/modules/itsm_integration_events_failed_info.py index b02e8dc1d..c2a6dca63 100644 --- a/ansible_collections/cisco/dnac/plugins/modules/itsm_integration_events_failed_info.py +++ b/ansible_collections/cisco/dnac/plugins/modules/itsm_integration_events_failed_info.py @@ -24,8 +24,8 @@ options: - InstanceId query parameter. Instance Id of the failed event as in the Runtime Dashboard. type: str requirements: -- dnacentersdk >= 2.5.5 -- python >= 3.5 +- dnacentersdk >= 2.6.0 +- python >= 3.9 seealso: - name: Cisco DNA Center documentation for ITSM GetFailedITSMEvents description: Complete reference of the GetFailedITSMEvents API. diff --git a/ansible_collections/cisco/dnac/plugins/modules/itsm_integration_events_retry.py b/ansible_collections/cisco/dnac/plugins/modules/itsm_integration_events_retry.py index 201f6891d..64c97fe80 100644 --- a/ansible_collections/cisco/dnac/plugins/modules/itsm_integration_events_retry.py +++ b/ansible_collections/cisco/dnac/plugins/modules/itsm_integration_events_retry.py @@ -24,8 +24,8 @@ options: elements: str type: list requirements: -- dnacentersdk >= 2.5.5 -- python >= 3.5 +- dnacentersdk >= 2.6.0 +- python >= 3.9 seealso: - name: Cisco DNA Center documentation for ITSM RetryIntegrationEvents description: Complete reference of the RetryIntegrationEvents API. diff --git a/ansible_collections/cisco/dnac/plugins/modules/lan_automation_count_info.py b/ansible_collections/cisco/dnac/plugins/modules/lan_automation_count_info.py index d172a752c..e275eaf2c 100644 --- a/ansible_collections/cisco/dnac/plugins/modules/lan_automation_count_info.py +++ b/ansible_collections/cisco/dnac/plugins/modules/lan_automation_count_info.py @@ -20,8 +20,8 @@ options: description: Additional headers. type: dict requirements: -- dnacentersdk >= 2.5.5 -- python >= 3.5 +- dnacentersdk >= 2.6.0 +- python >= 3.9 seealso: - name: Cisco DNA Center documentation for LAN Automation LANAutomationSessionCount description: Complete reference of the LANAutomationSessionCount API. diff --git a/ansible_collections/cisco/dnac/plugins/modules/lan_automation_create.py b/ansible_collections/cisco/dnac/plugins/modules/lan_automation_create.py index e87775b94..b9c04f38d 100644 --- a/ansible_collections/cisco/dnac/plugins/modules/lan_automation_create.py +++ b/ansible_collections/cisco/dnac/plugins/modules/lan_automation_create.py @@ -63,8 +63,8 @@ options: type: bool type: list requirements: -- dnacentersdk >= 2.5.5 -- python >= 3.5 +- dnacentersdk >= 2.6.0 +- python >= 3.9 seealso: - name: Cisco DNA Center documentation for LAN Automation LANAutomationStart description: Complete reference of the LANAutomationStart API. diff --git a/ansible_collections/cisco/dnac/plugins/modules/lan_automation_delete.py b/ansible_collections/cisco/dnac/plugins/modules/lan_automation_delete.py index d4a8a6651..d31484c67 100644 --- a/ansible_collections/cisco/dnac/plugins/modules/lan_automation_delete.py +++ b/ansible_collections/cisco/dnac/plugins/modules/lan_automation_delete.py @@ -20,8 +20,8 @@ options: description: Id path parameter. LAN Automation id can be obtained from /dna/intent/api/v1/lan-automation/status. type: str requirements: -- dnacentersdk >= 2.5.5 -- python >= 3.5 +- dnacentersdk >= 2.6.0 +- python >= 3.9 seealso: - name: Cisco DNA Center documentation for LAN Automation LANAutomationStop description: Complete reference of the LANAutomationStop API. diff --git a/ansible_collections/cisco/dnac/plugins/modules/lan_automation_log_by_serial_number_info.py b/ansible_collections/cisco/dnac/plugins/modules/lan_automation_log_by_serial_number_info.py index c81f24292..fa75bec89 100644 --- a/ansible_collections/cisco/dnac/plugins/modules/lan_automation_log_by_serial_number_info.py +++ b/ansible_collections/cisco/dnac/plugins/modules/lan_automation_log_by_serial_number_info.py @@ -37,8 +37,8 @@ options: the remaining logs, please leave the query parameter blank. type: str requirements: -- dnacentersdk >= 2.5.5 -- python >= 3.5 +- dnacentersdk >= 2.6.0 +- python >= 3.9 seealso: - name: Cisco DNA Center documentation for LAN Automation LANAutomationLogsForIndividualDevices description: Complete reference of the LANAutomationLogsForIndividualDevices API. diff --git a/ansible_collections/cisco/dnac/plugins/modules/lan_automation_log_info.py b/ansible_collections/cisco/dnac/plugins/modules/lan_automation_log_info.py index ede147df9..6a8aa1291 100644 --- a/ansible_collections/cisco/dnac/plugins/modules/lan_automation_log_info.py +++ b/ansible_collections/cisco/dnac/plugins/modules/lan_automation_log_info.py @@ -34,8 +34,8 @@ options: - Id path parameter. LAN Automation session identifier. type: str requirements: -- dnacentersdk >= 2.5.5 -- python >= 3.5 +- dnacentersdk >= 2.6.0 +- python >= 3.9 seealso: - name: Cisco DNA Center documentation for LAN Automation LANAutomationLog description: Complete reference of the LANAutomationLog API. diff --git a/ansible_collections/cisco/dnac/plugins/modules/lan_automation_status_info.py b/ansible_collections/cisco/dnac/plugins/modules/lan_automation_status_info.py index 62ad0a371..3680a97eb 100644 --- a/ansible_collections/cisco/dnac/plugins/modules/lan_automation_status_info.py +++ b/ansible_collections/cisco/dnac/plugins/modules/lan_automation_status_info.py @@ -34,8 +34,8 @@ options: - Id path parameter. LAN Automation session identifier. type: str requirements: -- dnacentersdk >= 2.5.5 -- python >= 3.5 +- dnacentersdk >= 2.6.0 +- python >= 3.9 seealso: - name: Cisco DNA Center documentation for LAN Automation LANAutomationStatus description: Complete reference of the LANAutomationStatus API. diff --git a/ansible_collections/cisco/dnac/plugins/modules/license_device_count_info.py b/ansible_collections/cisco/dnac/plugins/modules/license_device_count_info.py index efee0085a..0ec3976ac 100644 --- a/ansible_collections/cisco/dnac/plugins/modules/license_device_count_info.py +++ b/ansible_collections/cisco/dnac/plugins/modules/license_device_count_info.py @@ -40,8 +40,8 @@ options: - Smart_account_id query parameter. Smart account id. type: str requirements: -- dnacentersdk >= 2.5.5 -- python >= 3.5 +- dnacentersdk >= 2.6.0 +- python >= 3.9 seealso: - name: Cisco DNA Center documentation for Licenses DeviceCountDetails2 description: Complete reference of the DeviceCountDetails2 API. diff --git a/ansible_collections/cisco/dnac/plugins/modules/license_device_deregistration.py b/ansible_collections/cisco/dnac/plugins/modules/license_device_deregistration.py index aeceb3470..ddf70df11 100644 --- a/ansible_collections/cisco/dnac/plugins/modules/license_device_deregistration.py +++ b/ansible_collections/cisco/dnac/plugins/modules/license_device_deregistration.py @@ -21,8 +21,8 @@ options: elements: str type: list requirements: -- dnacentersdk >= 2.5.5 -- python >= 3.5 +- dnacentersdk >= 2.6.0 +- python >= 3.9 seealso: - name: Cisco DNA Center documentation for Licenses DeviceDeregistration2 description: Complete reference of the DeviceDeregistration2 API. diff --git a/ansible_collections/cisco/dnac/plugins/modules/license_device_license_details_info.py b/ansible_collections/cisco/dnac/plugins/modules/license_device_license_details_info.py index 5410196ca..965c577e3 100644 --- a/ansible_collections/cisco/dnac/plugins/modules/license_device_license_details_info.py +++ b/ansible_collections/cisco/dnac/plugins/modules/license_device_license_details_info.py @@ -24,8 +24,8 @@ options: - Device_uuid path parameter. Id of device. type: str requirements: -- dnacentersdk >= 2.5.5 -- python >= 3.5 +- dnacentersdk >= 2.6.0 +- python >= 3.9 seealso: - name: Cisco DNA Center documentation for Licenses DeviceLicenseDetails2 description: Complete reference of the DeviceLicenseDetails2 API. diff --git a/ansible_collections/cisco/dnac/plugins/modules/license_device_license_summary_info.py b/ansible_collections/cisco/dnac/plugins/modules/license_device_license_summary_info.py index ae872d095..c2806d39a 100644 --- a/ansible_collections/cisco/dnac/plugins/modules/license_device_license_summary_info.py +++ b/ansible_collections/cisco/dnac/plugins/modules/license_device_license_summary_info.py @@ -60,8 +60,8 @@ options: - Device_uuid query parameter. Id of device. type: str requirements: -- dnacentersdk >= 2.5.5 -- python >= 3.5 +- dnacentersdk >= 2.6.0 +- python >= 3.9 seealso: - name: Cisco DNA Center documentation for Licenses DeviceLicenseSummary2 description: Complete reference of the DeviceLicenseSummary2 API. diff --git a/ansible_collections/cisco/dnac/plugins/modules/license_device_registration.py b/ansible_collections/cisco/dnac/plugins/modules/license_device_registration.py index 6d7f5b955..de878f790 100644 --- a/ansible_collections/cisco/dnac/plugins/modules/license_device_registration.py +++ b/ansible_collections/cisco/dnac/plugins/modules/license_device_registration.py @@ -24,8 +24,8 @@ options: description: Virtual_account_name path parameter. Name of virtual account. type: str requirements: -- dnacentersdk >= 2.5.5 -- python >= 3.5 +- dnacentersdk >= 2.6.0 +- python >= 3.9 seealso: - name: Cisco DNA Center documentation for Licenses DeviceRegistration2 description: Complete reference of the DeviceRegistration2 API. diff --git a/ansible_collections/cisco/dnac/plugins/modules/license_smart_account_details_info.py b/ansible_collections/cisco/dnac/plugins/modules/license_smart_account_details_info.py index b70fa56c0..70685c2ed 100644 --- a/ansible_collections/cisco/dnac/plugins/modules/license_smart_account_details_info.py +++ b/ansible_collections/cisco/dnac/plugins/modules/license_smart_account_details_info.py @@ -20,8 +20,8 @@ options: description: Additional headers. type: dict requirements: -- dnacentersdk >= 2.5.5 -- python >= 3.5 +- dnacentersdk >= 2.6.0 +- python >= 3.9 seealso: - name: Cisco DNA Center documentation for Licenses SmartAccountDetails description: Complete reference of the SmartAccountDetails API. diff --git a/ansible_collections/cisco/dnac/plugins/modules/license_term_details_info.py b/ansible_collections/cisco/dnac/plugins/modules/license_term_details_info.py index bdf26471d..d0bf73d4d 100644 --- a/ansible_collections/cisco/dnac/plugins/modules/license_term_details_info.py +++ b/ansible_collections/cisco/dnac/plugins/modules/license_term_details_info.py @@ -34,8 +34,8 @@ options: - Device_type query parameter. Type of device like router, switch, wireless or ise. type: str requirements: -- dnacentersdk >= 2.5.5 -- python >= 3.5 +- dnacentersdk >= 2.6.0 +- python >= 3.9 seealso: - name: Cisco DNA Center documentation for Licenses LicenseTermDetails2 description: Complete reference of the LicenseTermDetails2 API. diff --git a/ansible_collections/cisco/dnac/plugins/modules/license_usage_details_info.py b/ansible_collections/cisco/dnac/plugins/modules/license_usage_details_info.py index d315848c9..3fd4d5466 100644 --- a/ansible_collections/cisco/dnac/plugins/modules/license_usage_details_info.py +++ b/ansible_collections/cisco/dnac/plugins/modules/license_usage_details_info.py @@ -34,8 +34,8 @@ options: - Device_type query parameter. Type of device like router, switch, wireless or ise. type: str requirements: -- dnacentersdk >= 2.5.5 -- python >= 3.5 +- dnacentersdk >= 2.6.0 +- python >= 3.9 seealso: - name: Cisco DNA Center documentation for Licenses LicenseUsageDetails2 description: Complete reference of the LicenseUsageDetails2 API. diff --git a/ansible_collections/cisco/dnac/plugins/modules/license_virtual_account_change.py b/ansible_collections/cisco/dnac/plugins/modules/license_virtual_account_change.py index 9e647aefc..762e01540 100644 --- a/ansible_collections/cisco/dnac/plugins/modules/license_virtual_account_change.py +++ b/ansible_collections/cisco/dnac/plugins/modules/license_virtual_account_change.py @@ -27,8 +27,8 @@ options: description: Virtual_account_name path parameter. Name of target virtual account. type: str requirements: -- dnacentersdk >= 2.5.5 -- python >= 3.5 +- dnacentersdk >= 2.6.0 +- python >= 3.9 seealso: - name: Cisco DNA Center documentation for Licenses ChangeVirtualAccount2 description: Complete reference of the ChangeVirtualAccount2 API. diff --git a/ansible_collections/cisco/dnac/plugins/modules/license_virtual_account_details_info.py b/ansible_collections/cisco/dnac/plugins/modules/license_virtual_account_details_info.py index 476f58758..72a2f1041 100644 --- a/ansible_collections/cisco/dnac/plugins/modules/license_virtual_account_details_info.py +++ b/ansible_collections/cisco/dnac/plugins/modules/license_virtual_account_details_info.py @@ -24,8 +24,8 @@ options: - Smart_account_id path parameter. Id of smart account. type: str requirements: -- dnacentersdk >= 2.5.5 -- python >= 3.5 +- dnacentersdk >= 2.6.0 +- python >= 3.9 seealso: - name: Cisco DNA Center documentation for Licenses VirtualAccountDetails2 description: Complete reference of the VirtualAccountDetails2 API. diff --git a/ansible_collections/cisco/dnac/plugins/modules/netconf_credential.py b/ansible_collections/cisco/dnac/plugins/modules/netconf_credential.py index a8cec0942..d75908aa6 100644 --- a/ansible_collections/cisco/dnac/plugins/modules/netconf_credential.py +++ b/ansible_collections/cisco/dnac/plugins/modules/netconf_credential.py @@ -39,8 +39,8 @@ options: description: Netconf Credential's netconfPort. type: str requirements: -- dnacentersdk >= 2.5.5 -- python >= 3.5 +- dnacentersdk >= 2.6.0 +- python >= 3.9 seealso: - name: Cisco DNA Center documentation for Discovery CreateNetconfCredentials description: Complete reference of the CreateNetconfCredentials API. diff --git a/ansible_collections/cisco/dnac/plugins/modules/network_create.py b/ansible_collections/cisco/dnac/plugins/modules/network_create.py index 9c7abda29..8bf553aba 100644 --- a/ansible_collections/cisco/dnac/plugins/modules/network_create.py +++ b/ansible_collections/cisco/dnac/plugins/modules/network_create.py @@ -134,8 +134,8 @@ options: the network settings. type: str requirements: -- dnacentersdk >= 2.5.5 -- python >= 3.5 +- dnacentersdk >= 2.6.0 +- python >= 3.9 seealso: - name: Cisco DNA Center documentation for Network Settings CreateNetwork description: Complete reference of the CreateNetwork API. diff --git a/ansible_collections/cisco/dnac/plugins/modules/network_device.py b/ansible_collections/cisco/dnac/plugins/modules/network_device.py index e103dbbf1..2fca16035 100644 --- a/ansible_collections/cisco/dnac/plugins/modules/network_device.py +++ b/ansible_collections/cisco/dnac/plugins/modules/network_device.py @@ -117,8 +117,8 @@ options: description: Network Device's userName. type: str requirements: -- dnacentersdk >= 2.5.5 -- python >= 3.5 +- dnacentersdk >= 2.6.0 +- python >= 3.9 seealso: - name: Cisco DNA Center documentation for Devices AddDevice2 description: Complete reference of the AddDevice2 API. diff --git a/ansible_collections/cisco/dnac/plugins/modules/network_device_by_ip_info.py b/ansible_collections/cisco/dnac/plugins/modules/network_device_by_ip_info.py index 151347c57..502db8ba4 100644 --- a/ansible_collections/cisco/dnac/plugins/modules/network_device_by_ip_info.py +++ b/ansible_collections/cisco/dnac/plugins/modules/network_device_by_ip_info.py @@ -24,8 +24,8 @@ options: - IpAddress path parameter. Device IP address. type: str requirements: -- dnacentersdk >= 2.5.5 -- python >= 3.5 +- dnacentersdk >= 2.6.0 +- python >= 3.9 seealso: - name: Cisco DNA Center documentation for Devices GetNetworkDeviceByIP description: Complete reference of the GetNetworkDeviceByIP API. diff --git a/ansible_collections/cisco/dnac/plugins/modules/network_device_by_serial_number_info.py b/ansible_collections/cisco/dnac/plugins/modules/network_device_by_serial_number_info.py index 4248aee8c..d40497b17 100644 --- a/ansible_collections/cisco/dnac/plugins/modules/network_device_by_serial_number_info.py +++ b/ansible_collections/cisco/dnac/plugins/modules/network_device_by_serial_number_info.py @@ -24,8 +24,8 @@ options: - SerialNumber path parameter. Device serial number. type: str requirements: -- dnacentersdk >= 2.5.5 -- python >= 3.5 +- dnacentersdk >= 2.6.0 +- python >= 3.9 seealso: - name: Cisco DNA Center documentation for Devices GetDeviceBySerialNumber description: Complete reference of the GetDeviceBySerialNumber API. diff --git a/ansible_collections/cisco/dnac/plugins/modules/network_device_chassis_details_info.py b/ansible_collections/cisco/dnac/plugins/modules/network_device_chassis_details_info.py index 6d540eae8..c5b34a498 100644 --- a/ansible_collections/cisco/dnac/plugins/modules/network_device_chassis_details_info.py +++ b/ansible_collections/cisco/dnac/plugins/modules/network_device_chassis_details_info.py @@ -24,8 +24,8 @@ options: - DeviceId path parameter. Device ID. type: str requirements: -- dnacentersdk >= 2.5.5 -- python >= 3.5 +- dnacentersdk >= 2.6.0 +- python >= 3.9 seealso: - name: Cisco DNA Center documentation for Devices GetChassisDetailsForDevice description: Complete reference of the GetChassisDetailsForDevice API. diff --git a/ansible_collections/cisco/dnac/plugins/modules/network_device_config_count_info.py b/ansible_collections/cisco/dnac/plugins/modules/network_device_config_count_info.py index e2b2a2449..3d2c900b0 100644 --- a/ansible_collections/cisco/dnac/plugins/modules/network_device_config_count_info.py +++ b/ansible_collections/cisco/dnac/plugins/modules/network_device_config_count_info.py @@ -20,8 +20,8 @@ options: description: Additional headers. type: dict requirements: -- dnacentersdk >= 2.5.5 -- python >= 3.5 +- dnacentersdk >= 2.6.0 +- python >= 3.9 seealso: - name: Cisco DNA Center documentation for Devices GetDeviceConfigCount description: Complete reference of the GetDeviceConfigCount API. diff --git a/ansible_collections/cisco/dnac/plugins/modules/network_device_config_info.py b/ansible_collections/cisco/dnac/plugins/modules/network_device_config_info.py index b2832bb77..6810fd6db 100644 --- a/ansible_collections/cisco/dnac/plugins/modules/network_device_config_info.py +++ b/ansible_collections/cisco/dnac/plugins/modules/network_device_config_info.py @@ -26,8 +26,8 @@ options: - NetworkDeviceId path parameter. type: str requirements: -- dnacentersdk >= 2.5.5 -- python >= 3.5 +- dnacentersdk >= 2.6.0 +- python >= 3.9 seealso: - name: Cisco DNA Center documentation for Devices GetDeviceConfigById description: Complete reference of the GetDeviceConfigById API. diff --git a/ansible_collections/cisco/dnac/plugins/modules/network_device_count_info.py b/ansible_collections/cisco/dnac/plugins/modules/network_device_count_info.py index 3a865dacb..cdcf87b7c 100644 --- a/ansible_collections/cisco/dnac/plugins/modules/network_device_count_info.py +++ b/ansible_collections/cisco/dnac/plugins/modules/network_device_count_info.py @@ -28,8 +28,8 @@ options: - DeviceId path parameter. Device ID. type: str requirements: -- dnacentersdk >= 2.5.5 -- python >= 3.5 +- dnacentersdk >= 2.6.0 +- python >= 3.9 seealso: - name: Cisco DNA Center documentation for Devices GetDeviceCount2 description: Complete reference of the GetDeviceCount2 API. diff --git a/ansible_collections/cisco/dnac/plugins/modules/network_device_custom_prompt.py b/ansible_collections/cisco/dnac/plugins/modules/network_device_custom_prompt.py index ab60bde8b..38fbc4eaa 100644 --- a/ansible_collections/cisco/dnac/plugins/modules/network_device_custom_prompt.py +++ b/ansible_collections/cisco/dnac/plugins/modules/network_device_custom_prompt.py @@ -25,8 +25,8 @@ options: description: Username Prompt. type: str requirements: -- dnacentersdk >= 2.5.5 -- python >= 3.5 +- dnacentersdk >= 2.6.0 +- python >= 3.9 seealso: - name: Cisco DNA Center documentation for System Settings CustomPromptPOSTAPI description: Complete reference of the CustomPromptPOSTAPI API. diff --git a/ansible_collections/cisco/dnac/plugins/modules/network_device_custom_prompt_info.py b/ansible_collections/cisco/dnac/plugins/modules/network_device_custom_prompt_info.py index 96a9c74bc..cd3d02bdd 100644 --- a/ansible_collections/cisco/dnac/plugins/modules/network_device_custom_prompt_info.py +++ b/ansible_collections/cisco/dnac/plugins/modules/network_device_custom_prompt_info.py @@ -20,8 +20,8 @@ options: description: Additional headers. type: dict requirements: -- dnacentersdk >= 2.5.5 -- python >= 3.5 +- dnacentersdk >= 2.6.0 +- python >= 3.9 seealso: - name: Cisco DNA Center documentation for System Settings CustomPromptSupportGETAPI description: Complete reference of the CustomPromptSupportGETAPI API. diff --git a/ansible_collections/cisco/dnac/plugins/modules/network_device_equipment_info.py b/ansible_collections/cisco/dnac/plugins/modules/network_device_equipment_info.py index 0e5cd5c64..7bc3a6733 100644 --- a/ansible_collections/cisco/dnac/plugins/modules/network_device_equipment_info.py +++ b/ansible_collections/cisco/dnac/plugins/modules/network_device_equipment_info.py @@ -30,8 +30,8 @@ options: If no type is mentioned, All equipments are fetched for the device. type: str requirements: -- dnacentersdk >= 2.5.5 -- python >= 3.5 +- dnacentersdk >= 2.6.0 +- python >= 3.9 seealso: - name: Cisco DNA Center documentation for Devices ReturnPowerSupplyFanDetailsForTheGivenDevice description: Complete reference of the ReturnPowerSupplyFanDetailsForTheGivenDevice API. diff --git a/ansible_collections/cisco/dnac/plugins/modules/network_device_export.py b/ansible_collections/cisco/dnac/plugins/modules/network_device_export.py index 93bb723e6..c1bf8d245 100644 --- a/ansible_collections/cisco/dnac/plugins/modules/network_device_export.py +++ b/ansible_collections/cisco/dnac/plugins/modules/network_device_export.py @@ -34,8 +34,8 @@ options: description: Network Device Export's password. type: str requirements: -- dnacentersdk >= 2.5.5 -- python >= 3.5 +- dnacentersdk >= 2.6.0 +- python >= 3.9 seealso: - name: Cisco DNA Center documentation for Devices ExportDeviceList description: Complete reference of the ExportDeviceList API. diff --git a/ansible_collections/cisco/dnac/plugins/modules/network_device_functional_capability_info.py b/ansible_collections/cisco/dnac/plugins/modules/network_device_functional_capability_info.py index 60d2c04b2..1d88047ab 100644 --- a/ansible_collections/cisco/dnac/plugins/modules/network_device_functional_capability_info.py +++ b/ansible_collections/cisco/dnac/plugins/modules/network_device_functional_capability_info.py @@ -37,8 +37,8 @@ options: - Id path parameter. Functional Capability UUID. type: str requirements: -- dnacentersdk >= 2.5.5 -- python >= 3.5 +- dnacentersdk >= 2.6.0 +- python >= 3.9 seealso: - name: Cisco DNA Center documentation for Devices GetFunctionalCapabilityById description: Complete reference of the GetFunctionalCapabilityById API. diff --git a/ansible_collections/cisco/dnac/plugins/modules/network_device_global_polling_interval_info.py b/ansible_collections/cisco/dnac/plugins/modules/network_device_global_polling_interval_info.py index 4d1df2f6e..41bced4d1 100644 --- a/ansible_collections/cisco/dnac/plugins/modules/network_device_global_polling_interval_info.py +++ b/ansible_collections/cisco/dnac/plugins/modules/network_device_global_polling_interval_info.py @@ -20,8 +20,8 @@ options: description: Additional headers. type: dict requirements: -- dnacentersdk >= 2.5.5 -- python >= 3.5 +- dnacentersdk >= 2.6.0 +- python >= 3.9 seealso: - name: Cisco DNA Center documentation for Devices GetPollingIntervalForAllDevices description: Complete reference of the GetPollingIntervalForAllDevices API. diff --git a/ansible_collections/cisco/dnac/plugins/modules/network_device_info.py b/ansible_collections/cisco/dnac/plugins/modules/network_device_info.py index 49d427c07..7dae65a3f 100644 --- a/ansible_collections/cisco/dnac/plugins/modules/network_device_info.py +++ b/ansible_collections/cisco/dnac/plugins/modules/network_device_info.py @@ -190,8 +190,8 @@ options: - Limit query parameter. 1 <= limit <= 500 max. No. Of devices to be returned in the result. type: int requirements: -- dnacentersdk >= 2.5.5 -- python >= 3.5 +- dnacentersdk >= 2.6.0 +- python >= 3.9 seealso: - name: Cisco DNA Center documentation for Devices GetDeviceByID description: Complete reference of the GetDeviceByID API. diff --git a/ansible_collections/cisco/dnac/plugins/modules/network_device_interface_neighbor_info.py b/ansible_collections/cisco/dnac/plugins/modules/network_device_interface_neighbor_info.py index 9b34f8a98..da4550a9e 100644 --- a/ansible_collections/cisco/dnac/plugins/modules/network_device_interface_neighbor_info.py +++ b/ansible_collections/cisco/dnac/plugins/modules/network_device_interface_neighbor_info.py @@ -28,8 +28,8 @@ options: - InterfaceUuid path parameter. Instanceuuid of interface. type: str requirements: -- dnacentersdk >= 2.5.5 -- python >= 3.5 +- dnacentersdk >= 2.6.0 +- python >= 3.9 seealso: - name: Cisco DNA Center documentation for Devices GetConnectedDeviceDetail description: Complete reference of the GetConnectedDeviceDetail API. diff --git a/ansible_collections/cisco/dnac/plugins/modules/network_device_interface_poe_info.py b/ansible_collections/cisco/dnac/plugins/modules/network_device_interface_poe_info.py index 3da01e141..2c525456f 100644 --- a/ansible_collections/cisco/dnac/plugins/modules/network_device_interface_poe_info.py +++ b/ansible_collections/cisco/dnac/plugins/modules/network_device_interface_poe_info.py @@ -31,8 +31,8 @@ options: - InterfaceNameList query parameter. Comma seperated interface names. type: str requirements: -- dnacentersdk >= 2.5.5 -- python >= 3.5 +- dnacentersdk >= 2.6.0 +- python >= 3.9 seealso: - name: Cisco DNA Center documentation for Devices ReturnsPOEInterfaceDetailsForTheDevice description: Complete reference of the ReturnsPOEInterfaceDetailsForTheDevice API. diff --git a/ansible_collections/cisco/dnac/plugins/modules/network_device_inventory_insight_link_mismatch_info.py b/ansible_collections/cisco/dnac/plugins/modules/network_device_inventory_insight_link_mismatch_info.py index 23f7c6c57..ee282e771 100644 --- a/ansible_collections/cisco/dnac/plugins/modules/network_device_inventory_insight_link_mismatch_info.py +++ b/ansible_collections/cisco/dnac/plugins/modules/network_device_inventory_insight_link_mismatch_info.py @@ -44,8 +44,8 @@ options: - Order query parameter. Order. Value can be asc or desc. Default value is asc. type: str requirements: -- dnacentersdk >= 2.5.5 -- python >= 3.5 +- dnacentersdk >= 2.6.0 +- python >= 3.9 seealso: - name: Cisco DNA Center documentation for Devices InventoryInsightDeviceLinkMismatchAPI description: Complete reference of the InventoryInsightDeviceLinkMismatchAPI API. diff --git a/ansible_collections/cisco/dnac/plugins/modules/network_device_lexicographically_sorted_info.py b/ansible_collections/cisco/dnac/plugins/modules/network_device_lexicographically_sorted_info.py index 04e1ebfce..cd7473692 100644 --- a/ansible_collections/cisco/dnac/plugins/modules/network_device_lexicographically_sorted_info.py +++ b/ansible_collections/cisco/dnac/plugins/modules/network_device_lexicographically_sorted_info.py @@ -108,8 +108,8 @@ options: - Limit query parameter. type: int requirements: -- dnacentersdk >= 2.5.5 -- python >= 3.5 +- dnacentersdk >= 2.6.0 +- python >= 3.9 seealso: - name: Cisco DNA Center documentation for Devices GetDeviceValuesThatMatchFullyOrPartiallyAnAttribute description: Complete reference of the GetDeviceValuesThatMatchFullyOrPartiallyAnAttribute API. diff --git a/ansible_collections/cisco/dnac/plugins/modules/network_device_linecard_details_info.py b/ansible_collections/cisco/dnac/plugins/modules/network_device_linecard_details_info.py index a2267a752..6ec120ded 100644 --- a/ansible_collections/cisco/dnac/plugins/modules/network_device_linecard_details_info.py +++ b/ansible_collections/cisco/dnac/plugins/modules/network_device_linecard_details_info.py @@ -24,8 +24,8 @@ options: - DeviceUuid path parameter. Instanceuuid of device. type: str requirements: -- dnacentersdk >= 2.5.5 -- python >= 3.5 +- dnacentersdk >= 2.6.0 +- python >= 3.9 seealso: - name: Cisco DNA Center documentation for Devices GetLinecardDetails description: Complete reference of the GetLinecardDetails API. diff --git a/ansible_collections/cisco/dnac/plugins/modules/network_device_meraki_organization_info.py b/ansible_collections/cisco/dnac/plugins/modules/network_device_meraki_organization_info.py index a9bde346e..a8bc1ddeb 100644 --- a/ansible_collections/cisco/dnac/plugins/modules/network_device_meraki_organization_info.py +++ b/ansible_collections/cisco/dnac/plugins/modules/network_device_meraki_organization_info.py @@ -24,8 +24,8 @@ options: - Id path parameter. type: str requirements: -- dnacentersdk >= 2.5.5 -- python >= 3.5 +- dnacentersdk >= 2.6.0 +- python >= 3.9 seealso: - name: Cisco DNA Center documentation for Devices GetOrganizationListForMeraki description: Complete reference of the GetOrganizationListForMeraki API. diff --git a/ansible_collections/cisco/dnac/plugins/modules/network_device_module_count_info.py b/ansible_collections/cisco/dnac/plugins/modules/network_device_module_count_info.py index 6bddca67e..5969b346e 100644 --- a/ansible_collections/cisco/dnac/plugins/modules/network_device_module_count_info.py +++ b/ansible_collections/cisco/dnac/plugins/modules/network_device_module_count_info.py @@ -44,8 +44,8 @@ options: elements: str type: list requirements: -- dnacentersdk >= 2.5.5 -- python >= 3.5 +- dnacentersdk >= 2.6.0 +- python >= 3.9 seealso: - name: Cisco DNA Center documentation for Devices GetModuleCount description: Complete reference of the GetModuleCount API. diff --git a/ansible_collections/cisco/dnac/plugins/modules/network_device_module_info.py b/ansible_collections/cisco/dnac/plugins/modules/network_device_module_info.py index d9924fc15..be3bd1a55 100644 --- a/ansible_collections/cisco/dnac/plugins/modules/network_device_module_info.py +++ b/ansible_collections/cisco/dnac/plugins/modules/network_device_module_info.py @@ -58,8 +58,8 @@ options: - Id path parameter. Module id. type: str requirements: -- dnacentersdk >= 2.5.5 -- python >= 3.5 +- dnacentersdk >= 2.6.0 +- python >= 3.9 seealso: - name: Cisco DNA Center documentation for Devices GetModuleInfoById description: Complete reference of the GetModuleInfoById API. diff --git a/ansible_collections/cisco/dnac/plugins/modules/network_device_poe_info.py b/ansible_collections/cisco/dnac/plugins/modules/network_device_poe_info.py index ca99bdd37..4f78d1e70 100644 --- a/ansible_collections/cisco/dnac/plugins/modules/network_device_poe_info.py +++ b/ansible_collections/cisco/dnac/plugins/modules/network_device_poe_info.py @@ -24,8 +24,8 @@ options: - DeviceUuid path parameter. Uuid of the device. type: str requirements: -- dnacentersdk >= 2.5.5 -- python >= 3.5 +- dnacentersdk >= 2.6.0 +- python >= 3.9 seealso: - name: Cisco DNA Center documentation for Devices POEDetails description: Complete reference of the POEDetails API. diff --git a/ansible_collections/cisco/dnac/plugins/modules/network_device_polling_interval_info.py b/ansible_collections/cisco/dnac/plugins/modules/network_device_polling_interval_info.py index 36bfbce02..fc4707d26 100644 --- a/ansible_collections/cisco/dnac/plugins/modules/network_device_polling_interval_info.py +++ b/ansible_collections/cisco/dnac/plugins/modules/network_device_polling_interval_info.py @@ -24,8 +24,8 @@ options: - Id path parameter. Device ID. type: str requirements: -- dnacentersdk >= 2.5.5 -- python >= 3.5 +- dnacentersdk >= 2.6.0 +- python >= 3.9 seealso: - name: Cisco DNA Center documentation for Devices GetPollingIntervalById description: Complete reference of the GetPollingIntervalById API. diff --git a/ansible_collections/cisco/dnac/plugins/modules/network_device_range_info.py b/ansible_collections/cisco/dnac/plugins/modules/network_device_range_info.py index 2aa2f9e80..5ea4572f4 100644 --- a/ansible_collections/cisco/dnac/plugins/modules/network_device_range_info.py +++ b/ansible_collections/cisco/dnac/plugins/modules/network_device_range_info.py @@ -30,8 +30,8 @@ options: - RecordsToReturn path parameter. Number of records to return 1<= recordsToReturn <= 500. type: int requirements: -- dnacentersdk >= 2.5.5 -- python >= 3.5 +- dnacentersdk >= 2.6.0 +- python >= 3.9 seealso: - name: Cisco DNA Center documentation for Devices GetNetworkDeviceByPaginationRange description: Complete reference of the GetNetworkDeviceByPaginationRange API. diff --git a/ansible_collections/cisco/dnac/plugins/modules/network_device_register_for_wsa_info.py b/ansible_collections/cisco/dnac/plugins/modules/network_device_register_for_wsa_info.py index 7997fa15f..29c483aa2 100644 --- a/ansible_collections/cisco/dnac/plugins/modules/network_device_register_for_wsa_info.py +++ b/ansible_collections/cisco/dnac/plugins/modules/network_device_register_for_wsa_info.py @@ -30,8 +30,8 @@ options: - Macaddress query parameter. Mac addres of the device. type: str requirements: -- dnacentersdk >= 2.5.5 -- python >= 3.5 +- dnacentersdk >= 2.6.0 +- python >= 3.9 seealso: - name: Cisco DNA Center documentation for Devices GetDevicesRegisteredForWSANotification description: Complete reference of the GetDevicesRegisteredForWSANotification API. diff --git a/ansible_collections/cisco/dnac/plugins/modules/network_device_stack_details_info.py b/ansible_collections/cisco/dnac/plugins/modules/network_device_stack_details_info.py index 4f8912bc9..5cdaf55ad 100644 --- a/ansible_collections/cisco/dnac/plugins/modules/network_device_stack_details_info.py +++ b/ansible_collections/cisco/dnac/plugins/modules/network_device_stack_details_info.py @@ -24,8 +24,8 @@ options: - DeviceId path parameter. Device ID. type: str requirements: -- dnacentersdk >= 2.5.5 -- python >= 3.5 +- dnacentersdk >= 2.6.0 +- python >= 3.9 seealso: - name: Cisco DNA Center documentation for Devices GetStackDetailsForDevice description: Complete reference of the GetStackDetailsForDevice API. diff --git a/ansible_collections/cisco/dnac/plugins/modules/network_device_summary_info.py b/ansible_collections/cisco/dnac/plugins/modules/network_device_summary_info.py index 4aa0c2940..3096ba1cf 100644 --- a/ansible_collections/cisco/dnac/plugins/modules/network_device_summary_info.py +++ b/ansible_collections/cisco/dnac/plugins/modules/network_device_summary_info.py @@ -24,8 +24,8 @@ options: - Id path parameter. Device ID. type: str requirements: -- dnacentersdk >= 2.5.5 -- python >= 3.5 +- dnacentersdk >= 2.6.0 +- python >= 3.9 seealso: - name: Cisco DNA Center documentation for Devices GetDeviceSummary description: Complete reference of the GetDeviceSummary API. diff --git a/ansible_collections/cisco/dnac/plugins/modules/network_device_supervisor_card_details_info.py b/ansible_collections/cisco/dnac/plugins/modules/network_device_supervisor_card_details_info.py index f4547f295..f9db5bdd7 100644 --- a/ansible_collections/cisco/dnac/plugins/modules/network_device_supervisor_card_details_info.py +++ b/ansible_collections/cisco/dnac/plugins/modules/network_device_supervisor_card_details_info.py @@ -24,8 +24,8 @@ options: - DeviceUuid path parameter. Instanceuuid of device. type: str requirements: -- dnacentersdk >= 2.5.5 -- python >= 3.5 +- dnacentersdk >= 2.6.0 +- python >= 3.9 seealso: - name: Cisco DNA Center documentation for Devices GetSupervisorCardDetail description: Complete reference of the GetSupervisorCardDetail API. diff --git a/ansible_collections/cisco/dnac/plugins/modules/network_device_sync.py b/ansible_collections/cisco/dnac/plugins/modules/network_device_sync.py index 255d81e12..526b8d239 100644 --- a/ansible_collections/cisco/dnac/plugins/modules/network_device_sync.py +++ b/ansible_collections/cisco/dnac/plugins/modules/network_device_sync.py @@ -27,8 +27,8 @@ options: elements: dict type: list requirements: -- dnacentersdk >= 2.5.5 -- python >= 3.5 +- dnacentersdk >= 2.6.0 +- python >= 3.9 seealso: - name: Cisco DNA Center documentation for Devices SyncDevices description: Complete reference of the SyncDevices API. diff --git a/ansible_collections/cisco/dnac/plugins/modules/network_device_update_role.py b/ansible_collections/cisco/dnac/plugins/modules/network_device_update_role.py index 16972e2ee..14ded7ec1 100644 --- a/ansible_collections/cisco/dnac/plugins/modules/network_device_update_role.py +++ b/ansible_collections/cisco/dnac/plugins/modules/network_device_update_role.py @@ -26,8 +26,8 @@ options: description: Network Device Update Role's roleSource. type: str requirements: -- dnacentersdk >= 2.5.5 -- python >= 3.5 +- dnacentersdk >= 2.6.0 +- python >= 3.9 seealso: - name: Cisco DNA Center documentation for Devices UpdateDeviceRole description: Complete reference of the UpdateDeviceRole API. diff --git a/ansible_collections/cisco/dnac/plugins/modules/network_device_user_defined_field.py b/ansible_collections/cisco/dnac/plugins/modules/network_device_user_defined_field.py index b350e69dd..8d0ddc17e 100644 --- a/ansible_collections/cisco/dnac/plugins/modules/network_device_user_defined_field.py +++ b/ansible_collections/cisco/dnac/plugins/modules/network_device_user_defined_field.py @@ -28,8 +28,8 @@ options: description: Name of UDF. type: str requirements: -- dnacentersdk >= 2.5.5 -- python >= 3.5 +- dnacentersdk >= 2.6.0 +- python >= 3.9 seealso: - name: Cisco DNA Center documentation for Devices CreateUserDefinedField description: Complete reference of the CreateUserDefinedField API. diff --git a/ansible_collections/cisco/dnac/plugins/modules/network_device_user_defined_field_info.py b/ansible_collections/cisco/dnac/plugins/modules/network_device_user_defined_field_info.py index d72f5955e..967114272 100644 --- a/ansible_collections/cisco/dnac/plugins/modules/network_device_user_defined_field_info.py +++ b/ansible_collections/cisco/dnac/plugins/modules/network_device_user_defined_field_info.py @@ -30,8 +30,8 @@ options: - Name query parameter. Comma-seperated name(s) used for search/filtering. type: str requirements: -- dnacentersdk >= 2.5.5 -- python >= 3.5 +- dnacentersdk >= 2.6.0 +- python >= 3.9 seealso: - name: Cisco DNA Center documentation for Devices GetAllUserDefinedFields description: Complete reference of the GetAllUserDefinedFields API. diff --git a/ansible_collections/cisco/dnac/plugins/modules/network_device_vlan_info.py b/ansible_collections/cisco/dnac/plugins/modules/network_device_vlan_info.py index d236beee3..132c102c7 100644 --- a/ansible_collections/cisco/dnac/plugins/modules/network_device_vlan_info.py +++ b/ansible_collections/cisco/dnac/plugins/modules/network_device_vlan_info.py @@ -28,8 +28,8 @@ options: - InterfaceType query parameter. Vlan assocaited with sub-interface. type: str requirements: -- dnacentersdk >= 2.5.5 -- python >= 3.5 +- dnacentersdk >= 2.6.0 +- python >= 3.9 seealso: - name: Cisco DNA Center documentation for Devices GetDeviceInterfaceVLANs description: Complete reference of the GetDeviceInterfaceVLANs API. diff --git a/ansible_collections/cisco/dnac/plugins/modules/network_device_wireless_lan_info.py b/ansible_collections/cisco/dnac/plugins/modules/network_device_wireless_lan_info.py index 29615e66d..f08b1bcca 100644 --- a/ansible_collections/cisco/dnac/plugins/modules/network_device_wireless_lan_info.py +++ b/ansible_collections/cisco/dnac/plugins/modules/network_device_wireless_lan_info.py @@ -24,8 +24,8 @@ options: - Id path parameter. Device ID. type: str requirements: -- dnacentersdk >= 2.5.5 -- python >= 3.5 +- dnacentersdk >= 2.6.0 +- python >= 3.9 seealso: - name: Cisco DNA Center documentation for Devices GetWirelessLanControllerDetailsById description: Complete reference of the GetWirelessLanControllerDetailsById API. diff --git a/ansible_collections/cisco/dnac/plugins/modules/network_device_with_snmp_v3_des_info.py b/ansible_collections/cisco/dnac/plugins/modules/network_device_with_snmp_v3_des_info.py index 4fd5157c5..b3b6a55d6 100644 --- a/ansible_collections/cisco/dnac/plugins/modules/network_device_with_snmp_v3_des_info.py +++ b/ansible_collections/cisco/dnac/plugins/modules/network_device_with_snmp_v3_des_info.py @@ -42,8 +42,8 @@ options: - Order query parameter. type: str requirements: -- dnacentersdk >= 2.5.5 -- python >= 3.5 +- dnacentersdk >= 2.6.0 +- python >= 3.9 seealso: - name: Cisco DNA Center documentation for Devices ReturnsDevicesAddedToCiscoDNACenterWithSnmpV3DES description: Complete reference of the ReturnsDevicesAddedToCiscoDNACenterWithSnmpV3DES API. diff --git a/ansible_collections/cisco/dnac/plugins/modules/network_info.py b/ansible_collections/cisco/dnac/plugins/modules/network_info.py index 682a9b5b1..0aa99bde5 100644 --- a/ansible_collections/cisco/dnac/plugins/modules/network_info.py +++ b/ansible_collections/cisco/dnac/plugins/modules/network_info.py @@ -24,8 +24,8 @@ options: - SiteId query parameter. Site id to get the network settings associated with the site. type: str requirements: -- dnacentersdk >= 2.5.5 -- python >= 3.5 +- dnacentersdk >= 2.6.0 +- python >= 3.9 seealso: - name: Cisco DNA Center documentation for Network Settings GetNetwork description: Complete reference of the GetNetwork API. diff --git a/ansible_collections/cisco/dnac/plugins/modules/network_settings_intent.py b/ansible_collections/cisco/dnac/plugins/modules/network_settings_intent.py index 49d6fa5d4..a86d342cf 100644 --- a/ansible_collections/cisco/dnac/plugins/modules/network_settings_intent.py +++ b/ansible_collections/cisco/dnac/plugins/modules/network_settings_intent.py @@ -318,7 +318,7 @@ options: type: str requirements: - dnacentersdk == 2.4.5 -- python >= 3.5 +- python >= 3.9 notes: - SDK Method used are network_settings.NetworkSettings.create_global_pool, @@ -705,6 +705,7 @@ class NetworkSettings(DnacBase): response = self.dnac._exec( family="sites", function='get_site', + op_modifies=True, params={"name": site_name}, ) self.log("Received API response from 'get_site': {0}".format(response), "DEBUG") @@ -856,6 +857,7 @@ class NetworkSettings(DnacBase): response = self.dnac._exec( family="network_settings", function='get_network_v2', + op_modifies=True, params={"site_id": site_id} ) self.log("Received API response from 'get_network_v2': {0}".format(response), "DEBUG") @@ -1061,6 +1063,7 @@ class NetworkSettings(DnacBase): response = self.dnac._exec( family="network_settings", function="get_reserve_ip_subpool", + op_modifies=True, params={"siteId": site_id} ) if not isinstance(response, dict): @@ -1748,6 +1751,7 @@ class NetworkSettings(DnacBase): response = self.dnac._exec( family="network_settings", function="create_global_pool", + op_modifies=True, params=pool_params, ) self.check_execution_response_status(response).check_return_status() @@ -1793,6 +1797,7 @@ class NetworkSettings(DnacBase): response = self.dnac._exec( family="network_settings", function="update_global_pool", + op_modifies=True, params=pool_params, ) @@ -1836,6 +1841,7 @@ class NetworkSettings(DnacBase): response = self.dnac._exec( family="network_settings", function="reserve_ip_subpool", + op_modifies=True, params=reserve_params, ) self.check_execution_response_status(response).check_return_status() @@ -1868,6 +1874,7 @@ class NetworkSettings(DnacBase): response = self.dnac._exec( family="network_settings", function="update_reserve_ip_subpool", + op_modifies=True, params=reserve_params, ) self.check_execution_response_status(response).check_return_status() @@ -1915,6 +1922,7 @@ class NetworkSettings(DnacBase): response = self.dnac._exec( family="network_settings", function='update_network_v2', + op_modifies=True, params=net_params, ) self.log("Received API response of 'update_network_v2': {0}".format(response), "DEBUG") @@ -1978,6 +1986,7 @@ class NetworkSettings(DnacBase): response = self.dnac._exec( family="network_settings", function="release_reserve_ip_subpool", + op_modifies=True, params={"id": _id}, ) self.check_execution_response_status(response).check_return_status() @@ -2014,6 +2023,7 @@ class NetworkSettings(DnacBase): response = self.dnac._exec( family="network_settings", function="delete_global_ip_pool", + op_modifies=True, params={"id": self.have.get("globalPool").get("id")}, ) diff --git a/ansible_collections/cisco/dnac/plugins/modules/network_settings_workflow_manager.py b/ansible_collections/cisco/dnac/plugins/modules/network_settings_workflow_manager.py index bbae36463..cdf7b0634 100644 --- a/ansible_collections/cisco/dnac/plugins/modules/network_settings_workflow_manager.py +++ b/ansible_collections/cisco/dnac/plugins/modules/network_settings_workflow_manager.py @@ -318,7 +318,7 @@ options: type: str requirements: - dnacentersdk == 2.4.5 -- python >= 3.5 +- python >= 3.9 notes: - SDK Method used are network_settings.NetworkSettings.create_global_pool, @@ -701,6 +701,7 @@ class NetworkSettings(DnacBase): response = self.dnac._exec( family="sites", function='get_site', + op_modifies=True, params={"name": site_name}, ) self.log("Received API response from 'get_site': {0}".format(response), "DEBUG") @@ -852,6 +853,7 @@ class NetworkSettings(DnacBase): response = self.dnac._exec( family="network_settings", function='get_network_v2', + op_modifies=True, params={"site_id": site_id} ) self.log("Received API response from 'get_network_v2': {0}".format(response), "DEBUG") @@ -1057,6 +1059,7 @@ class NetworkSettings(DnacBase): response = self.dnac._exec( family="network_settings", function="get_reserve_ip_subpool", + op_modifies=True, params={"siteId": site_id} ) if not isinstance(response, dict): @@ -1733,6 +1736,7 @@ class NetworkSettings(DnacBase): response = self.dnac._exec( family="network_settings", function="create_global_pool", + op_modifies=True, params=pool_params, ) self.check_execution_response_status(response).check_return_status() @@ -1778,6 +1782,7 @@ class NetworkSettings(DnacBase): response = self.dnac._exec( family="network_settings", function="update_global_pool", + op_modifies=True, params=pool_params, ) @@ -1821,6 +1826,7 @@ class NetworkSettings(DnacBase): response = self.dnac._exec( family="network_settings", function="reserve_ip_subpool", + op_modifies=True, params=reserve_params, ) self.check_execution_response_status(response).check_return_status() @@ -1853,6 +1859,7 @@ class NetworkSettings(DnacBase): response = self.dnac._exec( family="network_settings", function="update_reserve_ip_subpool", + op_modifies=True, params=reserve_params, ) self.check_execution_response_status(response).check_return_status() @@ -1900,6 +1907,7 @@ class NetworkSettings(DnacBase): response = self.dnac._exec( family="network_settings", function='update_network_v2', + op_modifies=True, params=net_params, ) self.log("Received API response of 'update_network_v2': {0}".format(response), "DEBUG") @@ -1963,6 +1971,7 @@ class NetworkSettings(DnacBase): response = self.dnac._exec( family="network_settings", function="release_reserve_ip_subpool", + op_modifies=True, params={"id": _id}, ) self.check_execution_response_status(response).check_return_status() @@ -1999,6 +2008,7 @@ class NetworkSettings(DnacBase): response = self.dnac._exec( family="network_settings", function="delete_global_ip_pool", + op_modifies=True, params={"id": self.have.get("globalPool").get("id")}, ) diff --git a/ansible_collections/cisco/dnac/plugins/modules/network_update.py b/ansible_collections/cisco/dnac/plugins/modules/network_update.py index be67025b8..42b2eec0f 100644 --- a/ansible_collections/cisco/dnac/plugins/modules/network_update.py +++ b/ansible_collections/cisco/dnac/plugins/modules/network_update.py @@ -131,8 +131,8 @@ options: is associated with the site. type: str requirements: -- dnacentersdk >= 2.5.5 -- python >= 3.5 +- dnacentersdk >= 2.6.0 +- python >= 3.9 seealso: - name: Cisco DNA Center documentation for Network Settings UpdateNetwork description: Complete reference of the UpdateNetwork API. diff --git a/ansible_collections/cisco/dnac/plugins/modules/network_v2.py b/ansible_collections/cisco/dnac/plugins/modules/network_v2.py index 14ca5c286..faa1b85c9 100644 --- a/ansible_collections/cisco/dnac/plugins/modules/network_v2.py +++ b/ansible_collections/cisco/dnac/plugins/modules/network_v2.py @@ -134,8 +134,8 @@ options: the network settings. type: str requirements: -- dnacentersdk >= 2.5.5 -- python >= 3.5 +- dnacentersdk >= 2.6.0 +- python >= 3.9 seealso: - name: Cisco DNA Center documentation for Network Settings CreateNetworkV2 description: Complete reference of the CreateNetworkV2 API. diff --git a/ansible_collections/cisco/dnac/plugins/modules/network_v2_info.py b/ansible_collections/cisco/dnac/plugins/modules/network_v2_info.py index f3b03cb76..096b27bbd 100644 --- a/ansible_collections/cisco/dnac/plugins/modules/network_v2_info.py +++ b/ansible_collections/cisco/dnac/plugins/modules/network_v2_info.py @@ -24,8 +24,8 @@ options: - SiteId query parameter. Site Id to get the network settings associated with the site. type: str requirements: -- dnacentersdk >= 2.5.5 -- python >= 3.5 +- dnacentersdk >= 2.6.0 +- python >= 3.9 seealso: - name: Cisco DNA Center documentation for Network Settings GetNetworkV2 description: Complete reference of the GetNetworkV2 API. diff --git a/ansible_collections/cisco/dnac/plugins/modules/nfv_profile.py b/ansible_collections/cisco/dnac/plugins/modules/nfv_profile.py index 409c937d4..37ce59101 100644 --- a/ansible_collections/cisco/dnac/plugins/modules/nfv_profile.py +++ b/ansible_collections/cisco/dnac/plugins/modules/nfv_profile.py @@ -147,8 +147,8 @@ options: description: Name of the profile to create NFV profile. type: str requirements: -- dnacentersdk >= 2.5.5 -- python >= 3.5 +- dnacentersdk >= 2.6.0 +- python >= 3.9 seealso: - name: Cisco DNA Center documentation for Site Design CreateNFVProfile description: Complete reference of the CreateNFVProfile API. diff --git a/ansible_collections/cisco/dnac/plugins/modules/nfv_profile_info.py b/ansible_collections/cisco/dnac/plugins/modules/nfv_profile_info.py index 946879359..7deb4f7be 100644 --- a/ansible_collections/cisco/dnac/plugins/modules/nfv_profile_info.py +++ b/ansible_collections/cisco/dnac/plugins/modules/nfv_profile_info.py @@ -36,8 +36,8 @@ options: - Name query parameter. Name of network profile to be retrieved. type: str requirements: -- dnacentersdk >= 2.5.5 -- python >= 3.5 +- dnacentersdk >= 2.6.0 +- python >= 3.9 seealso: - name: Cisco DNA Center documentation for Site Design GetNFVProfile description: Complete reference of the GetNFVProfile API. diff --git a/ansible_collections/cisco/dnac/plugins/modules/nfv_provision.py b/ansible_collections/cisco/dnac/plugins/modules/nfv_provision.py index 23f4269f0..e242de7f5 100644 --- a/ansible_collections/cisco/dnac/plugins/modules/nfv_provision.py +++ b/ansible_collections/cisco/dnac/plugins/modules/nfv_provision.py @@ -375,8 +375,8 @@ options: type: str type: list requirements: -- dnacentersdk >= 2.5.5 -- python >= 3.5 +- dnacentersdk >= 2.6.0 +- python >= 3.9 seealso: - name: Cisco DNA Center documentation for Site Design ProvisionNFV description: Complete reference of the ProvisionNFV API. diff --git a/ansible_collections/cisco/dnac/plugins/modules/nfv_provision_detail_info.py b/ansible_collections/cisco/dnac/plugins/modules/nfv_provision_detail_info.py index 8ad7287ad..2a0f85a5a 100644 --- a/ansible_collections/cisco/dnac/plugins/modules/nfv_provision_detail_info.py +++ b/ansible_collections/cisco/dnac/plugins/modules/nfv_provision_detail_info.py @@ -24,8 +24,8 @@ options: - DeviceIp query parameter. Device to which the provisioning detail has to be retrieved. type: str requirements: -- dnacentersdk >= 2.5.5 -- python >= 3.5 +- dnacentersdk >= 2.6.0 +- python >= 3.9 seealso: - name: Cisco DNA Center documentation for Site Design GetDeviceDetailsByIP description: Complete reference of the GetDeviceDetailsByIP API. diff --git a/ansible_collections/cisco/dnac/plugins/modules/nfv_provision_details.py b/ansible_collections/cisco/dnac/plugins/modules/nfv_provision_details.py index 6f8bc7308..af9792e72 100644 --- a/ansible_collections/cisco/dnac/plugins/modules/nfv_provision_details.py +++ b/ansible_collections/cisco/dnac/plugins/modules/nfv_provision_details.py @@ -23,8 +23,8 @@ options: description: Additional headers. type: dict requirements: -- dnacentersdk >= 2.5.5 -- python >= 3.5 +- dnacentersdk >= 2.6.0 +- python >= 3.9 seealso: - name: Cisco DNA Center documentation for Site Design NFVProvisioningDetail description: Complete reference of the NFVProvisioningDetail API. diff --git a/ansible_collections/cisco/dnac/plugins/modules/path_trace.py b/ansible_collections/cisco/dnac/plugins/modules/path_trace.py index a2b5519a6..055db2d56 100644 --- a/ansible_collections/cisco/dnac/plugins/modules/path_trace.py +++ b/ansible_collections/cisco/dnac/plugins/modules/path_trace.py @@ -49,8 +49,8 @@ options: description: Source Port. type: str requirements: -- dnacentersdk >= 2.5.5 -- python >= 3.5 +- dnacentersdk >= 2.6.0 +- python >= 3.9 seealso: - name: Cisco DNA Center documentation for Path Trace InitiateANewPathtrace description: Complete reference of the InitiateANewPathtrace API. diff --git a/ansible_collections/cisco/dnac/plugins/modules/path_trace_info.py b/ansible_collections/cisco/dnac/plugins/modules/path_trace_info.py index a160114ef..d305183c1 100644 --- a/ansible_collections/cisco/dnac/plugins/modules/path_trace_info.py +++ b/ansible_collections/cisco/dnac/plugins/modules/path_trace_info.py @@ -86,8 +86,8 @@ options: - FlowAnalysisId path parameter. Flow analysis request id. type: str requirements: -- dnacentersdk >= 2.5.5 -- python >= 3.5 +- dnacentersdk >= 2.6.0 +- python >= 3.9 seealso: - name: Cisco DNA Center documentation for Path Trace RetrievesPreviousPathtrace description: Complete reference of the RetrievesPreviousPathtrace API. diff --git a/ansible_collections/cisco/dnac/plugins/modules/planned_access_points_info.py b/ansible_collections/cisco/dnac/plugins/modules/planned_access_points_info.py index df323c577..bed5d8656 100644 --- a/ansible_collections/cisco/dnac/plugins/modules/planned_access_points_info.py +++ b/ansible_collections/cisco/dnac/plugins/modules/planned_access_points_info.py @@ -36,8 +36,8 @@ options: - Radios query parameter. Inlcude planned radio details. type: bool requirements: -- dnacentersdk >= 2.5.5 -- python >= 3.5 +- dnacentersdk >= 2.6.0 +- python >= 3.9 seealso: - name: Cisco DNA Center documentation for Devices GetPlannedAccessPointsForFloor description: Complete reference of the GetPlannedAccessPointsForFloor API. diff --git a/ansible_collections/cisco/dnac/plugins/modules/platform_nodes_configuration_summary_info.py b/ansible_collections/cisco/dnac/plugins/modules/platform_nodes_configuration_summary_info.py index 9e4bad79e..d06ecb029 100644 --- a/ansible_collections/cisco/dnac/plugins/modules/platform_nodes_configuration_summary_info.py +++ b/ansible_collections/cisco/dnac/plugins/modules/platform_nodes_configuration_summary_info.py @@ -23,8 +23,8 @@ options: description: Additional headers. type: dict requirements: -- dnacentersdk >= 2.5.5 -- python >= 3.5 +- dnacentersdk >= 2.6.0 +- python >= 3.9 seealso: - name: Cisco DNA Center documentation for Platform Configuration CiscoDNACenterNodesConfigurationSummary description: Complete reference of the CiscoDNACenterNodesConfigurationSummary API. diff --git a/ansible_collections/cisco/dnac/plugins/modules/platform_release_summary_info.py b/ansible_collections/cisco/dnac/plugins/modules/platform_release_summary_info.py index 7af697e95..b37caefc0 100644 --- a/ansible_collections/cisco/dnac/plugins/modules/platform_release_summary_info.py +++ b/ansible_collections/cisco/dnac/plugins/modules/platform_release_summary_info.py @@ -22,8 +22,8 @@ options: description: Additional headers. type: dict requirements: -- dnacentersdk >= 2.5.5 -- python >= 3.5 +- dnacentersdk >= 2.6.0 +- python >= 3.9 seealso: - name: Cisco DNA Center documentation for Platform Configuration CiscoDNACenterReleaseSummary description: Complete reference of the CiscoDNACenterReleaseSummary API. diff --git a/ansible_collections/cisco/dnac/plugins/modules/pnp_device.py b/ansible_collections/cisco/dnac/plugins/modules/pnp_device.py index 0f6a736a5..a3451edeb 100644 --- a/ansible_collections/cisco/dnac/plugins/modules/pnp_device.py +++ b/ansible_collections/cisco/dnac/plugins/modules/pnp_device.py @@ -823,8 +823,8 @@ options: type: str type: dict requirements: -- dnacentersdk >= 2.5.5 -- python >= 3.5 +- dnacentersdk >= 2.6.0 +- python >= 3.9 seealso: - name: Cisco DNA Center documentation for Device Onboarding (PnP) AddDevice description: Complete reference of the AddDevice API. diff --git a/ansible_collections/cisco/dnac/plugins/modules/pnp_device_authorize.py b/ansible_collections/cisco/dnac/plugins/modules/pnp_device_authorize.py index c6aa96590..2a033f504 100644 --- a/ansible_collections/cisco/dnac/plugins/modules/pnp_device_authorize.py +++ b/ansible_collections/cisco/dnac/plugins/modules/pnp_device_authorize.py @@ -21,8 +21,8 @@ options: elements: str type: list requirements: -- dnacentersdk >= 2.5.5 -- python >= 3.5 +- dnacentersdk >= 2.6.0 +- python >= 3.9 seealso: - name: Cisco DNA Center documentation for AuthorizeDevice description: Complete reference of the AuthorizeDevice API. diff --git a/ansible_collections/cisco/dnac/plugins/modules/pnp_device_claim.py b/ansible_collections/cisco/dnac/plugins/modules/pnp_device_claim.py index 3a6c668f5..4ce1b3389 100644 --- a/ansible_collections/cisco/dnac/plugins/modules/pnp_device_claim.py +++ b/ansible_collections/cisco/dnac/plugins/modules/pnp_device_claim.py @@ -77,8 +77,8 @@ options: description: Pnp Device Claim's workflowId. type: str requirements: -- dnacentersdk >= 2.5.5 -- python >= 3.5 +- dnacentersdk >= 2.6.0 +- python >= 3.9 seealso: - name: Cisco DNA Center documentation for Device Onboarding (PnP) ClaimDevice description: Complete reference of the ClaimDevice API. diff --git a/ansible_collections/cisco/dnac/plugins/modules/pnp_device_claim_to_site.py b/ansible_collections/cisco/dnac/plugins/modules/pnp_device_claim_to_site.py index 397dc9f95..2e3bdd0a5 100644 --- a/ansible_collections/cisco/dnac/plugins/modules/pnp_device_claim_to_site.py +++ b/ansible_collections/cisco/dnac/plugins/modules/pnp_device_claim_to_site.py @@ -80,8 +80,8 @@ options: description: For Catalyst 9800 WLC. type: str requirements: -- dnacentersdk >= 2.5.5 -- python >= 3.5 +- dnacentersdk >= 2.6.0 +- python >= 3.9 seealso: - name: Cisco DNA Center documentation for Device Onboarding (PnP) ClaimADeviceToASite description: Complete reference of the ClaimADeviceToASite API. diff --git a/ansible_collections/cisco/dnac/plugins/modules/pnp_device_config_preview.py b/ansible_collections/cisco/dnac/plugins/modules/pnp_device_config_preview.py index 7007ba3bb..24d1ae219 100644 --- a/ansible_collections/cisco/dnac/plugins/modules/pnp_device_config_preview.py +++ b/ansible_collections/cisco/dnac/plugins/modules/pnp_device_config_preview.py @@ -26,8 +26,8 @@ options: description: Pnp Device Config Preview's type. type: str requirements: -- dnacentersdk >= 2.5.5 -- python >= 3.5 +- dnacentersdk >= 2.6.0 +- python >= 3.9 seealso: - name: Cisco DNA Center documentation for Device Onboarding (PnP) PreviewConfig description: Complete reference of the PreviewConfig API. diff --git a/ansible_collections/cisco/dnac/plugins/modules/pnp_device_count_info.py b/ansible_collections/cisco/dnac/plugins/modules/pnp_device_count_info.py index 5b98a91e5..94dc35fa2 100644 --- a/ansible_collections/cisco/dnac/plugins/modules/pnp_device_count_info.py +++ b/ansible_collections/cisco/dnac/plugins/modules/pnp_device_count_info.py @@ -89,8 +89,8 @@ options: - LastContact query parameter. Device Has Contacted lastContact > 0. type: bool requirements: -- dnacentersdk >= 2.5.5 -- python >= 3.5 +- dnacentersdk >= 2.6.0 +- python >= 3.9 seealso: - name: Cisco DNA Center documentation for Device Onboarding (PnP) GetDeviceCount description: Complete reference of the GetDeviceCount API. diff --git a/ansible_collections/cisco/dnac/plugins/modules/pnp_device_history_info.py b/ansible_collections/cisco/dnac/plugins/modules/pnp_device_history_info.py index 662cc694b..781a2f035 100644 --- a/ansible_collections/cisco/dnac/plugins/modules/pnp_device_history_info.py +++ b/ansible_collections/cisco/dnac/plugins/modules/pnp_device_history_info.py @@ -33,8 +33,8 @@ options: - SortOrder query parameter. Sort Order Ascending (asc) or Descending (des). type: str requirements: -- dnacentersdk >= 2.5.5 -- python >= 3.5 +- dnacentersdk >= 2.6.0 +- python >= 3.9 seealso: - name: Cisco DNA Center documentation for Device Onboarding (PnP) GetDeviceHistory description: Complete reference of the GetDeviceHistory API. diff --git a/ansible_collections/cisco/dnac/plugins/modules/pnp_device_import.py b/ansible_collections/cisco/dnac/plugins/modules/pnp_device_import.py index 78ff2aada..ed0802a80 100644 --- a/ansible_collections/cisco/dnac/plugins/modules/pnp_device_import.py +++ b/ansible_collections/cisco/dnac/plugins/modules/pnp_device_import.py @@ -823,8 +823,8 @@ options: type: dict type: list requirements: -- dnacentersdk >= 2.5.5 -- python >= 3.5 +- dnacentersdk >= 2.6.0 +- python >= 3.9 seealso: - name: Cisco DNA Center documentation for Device Onboarding (PnP) ImportDevicesInBulk description: Complete reference of the ImportDevicesInBulk API. diff --git a/ansible_collections/cisco/dnac/plugins/modules/pnp_device_info.py b/ansible_collections/cisco/dnac/plugins/modules/pnp_device_info.py index 3f0b11bee..06500ec52 100644 --- a/ansible_collections/cisco/dnac/plugins/modules/pnp_device_info.py +++ b/ansible_collections/cisco/dnac/plugins/modules/pnp_device_info.py @@ -126,8 +126,8 @@ options: - Id path parameter. type: str requirements: -- dnacentersdk >= 2.5.5 -- python >= 3.5 +- dnacentersdk >= 2.6.0 +- python >= 3.9 seealso: - name: Cisco DNA Center documentation for Device Onboarding (PnP) GetDeviceById description: Complete reference of the GetDeviceById API. diff --git a/ansible_collections/cisco/dnac/plugins/modules/pnp_device_reset.py b/ansible_collections/cisco/dnac/plugins/modules/pnp_device_reset.py index 97d079c49..df5a7fe15 100644 --- a/ansible_collections/cisco/dnac/plugins/modules/pnp_device_reset.py +++ b/ansible_collections/cisco/dnac/plugins/modules/pnp_device_reset.py @@ -59,8 +59,8 @@ options: description: Pnp Device Reset's workflowId. type: str requirements: -- dnacentersdk >= 2.5.5 -- python >= 3.5 +- dnacentersdk >= 2.6.0 +- python >= 3.9 seealso: - name: Cisco DNA Center documentation for Device Onboarding (PnP) ResetDevice description: Complete reference of the ResetDevice API. diff --git a/ansible_collections/cisco/dnac/plugins/modules/pnp_device_unclaim.py b/ansible_collections/cisco/dnac/plugins/modules/pnp_device_unclaim.py index a1212a688..81ac6a27b 100644 --- a/ansible_collections/cisco/dnac/plugins/modules/pnp_device_unclaim.py +++ b/ansible_collections/cisco/dnac/plugins/modules/pnp_device_unclaim.py @@ -21,8 +21,8 @@ options: elements: str type: list requirements: -- dnacentersdk >= 2.5.5 -- python >= 3.5 +- dnacentersdk >= 2.6.0 +- python >= 3.9 seealso: - name: Cisco DNA Center documentation for Device Onboarding (PnP) UnClaimDevice description: Complete reference of the UnClaimDevice API. diff --git a/ansible_collections/cisco/dnac/plugins/modules/pnp_global_settings.py b/ansible_collections/cisco/dnac/plugins/modules/pnp_global_settings.py index fa5ff41b8..b7bd4f09e 100644 --- a/ansible_collections/cisco/dnac/plugins/modules/pnp_global_settings.py +++ b/ansible_collections/cisco/dnac/plugins/modules/pnp_global_settings.py @@ -158,8 +158,8 @@ options: description: Pnp Global Settings's version. type: int requirements: -- dnacentersdk >= 2.5.5 -- python >= 3.5 +- dnacentersdk >= 2.6.0 +- python >= 3.9 seealso: - name: Cisco DNA Center documentation for Device Onboarding (PnP) UpdatePnPGlobalSettings description: Complete reference of the UpdatePnPGlobalSettings API. diff --git a/ansible_collections/cisco/dnac/plugins/modules/pnp_global_settings_info.py b/ansible_collections/cisco/dnac/plugins/modules/pnp_global_settings_info.py index 9347be595..e9c124ec5 100644 --- a/ansible_collections/cisco/dnac/plugins/modules/pnp_global_settings_info.py +++ b/ansible_collections/cisco/dnac/plugins/modules/pnp_global_settings_info.py @@ -20,8 +20,8 @@ options: description: Additional headers. type: dict requirements: -- dnacentersdk >= 2.5.5 -- python >= 3.5 +- dnacentersdk >= 2.6.0 +- python >= 3.9 seealso: - name: Cisco DNA Center documentation for Device Onboarding (PnP) GetPnPGlobalSettings description: Complete reference of the GetPnPGlobalSettings API. diff --git a/ansible_collections/cisco/dnac/plugins/modules/pnp_intent.py b/ansible_collections/cisco/dnac/plugins/modules/pnp_intent.py index 3c71046a9..15d00b0dc 100644 --- a/ansible_collections/cisco/dnac/plugins/modules/pnp_intent.py +++ b/ansible_collections/cisco/dnac/plugins/modules/pnp_intent.py @@ -158,7 +158,7 @@ options: - TYPICAL requirements: - dnacentersdk == 2.6.10 - - python >= 3.5 + - python >= 3.9 notes: - SDK Method used are device_onboarding_pnp.DeviceOnboardingPnp.add_device, device_onboarding_pnp.DeviceOnboardingPnp.get_device_list, @@ -429,6 +429,7 @@ class PnP(DnacBase): family="sites", function='get_site', params={"name": self.want.get("site_name")}, + op_modifies=True, ) except Exception: self.log("Exception occurred as site \ @@ -467,6 +468,7 @@ class PnP(DnacBase): family="sites", function='get_site', params={"name": self.want.get("site_name")}, + op_modifies=True, ) except Exception: self.log("Exception occurred as \ @@ -632,7 +634,7 @@ class PnP(DnacBase): self.pnp_cred_failure(msg=msg) claim_params["rfProfile"] = self.validated_config[0]["rf_profile"] - self.log("Paramters used for claiming are {0}".format(str(claim_params)), "INFO") + self.log("Parameters used for claiming are {0}".format(str(claim_params)), "INFO") return claim_params def get_reset_params(self): @@ -698,7 +700,8 @@ class PnP(DnacBase): device_response = self.dnac_apply['exec']( family="device_onboarding_pnp", function='get_device_list', - params={"serial_number": self.want.get("serial_number")} + params={"serial_number": self.want.get("serial_number")}, + op_modifies=True, ) self.log("Device details for the device with serial \ number '{0}': {1}".format(self.want.get("serial_number"), str(device_response)), "DEBUG") @@ -721,6 +724,7 @@ class PnP(DnacBase): family="software_image_management_swim", function='get_software_image_details', params=self.want.get("image_params"), + op_modifies=True, ) image_list = image_response.get("response") self.log("Image details obtained from the API 'get_software_image_details': {0}".format(str(image_response)), "DEBUG") @@ -730,13 +734,15 @@ class PnP(DnacBase): family="configuration_templates", function='gets_the_templates_available', params={"project_names": self.want.get("project_name")}, + op_modifies=True, ) self.log("List of templates under the project '{0}': {1}".format(self.want.get("project_name"), str(template_list)), "DEBUG") dev_details_response = self.dnac_apply['exec']( family="device_onboarding_pnp", function="get_device_by_id", - params={"id": device_response[0].get("id")} + params={"id": device_response[0].get("id")}, + op_modifies=True, ) self.log("Device details retrieved after calling the 'get_device_by_id' API: {0}".format(str(dev_details_response)), "DEBUG") install_mode = dev_details_response.get("deviceInfo").get("mode") @@ -899,7 +905,8 @@ class PnP(DnacBase): multi_device_response = self.dnac_apply['exec']( family="device_onboarding_pnp", function='get_device_list', - params={"serial_number": device["deviceInfo"]["serialNumber"]} + params={"serial_number": device["deviceInfo"]["serialNumber"]}, + op_modifies=True, ) self.log("Device details for serial number {0} \ obtained from the API 'get_device_list': {1}".format(device["deviceInfo"]["serialNumber"], str(multi_device_response)), "DEBUG") @@ -1034,7 +1041,8 @@ class PnP(DnacBase): dev_details_response = self.dnac_apply['exec']( family="device_onboarding_pnp", function="get_device_by_id", - params={"id": self.have["device_id"]} + params={"id": self.have["device_id"]}, + op_modifies=True, ) self.log("Response from 'get_device_by_id' API for device details: {0}".format(str(dev_details_response)), "DEBUG") @@ -1133,7 +1141,8 @@ class PnP(DnacBase): multi_device_response = self.dnac_apply['exec']( family="device_onboarding_pnp", function='get_device_list', - params={"serial_number": device["deviceInfo"]["serialNumber"]} + params={"serial_number": device["deviceInfo"]["serialNumber"]}, + op_modifies=True, ) self.log("Response from 'get_device_list' API for claiming: {0}".format(str(multi_device_response)), "DEBUG") if multi_device_response and len(multi_device_response) == 1: @@ -1190,7 +1199,8 @@ class PnP(DnacBase): device_response = self.dnac_apply['exec']( family="device_onboarding_pnp", function='get_device_list', - params={"serial_number": device["deviceInfo"]["serialNumber"]} + params={"serial_number": device["deviceInfo"]["serialNumber"]}, + op_modifies=True, ) if (device_response and (len(device_response) == 1)): msg = ( @@ -1230,7 +1240,8 @@ class PnP(DnacBase): device_response = self.dnac_apply['exec']( family="device_onboarding_pnp", function='get_device_list', - params={"serial_number": device["deviceInfo"]["serialNumber"]} + params={"serial_number": device["deviceInfo"]["serialNumber"]}, + op_modifies=True, ) if not (device_response and (len(device_response) == 1)): msg = ( diff --git a/ansible_collections/cisco/dnac/plugins/modules/pnp_server_profile_update.py b/ansible_collections/cisco/dnac/plugins/modules/pnp_server_profile_update.py index b6528b96b..ee90a6978 100644 --- a/ansible_collections/cisco/dnac/plugins/modules/pnp_server_profile_update.py +++ b/ansible_collections/cisco/dnac/plugins/modules/pnp_server_profile_update.py @@ -99,8 +99,8 @@ options: description: Pnp Server Profile Update's virtualAccountId. type: str requirements: -- dnacentersdk >= 2.5.5 -- python >= 3.5 +- dnacentersdk >= 2.6.0 +- python >= 3.9 seealso: - name: Cisco DNA Center documentation for Device Onboarding (PnP) UpdatePnPServerProfile description: Complete reference of the UpdatePnPServerProfile API. diff --git a/ansible_collections/cisco/dnac/plugins/modules/pnp_smart_account_domains_info.py b/ansible_collections/cisco/dnac/plugins/modules/pnp_smart_account_domains_info.py index 6f57ce11d..bc612723a 100644 --- a/ansible_collections/cisco/dnac/plugins/modules/pnp_smart_account_domains_info.py +++ b/ansible_collections/cisco/dnac/plugins/modules/pnp_smart_account_domains_info.py @@ -20,8 +20,8 @@ options: description: Additional headers. type: dict requirements: -- dnacentersdk >= 2.5.5 -- python >= 3.5 +- dnacentersdk >= 2.6.0 +- python >= 3.9 seealso: - name: Cisco DNA Center documentation for Device Onboarding (PnP) GetSmartAccountList description: Complete reference of the GetSmartAccountList API. diff --git a/ansible_collections/cisco/dnac/plugins/modules/pnp_virtual_account_add.py b/ansible_collections/cisco/dnac/plugins/modules/pnp_virtual_account_add.py index 0f8140822..7a3ceef87 100644 --- a/ansible_collections/cisco/dnac/plugins/modules/pnp_virtual_account_add.py +++ b/ansible_collections/cisco/dnac/plugins/modules/pnp_virtual_account_add.py @@ -100,8 +100,8 @@ options: description: Pnp Virtual Account Add's virtualAccountId. type: str requirements: -- dnacentersdk >= 2.5.5 -- python >= 3.5 +- dnacentersdk >= 2.6.0 +- python >= 3.9 seealso: - name: Cisco DNA Center documentation for Device Onboarding (PnP) AddVirtualAccount description: Complete reference of the AddVirtualAccount API. diff --git a/ansible_collections/cisco/dnac/plugins/modules/pnp_virtual_account_deregister.py b/ansible_collections/cisco/dnac/plugins/modules/pnp_virtual_account_deregister.py index 8f0d9d432..06af57d3b 100644 --- a/ansible_collections/cisco/dnac/plugins/modules/pnp_virtual_account_deregister.py +++ b/ansible_collections/cisco/dnac/plugins/modules/pnp_virtual_account_deregister.py @@ -26,8 +26,8 @@ options: description: Name query parameter. Virtual Account Name. type: str requirements: -- dnacentersdk >= 2.5.5 -- python >= 3.5 +- dnacentersdk >= 2.6.0 +- python >= 3.9 seealso: - name: Cisco DNA Center documentation for Device Onboarding (PnP) DeregisterVirtualAccount description: Complete reference of the DeregisterVirtualAccount API. diff --git a/ansible_collections/cisco/dnac/plugins/modules/pnp_virtual_account_devices_sync.py b/ansible_collections/cisco/dnac/plugins/modules/pnp_virtual_account_devices_sync.py index 6a1c0da09..208bd3352 100644 --- a/ansible_collections/cisco/dnac/plugins/modules/pnp_virtual_account_devices_sync.py +++ b/ansible_collections/cisco/dnac/plugins/modules/pnp_virtual_account_devices_sync.py @@ -99,8 +99,8 @@ options: description: Pnp Virtual Account Devices Sync's virtualAccountId. type: str requirements: -- dnacentersdk >= 2.5.5 -- python >= 3.5 +- dnacentersdk >= 2.6.0 +- python >= 3.9 seealso: - name: Cisco DNA Center documentation for Device Onboarding (PnP) SyncVirtualAccountDevices description: Complete reference of the SyncVirtualAccountDevices API. diff --git a/ansible_collections/cisco/dnac/plugins/modules/pnp_virtual_account_sync_result_info.py b/ansible_collections/cisco/dnac/plugins/modules/pnp_virtual_account_sync_result_info.py index e3c37abe0..61a07cb79 100644 --- a/ansible_collections/cisco/dnac/plugins/modules/pnp_virtual_account_sync_result_info.py +++ b/ansible_collections/cisco/dnac/plugins/modules/pnp_virtual_account_sync_result_info.py @@ -28,8 +28,8 @@ options: - Name path parameter. Virtual Account Name. type: str requirements: -- dnacentersdk >= 2.5.5 -- python >= 3.5 +- dnacentersdk >= 2.6.0 +- python >= 3.9 seealso: - name: Cisco DNA Center documentation for Device Onboarding (PnP) GetSyncResultForVirtualAccount description: Complete reference of the GetSyncResultForVirtualAccount API. diff --git a/ansible_collections/cisco/dnac/plugins/modules/pnp_virtual_accounts_info.py b/ansible_collections/cisco/dnac/plugins/modules/pnp_virtual_accounts_info.py index 40ed3ac75..635a189d5 100644 --- a/ansible_collections/cisco/dnac/plugins/modules/pnp_virtual_accounts_info.py +++ b/ansible_collections/cisco/dnac/plugins/modules/pnp_virtual_accounts_info.py @@ -24,8 +24,8 @@ options: - Domain path parameter. Smart Account Domain. type: str requirements: -- dnacentersdk >= 2.5.5 -- python >= 3.5 +- dnacentersdk >= 2.6.0 +- python >= 3.9 seealso: - name: Cisco DNA Center documentation for Device Onboarding (PnP) GetVirtualAccountList description: Complete reference of the GetVirtualAccountList API. diff --git a/ansible_collections/cisco/dnac/plugins/modules/pnp_workflow.py b/ansible_collections/cisco/dnac/plugins/modules/pnp_workflow.py index 5a5850959..d8658e0ea 100644 --- a/ansible_collections/cisco/dnac/plugins/modules/pnp_workflow.py +++ b/ansible_collections/cisco/dnac/plugins/modules/pnp_workflow.py @@ -128,8 +128,8 @@ options: description: Pnp Workflow's version. type: int requirements: -- dnacentersdk >= 2.5.5 -- python >= 3.5 +- dnacentersdk >= 2.6.0 +- python >= 3.9 seealso: - name: Cisco DNA Center documentation for Device Onboarding (PnP) AddAWorkflow description: Complete reference of the AddAWorkflow API. diff --git a/ansible_collections/cisco/dnac/plugins/modules/pnp_workflow_count_info.py b/ansible_collections/cisco/dnac/plugins/modules/pnp_workflow_count_info.py index 215330a78..3c835c119 100644 --- a/ansible_collections/cisco/dnac/plugins/modules/pnp_workflow_count_info.py +++ b/ansible_collections/cisco/dnac/plugins/modules/pnp_workflow_count_info.py @@ -25,8 +25,8 @@ options: elements: str type: list requirements: -- dnacentersdk >= 2.5.5 -- python >= 3.5 +- dnacentersdk >= 2.6.0 +- python >= 3.9 seealso: - name: Cisco DNA Center documentation for Device Onboarding (PnP) GetWorkflowCount description: Complete reference of the GetWorkflowCount API. diff --git a/ansible_collections/cisco/dnac/plugins/modules/pnp_workflow_info.py b/ansible_collections/cisco/dnac/plugins/modules/pnp_workflow_info.py index 7a00e17bc..d91ea342b 100644 --- a/ansible_collections/cisco/dnac/plugins/modules/pnp_workflow_info.py +++ b/ansible_collections/cisco/dnac/plugins/modules/pnp_workflow_info.py @@ -55,8 +55,8 @@ options: - Id path parameter. type: str requirements: -- dnacentersdk >= 2.5.5 -- python >= 3.5 +- dnacentersdk >= 2.6.0 +- python >= 3.9 seealso: - name: Cisco DNA Center documentation for Device Onboarding (PnP) GetWorkflowById description: Complete reference of the GetWorkflowById API. diff --git a/ansible_collections/cisco/dnac/plugins/modules/pnp_workflow_manager.py b/ansible_collections/cisco/dnac/plugins/modules/pnp_workflow_manager.py index e1b334f71..909670645 100644 --- a/ansible_collections/cisco/dnac/plugins/modules/pnp_workflow_manager.py +++ b/ansible_collections/cisco/dnac/plugins/modules/pnp_workflow_manager.py @@ -158,7 +158,7 @@ options: - TYPICAL requirements: - dnacentersdk == 2.6.10 - - python >= 3.5 + - python >= 3.9 notes: - SDK Method used are device_onboarding_pnp.DeviceOnboardingPnp.add_device, device_onboarding_pnp.DeviceOnboardingPnp.get_device_list, @@ -429,6 +429,7 @@ class PnP(DnacBase): family="sites", function='get_site', params={"name": self.want.get("site_name")}, + op_modifies=True, ) except Exception: self.log("Exception occurred as site \ @@ -467,6 +468,7 @@ class PnP(DnacBase): family="sites", function='get_site', params={"name": self.want.get("site_name")}, + op_modifies=True, ) except Exception: self.log("Exception occurred as \ @@ -632,7 +634,7 @@ class PnP(DnacBase): self.pnp_cred_failure(msg=msg) claim_params["rfProfile"] = self.validated_config[0]["rf_profile"] - self.log("Paramters used for claiming are {0}".format(str(claim_params)), "INFO") + self.log("Parameters used for claiming are {0}".format(str(claim_params)), "INFO") return claim_params def get_reset_params(self): @@ -698,7 +700,8 @@ class PnP(DnacBase): device_response = self.dnac_apply['exec']( family="device_onboarding_pnp", function='get_device_list', - params={"serial_number": self.want.get("serial_number")} + params={"serial_number": self.want.get("serial_number")}, + op_modifies=True, ) self.log("Device details for the device with serial \ number '{0}': {1}".format(self.want.get("serial_number"), str(device_response)), "DEBUG") @@ -721,6 +724,7 @@ class PnP(DnacBase): family="software_image_management_swim", function='get_software_image_details', params=self.want.get("image_params"), + op_modifies=True, ) image_list = image_response.get("response") self.log("Image details obtained from the API 'get_software_image_details': {0}".format(str(image_response)), "DEBUG") @@ -730,13 +734,15 @@ class PnP(DnacBase): family="configuration_templates", function='gets_the_templates_available', params={"project_names": self.want.get("project_name")}, + op_modifies=True, ) self.log("List of templates under the project '{0}': {1}".format(self.want.get("project_name"), str(template_list)), "DEBUG") dev_details_response = self.dnac_apply['exec']( family="device_onboarding_pnp", function="get_device_by_id", - params={"id": device_response[0].get("id")} + params={"id": device_response[0].get("id")}, + op_modifies=True, ) self.log("Device details retrieved after calling the 'get_device_by_id' API: {0}".format(str(dev_details_response)), "DEBUG") install_mode = dev_details_response.get("deviceInfo").get("mode") @@ -899,7 +905,8 @@ class PnP(DnacBase): multi_device_response = self.dnac_apply['exec']( family="device_onboarding_pnp", function='get_device_list', - params={"serial_number": device["deviceInfo"]["serialNumber"]} + params={"serial_number": device["deviceInfo"]["serialNumber"]}, + op_modifies=True, ) self.log("Device details for serial number {0} \ obtained from the API 'get_device_list': {1}".format(device["deviceInfo"]["serialNumber"], str(multi_device_response)), "DEBUG") @@ -1034,7 +1041,8 @@ class PnP(DnacBase): dev_details_response = self.dnac_apply['exec']( family="device_onboarding_pnp", function="get_device_by_id", - params={"id": self.have["device_id"]} + params={"id": self.have["device_id"]}, + op_modifies=True, ) self.log("Response from 'get_device_by_id' API for device details: {0}".format(str(dev_details_response)), "DEBUG") @@ -1133,7 +1141,8 @@ class PnP(DnacBase): multi_device_response = self.dnac_apply['exec']( family="device_onboarding_pnp", function='get_device_list', - params={"serial_number": device["deviceInfo"]["serialNumber"]} + params={"serial_number": device["deviceInfo"]["serialNumber"]}, + op_modifies=True, ) self.log("Response from 'get_device_list' API for claiming: {0}".format(str(multi_device_response)), "DEBUG") if multi_device_response and len(multi_device_response) == 1: @@ -1190,7 +1199,8 @@ class PnP(DnacBase): device_response = self.dnac_apply['exec']( family="device_onboarding_pnp", function='get_device_list', - params={"serial_number": device["deviceInfo"]["serialNumber"]} + params={"serial_number": device["deviceInfo"]["serialNumber"]}, + op_modifies=True, ) if (device_response and (len(device_response) == 1)): msg = ( @@ -1230,7 +1240,8 @@ class PnP(DnacBase): device_response = self.dnac_apply['exec']( family="device_onboarding_pnp", function='get_device_list', - params={"serial_number": device["deviceInfo"]["serialNumber"]} + params={"serial_number": device["deviceInfo"]["serialNumber"]}, + op_modifies=True, ) if not (device_response and (len(device_response) == 1)): msg = ( diff --git a/ansible_collections/cisco/dnac/plugins/modules/profiling_rules_count_info.py b/ansible_collections/cisco/dnac/plugins/modules/profiling_rules_count_info.py index a3181b3c6..461adba26 100644 --- a/ansible_collections/cisco/dnac/plugins/modules/profiling_rules_count_info.py +++ b/ansible_collections/cisco/dnac/plugins/modules/profiling_rules_count_info.py @@ -29,8 +29,8 @@ options: - IncludeDeleted query parameter. Flag to indicate whether deleted rules should be part of the records fetched. type: bool requirements: -- dnacentersdk >= 2.5.5 -- python >= 3.5 +- dnacentersdk >= 2.6.0 +- python >= 3.9 notes: - SDK Method used are policy.Policy.get_count_of_profiling_rules, diff --git a/ansible_collections/cisco/dnac/plugins/modules/profiling_rules_in_bulk_create.py b/ansible_collections/cisco/dnac/plugins/modules/profiling_rules_in_bulk_create.py index 8e5b49c2d..ec2bfc306 100644 --- a/ansible_collections/cisco/dnac/plugins/modules/profiling_rules_in_bulk_create.py +++ b/ansible_collections/cisco/dnac/plugins/modules/profiling_rules_in_bulk_create.py @@ -121,8 +121,8 @@ options: type: list type: list requirements: -- dnacentersdk >= 2.5.5 -- python >= 3.5 +- dnacentersdk >= 2.6.0 +- python >= 3.9 notes: - SDK Method used are policy.Policy.import_profiling_rules_in_bulk, diff --git a/ansible_collections/cisco/dnac/plugins/modules/projects_details_info.py b/ansible_collections/cisco/dnac/plugins/modules/projects_details_info.py index 704c881e2..2185060fd 100644 --- a/ansible_collections/cisco/dnac/plugins/modules/projects_details_info.py +++ b/ansible_collections/cisco/dnac/plugins/modules/projects_details_info.py @@ -40,8 +40,8 @@ options: - SortOrder query parameter. Sort Order Ascending (asc) or Descending (dsc). type: str requirements: -- dnacentersdk >= 2.5.5 -- python >= 3.5 +- dnacentersdk >= 2.6.0 +- python >= 3.9 seealso: - name: Cisco DNA Center documentation for Configuration Templates GetProjectsDetails description: Complete reference of the GetProjectsDetails API. diff --git a/ansible_collections/cisco/dnac/plugins/modules/provision_intent.py b/ansible_collections/cisco/dnac/plugins/modules/provision_intent.py index 4a3c8a228..1c19ed0c7 100644 --- a/ansible_collections/cisco/dnac/plugins/modules/provision_intent.py +++ b/ansible_collections/cisco/dnac/plugins/modules/provision_intent.py @@ -74,7 +74,7 @@ options: requirements: - dnacentersdk == 2.4.5 -- python >= 3.5 +- python >= 3.9 notes: - SDK Methods used are sites.Sites.get_site, @@ -246,7 +246,8 @@ class Dnacprovision(DnacBase): dev_response = self.dnac_apply['exec']( family="devices", function='get_network_device_by_ip', - params={"ip_address": self.validated_config[0]["management_ip_address"]} + params={"ip_address": self.validated_config[0]["management_ip_address"]}, + op_modifies=True ) dev_dict = dev_response.get("response") @@ -282,6 +283,7 @@ class Dnacprovision(DnacBase): family="task", function='get_task_by_id', params=params, + op_modifies=True ) response = response.response if response.get('isError') or re.search( @@ -321,6 +323,7 @@ class Dnacprovision(DnacBase): family="sites", function='get_site', params={"name": site_name}, + op_modifies=True ) except Exception: self.module.fail_json(msg="Site not found", response=[]) @@ -403,7 +406,8 @@ class Dnacprovision(DnacBase): response = self.dnac_apply['exec']( family="devices", function='get_network_device_by_ip', - params={"management_ip_address": self.validated_config[0]["management_ip_address"]} + params={"management_ip_address": self.validated_config[0]["management_ip_address"]}, + op_modifies=True ) wireless_params[0]["deviceName"] = response.get("response")[0].get("hostname") diff --git a/ansible_collections/cisco/dnac/plugins/modules/provision_workflow_manager.py b/ansible_collections/cisco/dnac/plugins/modules/provision_workflow_manager.py index 27ae58141..cd99f3de6 100644 --- a/ansible_collections/cisco/dnac/plugins/modules/provision_workflow_manager.py +++ b/ansible_collections/cisco/dnac/plugins/modules/provision_workflow_manager.py @@ -75,7 +75,7 @@ options: requirements: - dnacentersdk == 2.4.5 -- python >= 3.5 +- python >= 3.9 notes: - SDK Methods used are sites.Sites.get_site, @@ -251,7 +251,8 @@ class Provision(DnacBase): dev_response = self.dnac_apply['exec']( family="devices", function='get_network_device_by_ip', - params={"ip_address": self.validated_config[0]["management_ip_address"]} + params={"ip_address": self.validated_config[0]["management_ip_address"]}, + op_modifies=True ) self.log("The device response from 'get_network_device_by_ip' API is {0}".format(str(dev_response)), "DEBUG") @@ -289,6 +290,7 @@ class Provision(DnacBase): family="task", function='get_task_by_id', params=params, + op_modifies=True ) self.log("Response collected from 'get_task_by_id' API is {0}".format(str(response)), "DEBUG") response = response.response @@ -330,6 +332,7 @@ class Provision(DnacBase): family="sites", function='get_site', params={"name": site_name_hierarchy}, + op_modifies=True ) except Exception: self.log("Exception occurred as \ @@ -418,7 +421,8 @@ class Provision(DnacBase): response = self.dnac_apply['exec']( family="devices", function='get_network_device_by_ip', - params={"management_ip_address": self.validated_config[0]["management_ip_address"]} + params={"management_ip_address": self.validated_config[0]["management_ip_address"]}, + op_modifies=True ) self.log("Response collected from 'get_network_device_by_ip' is:{0}".format(str(response)), "DEBUG") @@ -475,17 +479,14 @@ class Provision(DnacBase): device_type = self.want.get("device_type") if device_type == "wired": - try: - status_response = self.dnac_apply['exec']( - family="sda", - function="get_provisioned_wired_device", - op_modifies=True, - params={ - "device_management_ip_address": self.validated_config[0]["management_ip_address"] - }, - ) - except Exception: - status_response = {} + status_response = self.dnac_apply['exec']( + family="sda", + function="get_provisioned_wired_device", + op_modifies=True, + params={ + "device_management_ip_address": self.validated_config[0]["management_ip_address"] + }, + ) self.log("Wired device's status Response collected from 'get_provisioned_wired_device' API is:{0}".format(str(status_response)), "DEBUG") status = status_response.get("status") self.log("The provisioned status of the wired device is {0}".format(status), "INFO") diff --git a/ansible_collections/cisco/dnac/plugins/modules/qos_device_interface.py b/ansible_collections/cisco/dnac/plugins/modules/qos_device_interface.py index 2c7881cb7..e9b67c760 100644 --- a/ansible_collections/cisco/dnac/plugins/modules/qos_device_interface.py +++ b/ansible_collections/cisco/dnac/plugins/modules/qos_device_interface.py @@ -70,8 +70,8 @@ options: type: list type: list requirements: -- dnacentersdk >= 2.5.5 -- python >= 3.5 +- dnacentersdk >= 2.6.0 +- python >= 3.9 seealso: - name: Cisco DNA Center documentation for Application Policy CreateQosDeviceInterfaceInfo description: Complete reference of the CreateQosDeviceInterfaceInfo API. diff --git a/ansible_collections/cisco/dnac/plugins/modules/qos_device_interface_info.py b/ansible_collections/cisco/dnac/plugins/modules/qos_device_interface_info.py index 98f070c58..ad7bb2bbe 100644 --- a/ansible_collections/cisco/dnac/plugins/modules/qos_device_interface_info.py +++ b/ansible_collections/cisco/dnac/plugins/modules/qos_device_interface_info.py @@ -24,8 +24,8 @@ options: - NetworkDeviceId query parameter. Network device id. type: str requirements: -- dnacentersdk >= 2.5.5 -- python >= 3.5 +- dnacentersdk >= 2.6.0 +- python >= 3.9 seealso: - name: Cisco DNA Center documentation for Application Policy GetQosDeviceInterfaceInfo description: Complete reference of the GetQosDeviceInterfaceInfo API. diff --git a/ansible_collections/cisco/dnac/plugins/modules/qos_device_interface_info_count_info.py b/ansible_collections/cisco/dnac/plugins/modules/qos_device_interface_info_count_info.py index fd872ab6e..f77c2ce31 100644 --- a/ansible_collections/cisco/dnac/plugins/modules/qos_device_interface_info_count_info.py +++ b/ansible_collections/cisco/dnac/plugins/modules/qos_device_interface_info_count_info.py @@ -20,8 +20,8 @@ options: description: Additional headers. type: dict requirements: -- dnacentersdk >= 2.5.5 -- python >= 3.5 +- dnacentersdk >= 2.6.0 +- python >= 3.9 seealso: - name: Cisco DNA Center documentation for Application Policy GetQosDeviceInterfaceInfoCount description: Complete reference of the GetQosDeviceInterfaceInfoCount API. diff --git a/ansible_collections/cisco/dnac/plugins/modules/reports.py b/ansible_collections/cisco/dnac/plugins/modules/reports.py index 039746e73..3e7eab25c 100644 --- a/ansible_collections/cisco/dnac/plugins/modules/reports.py +++ b/ansible_collections/cisco/dnac/plugins/modules/reports.py @@ -103,8 +103,8 @@ options: description: Version of viewgroup for the report. type: str requirements: -- dnacentersdk >= 2.5.5 -- python >= 3.5 +- dnacentersdk >= 2.6.0 +- python >= 3.9 seealso: - name: Cisco DNA Center documentation for Reports CreateOrScheduleAReport description: Complete reference of the CreateOrScheduleAReport API. diff --git a/ansible_collections/cisco/dnac/plugins/modules/reports_executions_info.py b/ansible_collections/cisco/dnac/plugins/modules/reports_executions_info.py index 2002682db..f12cd7caa 100644 --- a/ansible_collections/cisco/dnac/plugins/modules/reports_executions_info.py +++ b/ansible_collections/cisco/dnac/plugins/modules/reports_executions_info.py @@ -44,8 +44,8 @@ options: - The filename used to save the download file. type: str requirements: -- dnacentersdk >= 2.5.5 -- python >= 3.5 +- dnacentersdk >= 2.6.0 +- python >= 3.9 seealso: - name: Cisco DNA Center documentation for Reports DownloadReportContent description: Complete reference of the DownloadReportContent API. diff --git a/ansible_collections/cisco/dnac/plugins/modules/reports_info.py b/ansible_collections/cisco/dnac/plugins/modules/reports_info.py index 963b6bb16..aed7e10df 100644 --- a/ansible_collections/cisco/dnac/plugins/modules/reports_info.py +++ b/ansible_collections/cisco/dnac/plugins/modules/reports_info.py @@ -34,8 +34,8 @@ options: - ReportId path parameter. ReportId of report. type: str requirements: -- dnacentersdk >= 2.5.5 -- python >= 3.5 +- dnacentersdk >= 2.6.0 +- python >= 3.9 seealso: - name: Cisco DNA Center documentation for Reports GetAScheduledReport description: Complete reference of the GetAScheduledReport API. diff --git a/ansible_collections/cisco/dnac/plugins/modules/reports_view_group_info.py b/ansible_collections/cisco/dnac/plugins/modules/reports_view_group_info.py index 71fd405a9..76b131718 100644 --- a/ansible_collections/cisco/dnac/plugins/modules/reports_view_group_info.py +++ b/ansible_collections/cisco/dnac/plugins/modules/reports_view_group_info.py @@ -28,8 +28,8 @@ options: - ViewGroupId path parameter. ViewGroupId of viewgroup. type: str requirements: -- dnacentersdk >= 2.5.5 -- python >= 3.5 +- dnacentersdk >= 2.6.0 +- python >= 3.9 seealso: - name: Cisco DNA Center documentation for Reports GetAllViewGroups description: Complete reference of the GetAllViewGroups API. diff --git a/ansible_collections/cisco/dnac/plugins/modules/reports_view_group_view_info.py b/ansible_collections/cisco/dnac/plugins/modules/reports_view_group_view_info.py index 791e4a0d6..11889bac9 100644 --- a/ansible_collections/cisco/dnac/plugins/modules/reports_view_group_view_info.py +++ b/ansible_collections/cisco/dnac/plugins/modules/reports_view_group_view_info.py @@ -30,8 +30,8 @@ options: - ViewId path parameter. View id of view. type: str requirements: -- dnacentersdk >= 2.5.5 -- python >= 3.5 +- dnacentersdk >= 2.6.0 +- python >= 3.9 seealso: - name: Cisco DNA Center documentation for Reports GetViewDetailsForAGivenViewGroup_View description: Complete reference of the GetViewDetailsForAGivenViewGroup_View API. diff --git a/ansible_collections/cisco/dnac/plugins/modules/reserve_ip_subpool.py b/ansible_collections/cisco/dnac/plugins/modules/reserve_ip_subpool.py index 8d0d75295..507b0e078 100644 --- a/ansible_collections/cisco/dnac/plugins/modules/reserve_ip_subpool.py +++ b/ansible_collections/cisco/dnac/plugins/modules/reserve_ip_subpool.py @@ -94,8 +94,8 @@ options: description: Type of the reserve ip sub pool. type: str requirements: -- dnacentersdk >= 2.5.5 -- python >= 3.5 +- dnacentersdk >= 2.6.0 +- python >= 3.9 seealso: - name: Cisco DNA Center documentation for Network Settings ReserveIPSubpool description: Complete reference of the ReserveIPSubpool API. diff --git a/ansible_collections/cisco/dnac/plugins/modules/reserve_ip_subpool_create.py b/ansible_collections/cisco/dnac/plugins/modules/reserve_ip_subpool_create.py index ad78c5f91..699e7c96c 100644 --- a/ansible_collections/cisco/dnac/plugins/modules/reserve_ip_subpool_create.py +++ b/ansible_collections/cisco/dnac/plugins/modules/reserve_ip_subpool_create.py @@ -88,8 +88,8 @@ options: description: Type of the reserve ip sub pool. type: str requirements: -- dnacentersdk >= 2.5.5 -- python >= 3.5 +- dnacentersdk >= 2.6.0 +- python >= 3.9 seealso: - name: Cisco DNA Center documentation for Network Settings ReserveIPSubpool description: Complete reference of the ReserveIPSubpool API. diff --git a/ansible_collections/cisco/dnac/plugins/modules/reserve_ip_subpool_delete.py b/ansible_collections/cisco/dnac/plugins/modules/reserve_ip_subpool_delete.py index d4471c2a9..65ecd4733 100644 --- a/ansible_collections/cisco/dnac/plugins/modules/reserve_ip_subpool_delete.py +++ b/ansible_collections/cisco/dnac/plugins/modules/reserve_ip_subpool_delete.py @@ -20,8 +20,8 @@ options: description: Id path parameter. Id of reserve ip subpool to be deleted. type: str requirements: -- dnacentersdk >= 2.5.5 -- python >= 3.5 +- dnacentersdk >= 2.6.0 +- python >= 3.9 seealso: - name: Cisco DNA Center documentation for Network Settings ReleaseReserveIPSubpool description: Complete reference of the ReleaseReserveIPSubpool API. diff --git a/ansible_collections/cisco/dnac/plugins/modules/reserve_ip_subpool_info.py b/ansible_collections/cisco/dnac/plugins/modules/reserve_ip_subpool_info.py index ab1a52955..ec3c76d16 100644 --- a/ansible_collections/cisco/dnac/plugins/modules/reserve_ip_subpool_info.py +++ b/ansible_collections/cisco/dnac/plugins/modules/reserve_ip_subpool_info.py @@ -32,8 +32,8 @@ options: - Limit query parameter. No of Global Pools to be retrieved. type: int requirements: -- dnacentersdk >= 2.5.5 -- python >= 3.5 +- dnacentersdk >= 2.6.0 +- python >= 3.9 seealso: - name: Cisco DNA Center documentation for Network Settings GetReserveIPSubpool description: Complete reference of the GetReserveIPSubpool API. diff --git a/ansible_collections/cisco/dnac/plugins/modules/reserve_ip_subpool_update.py b/ansible_collections/cisco/dnac/plugins/modules/reserve_ip_subpool_update.py index 3e960395f..4bf71c42c 100644 --- a/ansible_collections/cisco/dnac/plugins/modules/reserve_ip_subpool_update.py +++ b/ansible_collections/cisco/dnac/plugins/modules/reserve_ip_subpool_update.py @@ -72,8 +72,8 @@ options: description: Slaac Support. type: bool requirements: -- dnacentersdk >= 2.5.5 -- python >= 3.5 +- dnacentersdk >= 2.6.0 +- python >= 3.9 seealso: - name: Cisco DNA Center documentation for Network Settings UpdateReserveIPSubpool description: Complete reference of the UpdateReserveIPSubpool API. diff --git a/ansible_collections/cisco/dnac/plugins/modules/role_permissions_info.py b/ansible_collections/cisco/dnac/plugins/modules/role_permissions_info.py index 3f520a697..51957ed06 100644 --- a/ansible_collections/cisco/dnac/plugins/modules/role_permissions_info.py +++ b/ansible_collections/cisco/dnac/plugins/modules/role_permissions_info.py @@ -20,8 +20,8 @@ options: description: Additional headers. type: dict requirements: -- dnacentersdk >= 2.5.5 -- python >= 3.5 +- dnacentersdk >= 2.6.0 +- python >= 3.9 seealso: - name: Cisco DNA Center documentation for User and Roles GetPermissionsAPI description: Complete reference of the GetPermissionsAPI API. diff --git a/ansible_collections/cisco/dnac/plugins/modules/roles_info.py b/ansible_collections/cisco/dnac/plugins/modules/roles_info.py index 3e719be1a..a8ce30ddf 100644 --- a/ansible_collections/cisco/dnac/plugins/modules/roles_info.py +++ b/ansible_collections/cisco/dnac/plugins/modules/roles_info.py @@ -20,8 +20,8 @@ options: description: Additional headers. type: dict requirements: -- dnacentersdk >= 2.5.5 -- python >= 3.5 +- dnacentersdk >= 2.6.0 +- python >= 3.9 seealso: - name: Cisco DNA Center documentation for User and Roles GetRolesAPI description: Complete reference of the GetRolesAPI API. diff --git a/ansible_collections/cisco/dnac/plugins/modules/sda_count_info.py b/ansible_collections/cisco/dnac/plugins/modules/sda_count_info.py index a80b1d359..d942591c1 100644 --- a/ansible_collections/cisco/dnac/plugins/modules/sda_count_info.py +++ b/ansible_collections/cisco/dnac/plugins/modules/sda_count_info.py @@ -20,8 +20,8 @@ options: description: Additional headers. type: dict requirements: -- dnacentersdk >= 2.5.5 -- python >= 3.5 +- dnacentersdk >= 2.6.0 +- python >= 3.9 notes: - SDK Method used are sda.Sda.get_sda_fabric_count, diff --git a/ansible_collections/cisco/dnac/plugins/modules/sda_device_info.py b/ansible_collections/cisco/dnac/plugins/modules/sda_device_info.py index db40c572b..22029fe55 100644 --- a/ansible_collections/cisco/dnac/plugins/modules/sda_device_info.py +++ b/ansible_collections/cisco/dnac/plugins/modules/sda_device_info.py @@ -24,8 +24,8 @@ options: - DeviceManagementIpAddress query parameter. type: str requirements: -- dnacentersdk >= 2.5.5 -- python >= 3.5 +- dnacentersdk >= 2.6.0 +- python >= 3.9 seealso: - name: Cisco DNA Center documentation for SDA GetDeviceInfoFromSDAFabric description: Complete reference of the GetDeviceInfoFromSDAFabric API. diff --git a/ansible_collections/cisco/dnac/plugins/modules/sda_device_role_info.py b/ansible_collections/cisco/dnac/plugins/modules/sda_device_role_info.py index 2a857d803..b06a698a1 100644 --- a/ansible_collections/cisco/dnac/plugins/modules/sda_device_role_info.py +++ b/ansible_collections/cisco/dnac/plugins/modules/sda_device_role_info.py @@ -24,8 +24,8 @@ options: - DeviceManagementIpAddress query parameter. Device Management IP Address. type: str requirements: -- dnacentersdk >= 2.5.5 -- python >= 3.5 +- dnacentersdk >= 2.6.0 +- python >= 3.9 seealso: - name: Cisco DNA Center documentation for SDA GetDeviceRoleInSDAFabric description: Complete reference of the GetDeviceRoleInSDAFabric API. diff --git a/ansible_collections/cisco/dnac/plugins/modules/sda_fabric.py b/ansible_collections/cisco/dnac/plugins/modules/sda_fabric.py index 158e6f1e6..f068b0e1e 100644 --- a/ansible_collections/cisco/dnac/plugins/modules/sda_fabric.py +++ b/ansible_collections/cisco/dnac/plugins/modules/sda_fabric.py @@ -21,8 +21,8 @@ options: description: FabricName query parameter. Fabric Name. type: str requirements: -- dnacentersdk >= 2.5.5 -- python >= 3.5 +- dnacentersdk >= 2.6.0 +- python >= 3.9 notes: - SDK Method used are sda.Sda.add_fabric, diff --git a/ansible_collections/cisco/dnac/plugins/modules/sda_fabric_authentication_profile.py b/ansible_collections/cisco/dnac/plugins/modules/sda_fabric_authentication_profile.py index 51b32887b..925e28fa1 100644 --- a/ansible_collections/cisco/dnac/plugins/modules/sda_fabric_authentication_profile.py +++ b/ansible_collections/cisco/dnac/plugins/modules/sda_fabric_authentication_profile.py @@ -34,8 +34,8 @@ options: description: SiteNameHierarchy query parameter. type: str requirements: -- dnacentersdk >= 2.5.5 -- python >= 3.5 +- dnacentersdk >= 2.6.0 +- python >= 3.9 seealso: - name: Cisco DNA Center documentation for SDA AddDefaultAuthenticationTemplateInSDAFabric description: Complete reference of the AddDefaultAuthenticationTemplateInSDAFabric API. diff --git a/ansible_collections/cisco/dnac/plugins/modules/sda_fabric_authentication_profile_info.py b/ansible_collections/cisco/dnac/plugins/modules/sda_fabric_authentication_profile_info.py index 7d810bb81..619af5f01 100644 --- a/ansible_collections/cisco/dnac/plugins/modules/sda_fabric_authentication_profile_info.py +++ b/ansible_collections/cisco/dnac/plugins/modules/sda_fabric_authentication_profile_info.py @@ -29,8 +29,8 @@ options: - AuthenticateTemplateName query parameter. type: str requirements: -- dnacentersdk >= 2.5.5 -- python >= 3.5 +- dnacentersdk >= 2.6.0 +- python >= 3.9 seealso: - name: Cisco DNA Center documentation for SDA GetDefaultAuthenticationProfileFromSDAFabric description: Complete reference of the GetDefaultAuthenticationProfileFromSDAFabric API. diff --git a/ansible_collections/cisco/dnac/plugins/modules/sda_fabric_border_device.py b/ansible_collections/cisco/dnac/plugins/modules/sda_fabric_border_device.py index 960e9d7cd..e2441daf8 100644 --- a/ansible_collections/cisco/dnac/plugins/modules/sda_fabric_border_device.py +++ b/ansible_collections/cisco/dnac/plugins/modules/sda_fabric_border_device.py @@ -125,8 +125,8 @@ options: type: str type: list requirements: -- dnacentersdk >= 2.5.5 -- python >= 3.5 +- dnacentersdk >= 2.6.0 +- python >= 3.9 seealso: - name: Cisco DNA Center documentation for SDA AddBorderDeviceInSDAFabric description: Complete reference of the AddBorderDeviceInSDAFabric API. diff --git a/ansible_collections/cisco/dnac/plugins/modules/sda_fabric_border_device_info.py b/ansible_collections/cisco/dnac/plugins/modules/sda_fabric_border_device_info.py index 329040201..c4318cd73 100644 --- a/ansible_collections/cisco/dnac/plugins/modules/sda_fabric_border_device_info.py +++ b/ansible_collections/cisco/dnac/plugins/modules/sda_fabric_border_device_info.py @@ -25,8 +25,8 @@ options: - DeviceManagementIpAddress query parameter. type: str requirements: -- dnacentersdk >= 2.5.5 -- python >= 3.5 +- dnacentersdk >= 2.6.0 +- python >= 3.9 seealso: - name: Cisco DNA Center documentation for SDA GetBorderDeviceDetailFromSDAFabric description: Complete reference of the GetBorderDeviceDetailFromSDAFabric API. diff --git a/ansible_collections/cisco/dnac/plugins/modules/sda_fabric_control_plane_device.py b/ansible_collections/cisco/dnac/plugins/modules/sda_fabric_control_plane_device.py index 2f7189b35..ff3ecf449 100644 --- a/ansible_collections/cisco/dnac/plugins/modules/sda_fabric_control_plane_device.py +++ b/ansible_collections/cisco/dnac/plugins/modules/sda_fabric_control_plane_device.py @@ -31,8 +31,8 @@ options: type: str version_added: 4.0.0 requirements: -- dnacentersdk >= 2.5.5 -- python >= 3.5 +- dnacentersdk >= 2.6.0 +- python >= 3.9 seealso: - name: Cisco DNA Center documentation for SDA AddControlPlaneDeviceInSDAFabric description: Complete reference of the AddControlPlaneDeviceInSDAFabric API. diff --git a/ansible_collections/cisco/dnac/plugins/modules/sda_fabric_control_plane_device_info.py b/ansible_collections/cisco/dnac/plugins/modules/sda_fabric_control_plane_device_info.py index 837a4d543..9267a7014 100644 --- a/ansible_collections/cisco/dnac/plugins/modules/sda_fabric_control_plane_device_info.py +++ b/ansible_collections/cisco/dnac/plugins/modules/sda_fabric_control_plane_device_info.py @@ -25,8 +25,8 @@ options: - DeviceManagementIpAddress query parameter. type: str requirements: -- dnacentersdk >= 2.5.5 -- python >= 3.5 +- dnacentersdk >= 2.6.0 +- python >= 3.9 seealso: - name: Cisco DNA Center documentation for SDA GetControlPlaneDeviceFromSDAFabric description: Complete reference of the GetControlPlaneDeviceFromSDAFabric API. diff --git a/ansible_collections/cisco/dnac/plugins/modules/sda_fabric_edge_device.py b/ansible_collections/cisco/dnac/plugins/modules/sda_fabric_edge_device.py index 800ca6d3c..9bcde0422 100644 --- a/ansible_collections/cisco/dnac/plugins/modules/sda_fabric_edge_device.py +++ b/ansible_collections/cisco/dnac/plugins/modules/sda_fabric_edge_device.py @@ -26,8 +26,8 @@ options: type: str version_added: 4.0.0 requirements: -- dnacentersdk >= 2.5.5 -- python >= 3.5 +- dnacentersdk >= 2.6.0 +- python >= 3.9 seealso: - name: Cisco DNA Center documentation for SDA AddEdgeDeviceInSDAFabric description: Complete reference of the AddEdgeDeviceInSDAFabric API. diff --git a/ansible_collections/cisco/dnac/plugins/modules/sda_fabric_edge_device_info.py b/ansible_collections/cisco/dnac/plugins/modules/sda_fabric_edge_device_info.py index 7d94ac466..a4f6eecc2 100644 --- a/ansible_collections/cisco/dnac/plugins/modules/sda_fabric_edge_device_info.py +++ b/ansible_collections/cisco/dnac/plugins/modules/sda_fabric_edge_device_info.py @@ -24,8 +24,8 @@ options: - DeviceManagementIpAddress query parameter. type: str requirements: -- dnacentersdk >= 2.5.5 -- python >= 3.5 +- dnacentersdk >= 2.6.0 +- python >= 3.9 seealso: - name: Cisco DNA Center documentation for SDA GetEdgeDeviceFromSDAFabric description: Complete reference of the GetEdgeDeviceFromSDAFabric API. diff --git a/ansible_collections/cisco/dnac/plugins/modules/sda_fabric_info.py b/ansible_collections/cisco/dnac/plugins/modules/sda_fabric_info.py index c0e49de7d..c44290025 100644 --- a/ansible_collections/cisco/dnac/plugins/modules/sda_fabric_info.py +++ b/ansible_collections/cisco/dnac/plugins/modules/sda_fabric_info.py @@ -24,8 +24,8 @@ options: - FabricName query parameter. Fabric Name. type: str requirements: -- dnacentersdk >= 2.5.5 -- python >= 3.5 +- dnacentersdk >= 2.6.0 +- python >= 3.9 notes: - SDK Method used are sda.Sda.get_sda_fabric_info, diff --git a/ansible_collections/cisco/dnac/plugins/modules/sda_fabric_site.py b/ansible_collections/cisco/dnac/plugins/modules/sda_fabric_site.py index 2b7e6f8d4..eed71ad48 100644 --- a/ansible_collections/cisco/dnac/plugins/modules/sda_fabric_site.py +++ b/ansible_collections/cisco/dnac/plugins/modules/sda_fabric_site.py @@ -31,8 +31,8 @@ options: description: SiteNameHierarchy query parameter. Site Name Hierarchy. type: str requirements: -- dnacentersdk >= 2.5.5 -- python >= 3.5 +- dnacentersdk >= 2.6.0 +- python >= 3.9 seealso: - name: Cisco DNA Center documentation for SDA AddSiteInSDAFabric description: Complete reference of the AddSiteInSDAFabric API. diff --git a/ansible_collections/cisco/dnac/plugins/modules/sda_fabric_site_info.py b/ansible_collections/cisco/dnac/plugins/modules/sda_fabric_site_info.py index c0c115828..bd2e8c177 100644 --- a/ansible_collections/cisco/dnac/plugins/modules/sda_fabric_site_info.py +++ b/ansible_collections/cisco/dnac/plugins/modules/sda_fabric_site_info.py @@ -24,8 +24,8 @@ options: - SiteNameHierarchy query parameter. Site Name Hierarchy. type: str requirements: -- dnacentersdk >= 2.5.5 -- python >= 3.5 +- dnacentersdk >= 2.6.0 +- python >= 3.9 seealso: - name: Cisco DNA Center documentation for SDA GetSiteFromSDAFabric description: Complete reference of the GetSiteFromSDAFabric API. diff --git a/ansible_collections/cisco/dnac/plugins/modules/sda_multicast.py b/ansible_collections/cisco/dnac/plugins/modules/sda_multicast.py index 4ee828f02..6e1045c5d 100644 --- a/ansible_collections/cisco/dnac/plugins/modules/sda_multicast.py +++ b/ansible_collections/cisco/dnac/plugins/modules/sda_multicast.py @@ -56,8 +56,8 @@ options: description: Full path of sda Fabric Site. type: str requirements: -- dnacentersdk >= 2.5.5 -- python >= 3.5 +- dnacentersdk >= 2.6.0 +- python >= 3.9 seealso: - name: Cisco DNA Center documentation for SDA AddMulticastInSDAFabric description: Complete reference of the AddMulticastInSDAFabric API. diff --git a/ansible_collections/cisco/dnac/plugins/modules/sda_multicast_info.py b/ansible_collections/cisco/dnac/plugins/modules/sda_multicast_info.py index 959c9ed2f..2f4ae1218 100644 --- a/ansible_collections/cisco/dnac/plugins/modules/sda_multicast_info.py +++ b/ansible_collections/cisco/dnac/plugins/modules/sda_multicast_info.py @@ -24,8 +24,8 @@ options: - SiteNameHierarchy query parameter. Fabric site name hierarchy. type: str requirements: -- dnacentersdk >= 2.5.5 -- python >= 3.5 +- dnacentersdk >= 2.6.0 +- python >= 3.9 seealso: - name: Cisco DNA Center documentation for SDA GetMulticastDetailsFromSDAFabric description: Complete reference of the GetMulticastDetailsFromSDAFabric API. diff --git a/ansible_collections/cisco/dnac/plugins/modules/sda_port_assignment_for_access_point.py b/ansible_collections/cisco/dnac/plugins/modules/sda_port_assignment_for_access_point.py index 39b7df6e5..c8280407d 100644 --- a/ansible_collections/cisco/dnac/plugins/modules/sda_port_assignment_for_access_point.py +++ b/ansible_collections/cisco/dnac/plugins/modules/sda_port_assignment_for_access_point.py @@ -41,8 +41,8 @@ options: type: str version_added: 4.0.0 requirements: -- dnacentersdk >= 2.5.5 -- python >= 3.5 +- dnacentersdk >= 2.6.0 +- python >= 3.9 seealso: - name: Cisco DNA Center documentation for SDA AddPortAssignmentForAccessPointInSDAFabric description: Complete reference of the AddPortAssignmentForAccessPointInSDAFabric API. diff --git a/ansible_collections/cisco/dnac/plugins/modules/sda_port_assignment_for_access_point_info.py b/ansible_collections/cisco/dnac/plugins/modules/sda_port_assignment_for_access_point_info.py index 45dc1ea39..3cdb7cd3a 100644 --- a/ansible_collections/cisco/dnac/plugins/modules/sda_port_assignment_for_access_point_info.py +++ b/ansible_collections/cisco/dnac/plugins/modules/sda_port_assignment_for_access_point_info.py @@ -29,8 +29,8 @@ options: - InterfaceName query parameter. type: str requirements: -- dnacentersdk >= 2.5.5 -- python >= 3.5 +- dnacentersdk >= 2.6.0 +- python >= 3.9 seealso: - name: Cisco DNA Center documentation for SDA GetPortAssignmentForAccessPointInSDAFabric description: Complete reference of the GetPortAssignmentForAccessPointInSDAFabric API. diff --git a/ansible_collections/cisco/dnac/plugins/modules/sda_port_assignment_for_user_device.py b/ansible_collections/cisco/dnac/plugins/modules/sda_port_assignment_for_user_device.py index 15c389ce6..58664b8e2 100644 --- a/ansible_collections/cisco/dnac/plugins/modules/sda_port_assignment_for_user_device.py +++ b/ansible_collections/cisco/dnac/plugins/modules/sda_port_assignment_for_user_device.py @@ -54,8 +54,8 @@ options: type: str version_added: 4.0.0 requirements: -- dnacentersdk >= 2.5.5 -- python >= 3.5 +- dnacentersdk >= 2.6.0 +- python >= 3.9 seealso: - name: Cisco DNA Center documentation for SDA AddPortAssignmentForUserDeviceInSDAFabric description: Complete reference of the AddPortAssignmentForUserDeviceInSDAFabric API. diff --git a/ansible_collections/cisco/dnac/plugins/modules/sda_port_assignment_for_user_device_info.py b/ansible_collections/cisco/dnac/plugins/modules/sda_port_assignment_for_user_device_info.py index e62e9ae3c..2fdbee046 100644 --- a/ansible_collections/cisco/dnac/plugins/modules/sda_port_assignment_for_user_device_info.py +++ b/ansible_collections/cisco/dnac/plugins/modules/sda_port_assignment_for_user_device_info.py @@ -28,8 +28,8 @@ options: - InterfaceName query parameter. type: str requirements: -- dnacentersdk >= 2.5.5 -- python >= 3.5 +- dnacentersdk >= 2.6.0 +- python >= 3.9 seealso: - name: Cisco DNA Center documentation for SDA GetPortAssignmentForUserDeviceInSDAFabric description: Complete reference of the GetPortAssignmentForUserDeviceInSDAFabric API. diff --git a/ansible_collections/cisco/dnac/plugins/modules/sda_provision_device.py b/ansible_collections/cisco/dnac/plugins/modules/sda_provision_device.py index 97c12fae0..5940634b8 100644 --- a/ansible_collections/cisco/dnac/plugins/modules/sda_provision_device.py +++ b/ansible_collections/cisco/dnac/plugins/modules/sda_provision_device.py @@ -26,8 +26,8 @@ options: description: SiteNameHierarchy of the provisioned device. type: str requirements: -- dnacentersdk >= 2.5.5 -- python >= 3.5 +- dnacentersdk >= 2.6.0 +- python >= 3.9 seealso: - name: Cisco DNA Center documentation for SDA ProvisionWiredDevice description: Complete reference of the ProvisionWiredDevice API. diff --git a/ansible_collections/cisco/dnac/plugins/modules/sda_provision_device_info.py b/ansible_collections/cisco/dnac/plugins/modules/sda_provision_device_info.py index a57d73303..ae78549ec 100644 --- a/ansible_collections/cisco/dnac/plugins/modules/sda_provision_device_info.py +++ b/ansible_collections/cisco/dnac/plugins/modules/sda_provision_device_info.py @@ -24,8 +24,8 @@ options: - DeviceManagementIpAddress query parameter. type: str requirements: -- dnacentersdk >= 2.5.5 -- python >= 3.5 +- dnacentersdk >= 2.6.0 +- python >= 3.9 seealso: - name: Cisco DNA Center documentation for SDA GetProvisionedWiredDevice description: Complete reference of the GetProvisionedWiredDevice API. diff --git a/ansible_collections/cisco/dnac/plugins/modules/sda_virtual_network.py b/ansible_collections/cisco/dnac/plugins/modules/sda_virtual_network.py index 5231d8b95..09d01e5ed 100644 --- a/ansible_collections/cisco/dnac/plugins/modules/sda_virtual_network.py +++ b/ansible_collections/cisco/dnac/plugins/modules/sda_virtual_network.py @@ -24,8 +24,8 @@ options: description: VirtualNetworkName query parameter. type: str requirements: -- dnacentersdk >= 2.5.5 -- python >= 3.5 +- dnacentersdk >= 2.6.0 +- python >= 3.9 seealso: - name: Cisco DNA Center documentation for SDA AddVNInFabric description: Complete reference of the AddVNInFabric API. diff --git a/ansible_collections/cisco/dnac/plugins/modules/sda_virtual_network_info.py b/ansible_collections/cisco/dnac/plugins/modules/sda_virtual_network_info.py index 073937177..560c9179f 100644 --- a/ansible_collections/cisco/dnac/plugins/modules/sda_virtual_network_info.py +++ b/ansible_collections/cisco/dnac/plugins/modules/sda_virtual_network_info.py @@ -28,8 +28,8 @@ options: - SiteNameHierarchy query parameter. type: str requirements: -- dnacentersdk >= 2.5.5 -- python >= 3.5 +- dnacentersdk >= 2.6.0 +- python >= 3.9 seealso: - name: Cisco DNA Center documentation for SDA GetVNFromSDAFabric description: Complete reference of the GetVNFromSDAFabric API. diff --git a/ansible_collections/cisco/dnac/plugins/modules/sda_virtual_network_ip_pool.py b/ansible_collections/cisco/dnac/plugins/modules/sda_virtual_network_ip_pool.py index c0242821c..71bdf744f 100644 --- a/ansible_collections/cisco/dnac/plugins/modules/sda_virtual_network_ip_pool.py +++ b/ansible_collections/cisco/dnac/plugins/modules/sda_virtual_network_ip_pool.py @@ -83,8 +83,8 @@ options: type: str version_added: 4.0.0 requirements: -- dnacentersdk >= 2.5.5 -- python >= 3.5 +- dnacentersdk >= 2.6.0 +- python >= 3.9 seealso: - name: Cisco DNA Center documentation for SDA AddIPPoolInSDAVirtualNetwork description: Complete reference of the AddIPPoolInSDAVirtualNetwork API. diff --git a/ansible_collections/cisco/dnac/plugins/modules/sda_virtual_network_ip_pool_info.py b/ansible_collections/cisco/dnac/plugins/modules/sda_virtual_network_ip_pool_info.py index 205199cf5..35de542c6 100644 --- a/ansible_collections/cisco/dnac/plugins/modules/sda_virtual_network_ip_pool_info.py +++ b/ansible_collections/cisco/dnac/plugins/modules/sda_virtual_network_ip_pool_info.py @@ -34,8 +34,8 @@ options: - IpPoolName query parameter. type: str requirements: -- dnacentersdk >= 2.5.5 -- python >= 3.5 +- dnacentersdk >= 2.6.0 +- python >= 3.9 seealso: - name: Cisco DNA Center documentation for SDA GetIPPoolFromSDAVirtualNetwork description: Complete reference of the GetIPPoolFromSDAVirtualNetwork API. diff --git a/ansible_collections/cisco/dnac/plugins/modules/sda_virtual_network_v2.py b/ansible_collections/cisco/dnac/plugins/modules/sda_virtual_network_v2.py index 37e862ae5..27bffd8d9 100644 --- a/ansible_collections/cisco/dnac/plugins/modules/sda_virtual_network_v2.py +++ b/ansible_collections/cisco/dnac/plugins/modules/sda_virtual_network_v2.py @@ -32,8 +32,8 @@ options: description: Virtual Network Name to be assigned at global level. type: str requirements: -- dnacentersdk >= 2.5.5 -- python >= 3.5 +- dnacentersdk >= 2.6.0 +- python >= 3.9 seealso: - name: Cisco DNA Center documentation for SDA AddVirtualNetworkWithScalableGroups description: Complete reference of the AddVirtualNetworkWithScalableGroups API. diff --git a/ansible_collections/cisco/dnac/plugins/modules/sda_virtual_network_v2_info.py b/ansible_collections/cisco/dnac/plugins/modules/sda_virtual_network_v2_info.py index b1b408c08..fc73454d1 100644 --- a/ansible_collections/cisco/dnac/plugins/modules/sda_virtual_network_v2_info.py +++ b/ansible_collections/cisco/dnac/plugins/modules/sda_virtual_network_v2_info.py @@ -24,8 +24,8 @@ options: - VirtualNetworkName query parameter. type: str requirements: -- dnacentersdk >= 2.5.5 -- python >= 3.5 +- dnacentersdk >= 2.6.0 +- python >= 3.9 seealso: - name: Cisco DNA Center documentation for SDA GetVirtualNetworkWithScalableGroups description: Complete reference of the GetVirtualNetworkWithScalableGroups API. diff --git a/ansible_collections/cisco/dnac/plugins/modules/security_advisories_devices_info.py b/ansible_collections/cisco/dnac/plugins/modules/security_advisories_devices_info.py index 0a0bf0c90..977fe48cd 100644 --- a/ansible_collections/cisco/dnac/plugins/modules/security_advisories_devices_info.py +++ b/ansible_collections/cisco/dnac/plugins/modules/security_advisories_devices_info.py @@ -24,8 +24,8 @@ options: - AdvisoryId path parameter. Advisory ID. type: str requirements: -- dnacentersdk >= 2.5.5 -- python >= 3.5 +- dnacentersdk >= 2.6.0 +- python >= 3.9 seealso: - name: Cisco DNA Center documentation for Security Advisories GetDevicesPerAdvisory description: Complete reference of the GetDevicesPerAdvisory API. diff --git a/ansible_collections/cisco/dnac/plugins/modules/security_advisories_ids_per_device_info.py b/ansible_collections/cisco/dnac/plugins/modules/security_advisories_ids_per_device_info.py index 8bf7638d9..47f2db396 100644 --- a/ansible_collections/cisco/dnac/plugins/modules/security_advisories_ids_per_device_info.py +++ b/ansible_collections/cisco/dnac/plugins/modules/security_advisories_ids_per_device_info.py @@ -24,8 +24,8 @@ options: - DeviceId path parameter. Device instance UUID. type: str requirements: -- dnacentersdk >= 2.5.5 -- python >= 3.5 +- dnacentersdk >= 2.6.0 +- python >= 3.9 seealso: - name: Cisco DNA Center documentation for Security Advisories GetAdvisoryIDsPerDevice description: Complete reference of the GetAdvisoryIDsPerDevice API. diff --git a/ansible_collections/cisco/dnac/plugins/modules/security_advisories_info.py b/ansible_collections/cisco/dnac/plugins/modules/security_advisories_info.py index b0b551cd9..a2d860316 100644 --- a/ansible_collections/cisco/dnac/plugins/modules/security_advisories_info.py +++ b/ansible_collections/cisco/dnac/plugins/modules/security_advisories_info.py @@ -20,8 +20,8 @@ options: description: Additional headers. type: dict requirements: -- dnacentersdk >= 2.5.5 -- python >= 3.5 +- dnacentersdk >= 2.6.0 +- python >= 3.9 seealso: - name: Cisco DNA Center documentation for Security Advisories GetAdvisoriesList description: Complete reference of the GetAdvisoriesList API. diff --git a/ansible_collections/cisco/dnac/plugins/modules/security_advisories_per_device_info.py b/ansible_collections/cisco/dnac/plugins/modules/security_advisories_per_device_info.py index 54735ee13..486bb4654 100644 --- a/ansible_collections/cisco/dnac/plugins/modules/security_advisories_per_device_info.py +++ b/ansible_collections/cisco/dnac/plugins/modules/security_advisories_per_device_info.py @@ -24,8 +24,8 @@ options: - DeviceId path parameter. Device instance UUID. type: str requirements: -- dnacentersdk >= 2.5.5 -- python >= 3.5 +- dnacentersdk >= 2.6.0 +- python >= 3.9 seealso: - name: Cisco DNA Center documentation for Security Advisories GetAdvisoriesPerDevice description: Complete reference of the GetAdvisoriesPerDevice API. diff --git a/ansible_collections/cisco/dnac/plugins/modules/security_advisories_summary_info.py b/ansible_collections/cisco/dnac/plugins/modules/security_advisories_summary_info.py index 4709ca6b9..88440aceb 100644 --- a/ansible_collections/cisco/dnac/plugins/modules/security_advisories_summary_info.py +++ b/ansible_collections/cisco/dnac/plugins/modules/security_advisories_summary_info.py @@ -20,8 +20,8 @@ options: description: Additional headers. type: dict requirements: -- dnacentersdk >= 2.5.5 -- python >= 3.5 +- dnacentersdk >= 2.6.0 +- python >= 3.9 seealso: - name: Cisco DNA Center documentation for Security Advisories GetAdvisoriesSummary description: Complete reference of the GetAdvisoriesSummary API. diff --git a/ansible_collections/cisco/dnac/plugins/modules/sensor.py b/ansible_collections/cisco/dnac/plugins/modules/sensor.py index 4ac0fc8bd..c98887c45 100644 --- a/ansible_collections/cisco/dnac/plugins/modules/sensor.py +++ b/ansible_collections/cisco/dnac/plugins/modules/sensor.py @@ -87,8 +87,8 @@ options: description: TemplateName query parameter. type: str requirements: -- dnacentersdk >= 2.5.5 -- python >= 3.5 +- dnacentersdk >= 2.6.0 +- python >= 3.9 seealso: - name: Cisco DNA Center documentation for Sensors CreateSensorTestTemplate description: Complete reference of the CreateSensorTestTemplate API. diff --git a/ansible_collections/cisco/dnac/plugins/modules/sensor_info.py b/ansible_collections/cisco/dnac/plugins/modules/sensor_info.py index 20bbeae04..2955ceac1 100644 --- a/ansible_collections/cisco/dnac/plugins/modules/sensor_info.py +++ b/ansible_collections/cisco/dnac/plugins/modules/sensor_info.py @@ -24,8 +24,8 @@ options: - SiteId query parameter. type: str requirements: -- dnacentersdk >= 2.5.5 -- python >= 3.5 +- dnacentersdk >= 2.6.0 +- python >= 3.9 seealso: - name: Cisco DNA Center documentation for Sensors Sensors description: Complete reference of the Sensors API. diff --git a/ansible_collections/cisco/dnac/plugins/modules/sensor_test_run.py b/ansible_collections/cisco/dnac/plugins/modules/sensor_test_run.py index ac13177e0..cb800c968 100644 --- a/ansible_collections/cisco/dnac/plugins/modules/sensor_test_run.py +++ b/ansible_collections/cisco/dnac/plugins/modules/sensor_test_run.py @@ -20,8 +20,8 @@ options: description: Template Name. type: str requirements: -- dnacentersdk >= 2.5.5 -- python >= 3.5 +- dnacentersdk >= 2.6.0 +- python >= 3.9 seealso: - name: Cisco DNA Center documentation for Sensors RunNowSensorTest description: Complete reference of the RunNowSensorTest API. diff --git a/ansible_collections/cisco/dnac/plugins/modules/sensor_test_template_duplicate.py b/ansible_collections/cisco/dnac/plugins/modules/sensor_test_template_duplicate.py index 513178c5e..85cad96d2 100644 --- a/ansible_collections/cisco/dnac/plugins/modules/sensor_test_template_duplicate.py +++ b/ansible_collections/cisco/dnac/plugins/modules/sensor_test_template_duplicate.py @@ -23,8 +23,8 @@ options: description: Template Name. type: str requirements: -- dnacentersdk >= 2.5.5 -- python >= 3.5 +- dnacentersdk >= 2.6.0 +- python >= 3.9 seealso: - name: Cisco DNA Center documentation for Sensors DuplicateSensorTestTemplate description: Complete reference of the DuplicateSensorTestTemplate API. diff --git a/ansible_collections/cisco/dnac/plugins/modules/sensor_test_template_edit.py b/ansible_collections/cisco/dnac/plugins/modules/sensor_test_template_edit.py index aa993bd10..b8bf3f3b4 100644 --- a/ansible_collections/cisco/dnac/plugins/modules/sensor_test_template_edit.py +++ b/ansible_collections/cisco/dnac/plugins/modules/sensor_test_template_edit.py @@ -83,8 +83,8 @@ options: description: Template Name. type: str requirements: -- dnacentersdk >= 2.5.5 -- python >= 3.5 +- dnacentersdk >= 2.6.0 +- python >= 3.9 seealso: - name: Cisco DNA Center documentation for Sensors EditSensorTestTemplate description: Complete reference of the EditSensorTestTemplate API. diff --git a/ansible_collections/cisco/dnac/plugins/modules/service_provider_create.py b/ansible_collections/cisco/dnac/plugins/modules/service_provider_create.py index 44ef4888b..2ce62b664 100644 --- a/ansible_collections/cisco/dnac/plugins/modules/service_provider_create.py +++ b/ansible_collections/cisco/dnac/plugins/modules/service_provider_create.py @@ -35,8 +35,8 @@ options: type: list type: dict requirements: -- dnacentersdk >= 2.5.5 -- python >= 3.5 +- dnacentersdk >= 2.6.0 +- python >= 3.9 seealso: - name: Cisco DNA Center documentation for Network Settings CreateSPProfile description: Complete reference of the CreateSPProfile API. diff --git a/ansible_collections/cisco/dnac/plugins/modules/service_provider_info.py b/ansible_collections/cisco/dnac/plugins/modules/service_provider_info.py index 6444f7978..d2bc282f3 100644 --- a/ansible_collections/cisco/dnac/plugins/modules/service_provider_info.py +++ b/ansible_collections/cisco/dnac/plugins/modules/service_provider_info.py @@ -20,8 +20,8 @@ options: description: Additional headers. type: dict requirements: -- dnacentersdk >= 2.5.5 -- python >= 3.5 +- dnacentersdk >= 2.6.0 +- python >= 3.9 seealso: - name: Cisco DNA Center documentation for Network Settings GetServiceProviderDetails description: Complete reference of the GetServiceProviderDetails API. diff --git a/ansible_collections/cisco/dnac/plugins/modules/service_provider_profile_delete.py b/ansible_collections/cisco/dnac/plugins/modules/service_provider_profile_delete.py index ec7330c64..0d076885e 100644 --- a/ansible_collections/cisco/dnac/plugins/modules/service_provider_profile_delete.py +++ b/ansible_collections/cisco/dnac/plugins/modules/service_provider_profile_delete.py @@ -20,8 +20,8 @@ options: description: SpProfileName path parameter. Sp profile name. type: str requirements: -- dnacentersdk >= 2.5.5 -- python >= 3.5 +- dnacentersdk >= 2.6.0 +- python >= 3.9 seealso: - name: Cisco DNA Center documentation for Network Settings DeleteSPProfile description: Complete reference of the DeleteSPProfile API. diff --git a/ansible_collections/cisco/dnac/plugins/modules/service_provider_update.py b/ansible_collections/cisco/dnac/plugins/modules/service_provider_update.py index f3c9a6d35..3ec3fcde9 100644 --- a/ansible_collections/cisco/dnac/plugins/modules/service_provider_update.py +++ b/ansible_collections/cisco/dnac/plugins/modules/service_provider_update.py @@ -38,8 +38,8 @@ options: type: list type: dict requirements: -- dnacentersdk >= 2.5.5 -- python >= 3.5 +- dnacentersdk >= 2.6.0 +- python >= 3.9 seealso: - name: Cisco DNA Center documentation for Network Settings UpdateSPProfile description: Complete reference of the UpdateSPProfile API. diff --git a/ansible_collections/cisco/dnac/plugins/modules/service_provider_v2.py b/ansible_collections/cisco/dnac/plugins/modules/service_provider_v2.py index 3a804288f..5dcf4f367 100644 --- a/ansible_collections/cisco/dnac/plugins/modules/service_provider_v2.py +++ b/ansible_collections/cisco/dnac/plugins/modules/service_provider_v2.py @@ -36,8 +36,8 @@ options: type: list type: dict requirements: -- dnacentersdk >= 2.5.5 -- python >= 3.5 +- dnacentersdk >= 2.6.0 +- python >= 3.9 seealso: - name: Cisco DNA Center documentation for Network Settings CreateSPProfileV2 description: Complete reference of the CreateSPProfileV2 API. diff --git a/ansible_collections/cisco/dnac/plugins/modules/service_provider_v2_info.py b/ansible_collections/cisco/dnac/plugins/modules/service_provider_v2_info.py index 50635cc29..2641b9bdb 100644 --- a/ansible_collections/cisco/dnac/plugins/modules/service_provider_v2_info.py +++ b/ansible_collections/cisco/dnac/plugins/modules/service_provider_v2_info.py @@ -20,8 +20,8 @@ options: description: Additional headers. type: dict requirements: -- dnacentersdk >= 2.5.5 -- python >= 3.5 +- dnacentersdk >= 2.6.0 +- python >= 3.9 seealso: - name: Cisco DNA Center documentation for Network Settings GetServiceProviderDetailsV2 description: Complete reference of the GetServiceProviderDetailsV2 API. diff --git a/ansible_collections/cisco/dnac/plugins/modules/site_assign_credential.py b/ansible_collections/cisco/dnac/plugins/modules/site_assign_credential.py index 5cbb53684..b21a5ca77 100644 --- a/ansible_collections/cisco/dnac/plugins/modules/site_assign_credential.py +++ b/ansible_collections/cisco/dnac/plugins/modules/site_assign_credential.py @@ -41,8 +41,8 @@ options: description: Snmp V3 Id. type: str requirements: -- dnacentersdk >= 2.5.5 -- python >= 3.5 +- dnacentersdk >= 2.6.0 +- python >= 3.9 seealso: - name: Cisco DNA Center documentation for Network Settings AssignDeviceCredentialToSite description: Complete reference of the AssignDeviceCredentialToSite API. diff --git a/ansible_collections/cisco/dnac/plugins/modules/site_assign_device.py b/ansible_collections/cisco/dnac/plugins/modules/site_assign_device.py index d0bdd2268..1c080cba4 100644 --- a/ansible_collections/cisco/dnac/plugins/modules/site_assign_device.py +++ b/ansible_collections/cisco/dnac/plugins/modules/site_assign_device.py @@ -28,8 +28,8 @@ options: description: SiteId path parameter. Site id to which site the device to assign. type: str requirements: -- dnacentersdk >= 2.5.5 -- python >= 3.5 +- dnacentersdk >= 2.6.0 +- python >= 3.9 notes: - SDK Method used are sites.Sites.assign_device_to_site, diff --git a/ansible_collections/cisco/dnac/plugins/modules/site_count_info.py b/ansible_collections/cisco/dnac/plugins/modules/site_count_info.py index 85b57d946..c4a5dbd96 100644 --- a/ansible_collections/cisco/dnac/plugins/modules/site_count_info.py +++ b/ansible_collections/cisco/dnac/plugins/modules/site_count_info.py @@ -24,8 +24,8 @@ options: - SiteId query parameter. Site id to retrieve site count. type: str requirements: -- dnacentersdk >= 2.5.5 -- python >= 3.5 +- dnacentersdk >= 2.6.0 +- python >= 3.9 seealso: - name: Cisco DNA Center documentation for Sites GetSiteCount description: Complete reference of the GetSiteCount API. diff --git a/ansible_collections/cisco/dnac/plugins/modules/site_create.py b/ansible_collections/cisco/dnac/plugins/modules/site_create.py index 31f357aea..6b690ac25 100644 --- a/ansible_collections/cisco/dnac/plugins/modules/site_create.py +++ b/ansible_collections/cisco/dnac/plugins/modules/site_create.py @@ -84,8 +84,8 @@ options: description: Type of site to create (eg area, building, floor). type: str requirements: -- dnacentersdk >= 2.5.5 -- python >= 3.5 +- dnacentersdk >= 2.6.0 +- python >= 3.9 seealso: - name: Cisco DNA Center documentation for Sites CreateSite description: Complete reference of the CreateSite API. diff --git a/ansible_collections/cisco/dnac/plugins/modules/site_delete.py b/ansible_collections/cisco/dnac/plugins/modules/site_delete.py index d36690ef4..6c52cc343 100644 --- a/ansible_collections/cisco/dnac/plugins/modules/site_delete.py +++ b/ansible_collections/cisco/dnac/plugins/modules/site_delete.py @@ -20,8 +20,8 @@ options: description: SiteId path parameter. Site id to which site details to be deleted. type: str requirements: -- dnacentersdk >= 2.5.5 -- python >= 3.5 +- dnacentersdk >= 2.6.0 +- python >= 3.9 seealso: - name: Cisco DNA Center documentation for Sites DeleteSite description: Complete reference of the DeleteSite API. diff --git a/ansible_collections/cisco/dnac/plugins/modules/site_design_floormap.py b/ansible_collections/cisco/dnac/plugins/modules/site_design_floormap.py index a5f868383..0948930f3 100644 --- a/ansible_collections/cisco/dnac/plugins/modules/site_design_floormap.py +++ b/ansible_collections/cisco/dnac/plugins/modules/site_design_floormap.py @@ -24,8 +24,8 @@ options: description: Site Design Floormap's payload type: dict requirements: -- dnacentersdk >= 2.5.5 -- python >= 3.5 +- dnacentersdk >= 2.6.0 +- python >= 3.9 notes: - SDK Method used are site_design.SiteDesign.create_floormap, diff --git a/ansible_collections/cisco/dnac/plugins/modules/site_design_floormap_info.py b/ansible_collections/cisco/dnac/plugins/modules/site_design_floormap_info.py index ee1fa87bf..c427e42bb 100644 --- a/ansible_collections/cisco/dnac/plugins/modules/site_design_floormap_info.py +++ b/ansible_collections/cisco/dnac/plugins/modules/site_design_floormap_info.py @@ -26,8 +26,8 @@ options: - FloorId path parameter. Group Id of the specified floormap. type: str requirements: -- dnacentersdk >= 2.5.5 -- python >= 3.5 +- dnacentersdk >= 2.6.0 +- python >= 3.9 notes: - SDK Method used are site_design.SiteDesign.get_floormap, diff --git a/ansible_collections/cisco/dnac/plugins/modules/site_health_info.py b/ansible_collections/cisco/dnac/plugins/modules/site_health_info.py index 9614b6eb8..cbb91dcd6 100644 --- a/ansible_collections/cisco/dnac/plugins/modules/site_health_info.py +++ b/ansible_collections/cisco/dnac/plugins/modules/site_health_info.py @@ -36,8 +36,8 @@ options: - Limit query parameter. The max number of sites in the returned data set. Default is 25, and max at 50. type: int requirements: -- dnacentersdk >= 2.5.5 -- python >= 3.5 +- dnacentersdk >= 2.6.0 +- python >= 3.9 seealso: - name: Cisco DNA Center documentation for Sites GetSiteHealth description: Complete reference of the GetSiteHealth API. diff --git a/ansible_collections/cisco/dnac/plugins/modules/site_info.py b/ansible_collections/cisco/dnac/plugins/modules/site_info.py index 49bdf393c..be914d2e2 100644 --- a/ansible_collections/cisco/dnac/plugins/modules/site_info.py +++ b/ansible_collections/cisco/dnac/plugins/modules/site_info.py @@ -40,8 +40,8 @@ options: - Limit query parameter. Number of sites to be retrieved. The default value is 500. type: int requirements: -- dnacentersdk >= 2.5.5 -- python >= 3.5 +- dnacentersdk >= 2.6.0 +- python >= 3.9 seealso: - name: Cisco DNA Center documentation for Sites GetSite description: Complete reference of the GetSite API. diff --git a/ansible_collections/cisco/dnac/plugins/modules/site_intent.py b/ansible_collections/cisco/dnac/plugins/modules/site_intent.py index 751d520be..39d708730 100644 --- a/ansible_collections/cisco/dnac/plugins/modules/site_intent.py +++ b/ansible_collections/cisco/dnac/plugins/modules/site_intent.py @@ -120,7 +120,7 @@ options: requirements: - dnacentersdk == 2.4.5 -- python >= 3.5 +- python >= 3.9 notes: - SDK Method used are sites.Sites.create_site, @@ -489,6 +489,7 @@ class DnacSite(DnacBase): response = self.dnac._exec( family="sites", function='get_site', + op_modifies=True, params={"name": self.want.get("site_name")}, ) @@ -807,12 +808,18 @@ class DnacSite(DnacBase): else: # Creating New Site site_params = self.want.get("site_params") - if site_params['site']['building']: - building_details = {} - for key, value in site_params['site']['building'].items(): - if value is not None: - building_details[key] = value - site_params['site']['building'] = building_details + try: + if site_params['site']['building']: + building_details = {} + for key, value in site_params['site']['building'].items(): + if value is not None: + building_details[key] = value + site_params['site']['building'] = building_details + except Exception as e: + site_type = site_params['type'] + site_name = site_params['site'][site_type]['name'] + self.log("""The site '{0}' is not categorized as a building; hence, there is no need to filter out 'None' + values from the 'site_params' dictionary.""".format(site_name), "INFO") response = self.dnac._exec( family="sites", @@ -877,6 +884,7 @@ class DnacSite(DnacBase): response = self.dnac._exec( family="sites", function="delete_site", + op_modifies=True, params={"site_id": site_id}, ) @@ -941,6 +949,7 @@ class DnacSite(DnacBase): mem_response = self.dnac._exec( family="sites", function="get_membership", + op_modifies=True, params={"site_id": site_id}, ) site_response = mem_response.get("site").get("response") diff --git a/ansible_collections/cisco/dnac/plugins/modules/site_membership_info.py b/ansible_collections/cisco/dnac/plugins/modules/site_membership_info.py index d38f3844e..bc28ba3f3 100644 --- a/ansible_collections/cisco/dnac/plugins/modules/site_membership_info.py +++ b/ansible_collections/cisco/dnac/plugins/modules/site_membership_info.py @@ -40,8 +40,8 @@ options: - SerialNumber query parameter. Device serial number. type: str requirements: -- dnacentersdk >= 2.5.5 -- python >= 3.5 +- dnacentersdk >= 2.6.0 +- python >= 3.9 seealso: - name: Cisco DNA Center documentation for Sites GetMembership description: Complete reference of the GetMembership API. diff --git a/ansible_collections/cisco/dnac/plugins/modules/site_update.py b/ansible_collections/cisco/dnac/plugins/modules/site_update.py index 4a97a6ede..86c54a60b 100644 --- a/ansible_collections/cisco/dnac/plugins/modules/site_update.py +++ b/ansible_collections/cisco/dnac/plugins/modules/site_update.py @@ -78,8 +78,8 @@ options: description: Type. type: str requirements: -- dnacentersdk >= 2.5.5 -- python >= 3.5 +- dnacentersdk >= 2.6.0 +- python >= 3.9 seealso: - name: Cisco DNA Center documentation for Sites UpdateSite description: Complete reference of the UpdateSite API. diff --git a/ansible_collections/cisco/dnac/plugins/modules/site_workflow_manager.py b/ansible_collections/cisco/dnac/plugins/modules/site_workflow_manager.py index 1ae28afd8..81c6a974e 100644 --- a/ansible_collections/cisco/dnac/plugins/modules/site_workflow_manager.py +++ b/ansible_collections/cisco/dnac/plugins/modules/site_workflow_manager.py @@ -120,7 +120,7 @@ options: requirements: - dnacentersdk == 2.4.5 -- python >= 3.5 +- python >= 3.9 notes: - SDK Method used are sites.Sites.create_site, @@ -488,6 +488,7 @@ class Site(DnacBase): response = self.dnac._exec( family="sites", function='get_site', + op_modifies=True, params={"name": self.want.get("site_name")}, ) @@ -806,12 +807,18 @@ class Site(DnacBase): else: # Creating New Site site_params = self.want.get("site_params") - if site_params['site']['building']: - building_details = {} - for key, value in site_params['site']['building'].items(): - if value is not None: - building_details[key] = value - site_params['site']['building'] = building_details + try: + if site_params['site']['building']: + building_details = {} + for key, value in site_params['site']['building'].items(): + if value is not None: + building_details[key] = value + site_params['site']['building'] = building_details + except Exception as e: + site_type = site_params['type'] + site_name = site_params['site'][site_type]['name'] + self.log("""The site '{0}' is not categorized as a building; hence, there is no need to filter out 'None' + values from the 'site_params' dictionary.""".format(site_name), "INFO") response = self.dnac._exec( family="sites", @@ -876,6 +883,7 @@ class Site(DnacBase): response = self.dnac._exec( family="sites", function="delete_site", + op_modifies=True, params={"site_id": site_id}, ) @@ -940,6 +948,7 @@ class Site(DnacBase): mem_response = self.dnac._exec( family="sites", function="get_membership", + op_modifies=True, params={"site_id": site_id}, ) site_response = mem_response.get("site").get("response") diff --git a/ansible_collections/cisco/dnac/plugins/modules/snmp_properties.py b/ansible_collections/cisco/dnac/plugins/modules/snmp_properties.py index 0ea733b2a..9cbcae16c 100644 --- a/ansible_collections/cisco/dnac/plugins/modules/snmp_properties.py +++ b/ansible_collections/cisco/dnac/plugins/modules/snmp_properties.py @@ -37,8 +37,8 @@ options: type: str type: list requirements: -- dnacentersdk >= 2.5.5 -- python >= 3.5 +- dnacentersdk >= 2.6.0 +- python >= 3.9 seealso: - name: Cisco DNA Center documentation for Discovery CreateUpdateSNMPProperties description: Complete reference of the CreateUpdateSNMPProperties API. diff --git a/ansible_collections/cisco/dnac/plugins/modules/snmp_properties_info.py b/ansible_collections/cisco/dnac/plugins/modules/snmp_properties_info.py index 9300eaa86..4f32fd28d 100644 --- a/ansible_collections/cisco/dnac/plugins/modules/snmp_properties_info.py +++ b/ansible_collections/cisco/dnac/plugins/modules/snmp_properties_info.py @@ -20,8 +20,8 @@ options: description: Additional headers. type: dict requirements: -- dnacentersdk >= 2.5.5 -- python >= 3.5 +- dnacentersdk >= 2.6.0 +- python >= 3.9 seealso: - name: Cisco DNA Center documentation for Discovery GetSNMPProperties description: Complete reference of the GetSNMPProperties API. diff --git a/ansible_collections/cisco/dnac/plugins/modules/snmpv2_read_community_credential.py b/ansible_collections/cisco/dnac/plugins/modules/snmpv2_read_community_credential.py index 69da389ea..0fd5ce8cb 100644 --- a/ansible_collections/cisco/dnac/plugins/modules/snmpv2_read_community_credential.py +++ b/ansible_collections/cisco/dnac/plugins/modules/snmpv2_read_community_credential.py @@ -33,8 +33,8 @@ options: description: SNMP read community. NO!$DATA!$ for no value change. type: str requirements: -- dnacentersdk >= 2.5.5 -- python >= 3.5 +- dnacentersdk >= 2.6.0 +- python >= 3.9 seealso: - name: Cisco DNA Center documentation for Discovery CreateSNMPReadCommunity description: Complete reference of the CreateSNMPReadCommunity API. diff --git a/ansible_collections/cisco/dnac/plugins/modules/snmpv2_write_community_credential.py b/ansible_collections/cisco/dnac/plugins/modules/snmpv2_write_community_credential.py index 2fbfbbc66..00caf3e5b 100644 --- a/ansible_collections/cisco/dnac/plugins/modules/snmpv2_write_community_credential.py +++ b/ansible_collections/cisco/dnac/plugins/modules/snmpv2_write_community_credential.py @@ -33,8 +33,8 @@ options: description: SNMP write community. NO!$DATA!$ for no value change. type: str requirements: -- dnacentersdk >= 2.5.5 -- python >= 3.5 +- dnacentersdk >= 2.6.0 +- python >= 3.9 seealso: - name: Cisco DNA Center documentation for Discovery CreateSNMPWriteCommunity description: Complete reference of the CreateSNMPWriteCommunity API. diff --git a/ansible_collections/cisco/dnac/plugins/modules/snmpv3_credential.py b/ansible_collections/cisco/dnac/plugins/modules/snmpv3_credential.py index d48c693d5..705d9e507 100644 --- a/ansible_collections/cisco/dnac/plugins/modules/snmpv3_credential.py +++ b/ansible_collections/cisco/dnac/plugins/modules/snmpv3_credential.py @@ -54,8 +54,8 @@ options: description: Snmpv3 Credential's username. type: str requirements: -- dnacentersdk >= 2.5.5 -- python >= 3.5 +- dnacentersdk >= 2.6.0 +- python >= 3.9 seealso: - name: Cisco DNA Center documentation for Discovery CreateSNMPv3Credentials description: Complete reference of the CreateSNMPv3Credentials API. diff --git a/ansible_collections/cisco/dnac/plugins/modules/sp_profile_delete_v2.py b/ansible_collections/cisco/dnac/plugins/modules/sp_profile_delete_v2.py index 1022d4de4..236a0ba49 100644 --- a/ansible_collections/cisco/dnac/plugins/modules/sp_profile_delete_v2.py +++ b/ansible_collections/cisco/dnac/plugins/modules/sp_profile_delete_v2.py @@ -20,8 +20,8 @@ options: description: SpProfileName path parameter. Sp profile name. type: str requirements: -- dnacentersdk >= 2.5.5 -- python >= 3.5 +- dnacentersdk >= 2.6.0 +- python >= 3.9 seealso: - name: Cisco DNA Center documentation for Network Settings DeleteSPProfileV2 description: Complete reference of the DeleteSPProfileV2 API. diff --git a/ansible_collections/cisco/dnac/plugins/modules/swim_image_details_info.py b/ansible_collections/cisco/dnac/plugins/modules/swim_image_details_info.py index b9ed467ed..d41519382 100644 --- a/ansible_collections/cisco/dnac/plugins/modules/swim_image_details_info.py +++ b/ansible_collections/cisco/dnac/plugins/modules/swim_image_details_info.py @@ -92,8 +92,8 @@ options: - Offset query parameter. type: int requirements: -- dnacentersdk >= 2.5.5 -- python >= 3.5 +- dnacentersdk >= 2.6.0 +- python >= 3.9 seealso: - name: Cisco DNA Center documentation for Software Image Management (SWIM) GetSoftwareImageDetails description: Complete reference of the GetSoftwareImageDetails API. diff --git a/ansible_collections/cisco/dnac/plugins/modules/swim_import_local.py b/ansible_collections/cisco/dnac/plugins/modules/swim_import_local.py index 6ea0d9b9c..27966b4cd 100644 --- a/ansible_collections/cisco/dnac/plugins/modules/swim_import_local.py +++ b/ansible_collections/cisco/dnac/plugins/modules/swim_import_local.py @@ -35,8 +35,8 @@ options: description: ThirdPartyVendor query parameter. Third Party Vendor. type: str requirements: -- dnacentersdk >= 2.5.5 -- python >= 3.5 +- dnacentersdk >= 2.6.0 +- python >= 3.9 seealso: - name: Cisco DNA Center documentation for Software Image Management (SWIM) ImportLocalSoftwareImage description: Complete reference of the ImportLocalSoftwareImage API. diff --git a/ansible_collections/cisco/dnac/plugins/modules/swim_import_via_url.py b/ansible_collections/cisco/dnac/plugins/modules/swim_import_via_url.py index 3f86cc047..df217a30c 100644 --- a/ansible_collections/cisco/dnac/plugins/modules/swim_import_via_url.py +++ b/ansible_collections/cisco/dnac/plugins/modules/swim_import_via_url.py @@ -49,8 +49,8 @@ options: description: ScheduleOrigin query parameter. Originator of this call (Optional). type: str requirements: -- dnacentersdk >= 2.5.5 -- python >= 3.5 +- dnacentersdk >= 2.6.0 +- python >= 3.9 seealso: - name: Cisco DNA Center documentation for Software Image Management (SWIM) ImportSoftwareImageViaURL description: Complete reference of the ImportSoftwareImageViaURL API. diff --git a/ansible_collections/cisco/dnac/plugins/modules/swim_intent.py b/ansible_collections/cisco/dnac/plugins/modules/swim_intent.py index 08f78ac30..f1eadb5b4 100644 --- a/ansible_collections/cisco/dnac/plugins/modules/swim_intent.py +++ b/ansible_collections/cisco/dnac/plugins/modules/swim_intent.py @@ -309,7 +309,7 @@ options: type: bool requirements: - dnacentersdk == 2.4.5 -- python >= 3.5 +- python >= 3.9 notes: - SDK Method used are software_image_management_swim.SoftwareImageManagementSwim.import_software_image_via_url, @@ -583,6 +583,7 @@ class DnacSwims(DnacBase): response = self.dnac._exec( family="sites", function='get_site', + op_modifies=True, params={"name": site_name}, ) except Exception as e: @@ -617,6 +618,7 @@ class DnacSwims(DnacBase): image_response = self.dnac._exec( family="software_image_management_swim", function='get_software_image_details', + op_modifies=True, params={"image_name": name}, ) self.log("Received API response from 'get_software_image_details': {0}".format(str(image_response)), "DEBUG") @@ -651,6 +653,7 @@ class DnacSwims(DnacBase): image_response = self.dnac._exec( family="software_image_management_swim", function='get_software_image_details', + op_modifies=True, params={"image_uuid": image_id}, ) self.log("Received API response from 'get_software_image_details': {0}".format(str(image_response)), "DEBUG") @@ -686,6 +689,7 @@ class DnacSwims(DnacBase): image_response = self.dnac._exec( family="software_image_management_swim", function='get_software_image_details', + op_modifies=True, params={"image_name": name}, ) self.log("Received API response from 'get_software_image_details': {0}".format(str(image_response)), "DEBUG") @@ -713,6 +717,7 @@ class DnacSwims(DnacBase): response = self.dnac._exec( family="devices", function='get_device_list', + op_modifies=True, params=params, ) self.log("Received API response from 'get_device_list': {0}".format(str(response)), "DEBUG") @@ -765,12 +770,18 @@ class DnacSwims(DnacBase): "site_id": site_id, "device_family": device_family } - response = self.dnac._exec( - family="sites", - function='get_membership', - op_modifies=True, - params=site_params, - ) + + try: + response = self.dnac._exec( + family="sites", + function='get_membership', + op_modifies=True, + params=site_params, + ) + except Exception as e: + self.log("Unable to fetch the device(s) associated to the site '{0}' due to '{1}'".format(site_name, str(e)), "WARNING") + return device_uuid_list + self.log("Received API response from 'get_membership': {0}".format(str(response)), "DEBUG") response = response['device'] @@ -1305,6 +1316,7 @@ class DnacSwims(DnacBase): response = self.dnac._exec( family="devices", function='get_device_list', + op_modifies=True, params={"id": device_id} ) self.log("Received API response from 'get_device_list': {0}".format(str(response)), "DEBUG") diff --git a/ansible_collections/cisco/dnac/plugins/modules/swim_trigger_activation.py b/ansible_collections/cisco/dnac/plugins/modules/swim_trigger_activation.py index ec9ca0e5b..5d7cae2b5 100644 --- a/ansible_collections/cisco/dnac/plugins/modules/swim_trigger_activation.py +++ b/ansible_collections/cisco/dnac/plugins/modules/swim_trigger_activation.py @@ -49,8 +49,8 @@ options: before schedule (Optional). type: bool requirements: -- dnacentersdk >= 2.5.5 -- python >= 3.5 +- dnacentersdk >= 2.6.0 +- python >= 3.9 seealso: - name: Cisco DNA Center documentation for Software Image Management (SWIM) TriggerSoftwareImageActivation description: Complete reference of the TriggerSoftwareImageActivation API. diff --git a/ansible_collections/cisco/dnac/plugins/modules/swim_trigger_distribution.py b/ansible_collections/cisco/dnac/plugins/modules/swim_trigger_distribution.py index cad143cb4..ce1b5e1fc 100644 --- a/ansible_collections/cisco/dnac/plugins/modules/swim_trigger_distribution.py +++ b/ansible_collections/cisco/dnac/plugins/modules/swim_trigger_distribution.py @@ -30,8 +30,8 @@ options: type: str type: list requirements: -- dnacentersdk >= 2.5.5 -- python >= 3.5 +- dnacentersdk >= 2.6.0 +- python >= 3.9 seealso: - name: Cisco DNA Center documentation for Software Image Management (SWIM) TriggerSoftwareImageDistribution description: Complete reference of the TriggerSoftwareImageDistribution API. diff --git a/ansible_collections/cisco/dnac/plugins/modules/swim_workflow_manager.py b/ansible_collections/cisco/dnac/plugins/modules/swim_workflow_manager.py index a147b4055..f7a1764fd 100644 --- a/ansible_collections/cisco/dnac/plugins/modules/swim_workflow_manager.py +++ b/ansible_collections/cisco/dnac/plugins/modules/swim_workflow_manager.py @@ -296,7 +296,7 @@ options: type: bool requirements: - dnacentersdk == 2.4.5 -- python >= 3.5 +- python >= 3.9 notes: - SDK Method used are software_image_management_swim.SoftwareImageManagementSwim.import_software_image_via_url, @@ -569,6 +569,7 @@ class Swim(DnacBase): response = self.dnac._exec( family="sites", function='get_site', + op_modifies=True, params={"name": site_name}, ) except Exception as e: @@ -603,6 +604,7 @@ class Swim(DnacBase): image_response = self.dnac._exec( family="software_image_management_swim", function='get_software_image_details', + op_modifies=True, params={"image_name": name}, ) self.log("Received API response from 'get_software_image_details': {0}".format(str(image_response)), "DEBUG") @@ -637,6 +639,7 @@ class Swim(DnacBase): image_response = self.dnac._exec( family="software_image_management_swim", function='get_software_image_details', + op_modifies=True, params={"image_uuid": image_id}, ) self.log("Received API response from 'get_software_image_details': {0}".format(str(image_response)), "DEBUG") @@ -672,6 +675,7 @@ class Swim(DnacBase): image_response = self.dnac._exec( family="software_image_management_swim", function='get_software_image_details', + op_modifies=True, params={"image_name": name}, ) self.log("Received API response from 'get_software_image_details': {0}".format(str(image_response)), "DEBUG") @@ -699,6 +703,7 @@ class Swim(DnacBase): response = self.dnac._exec( family="devices", function='get_device_list', + op_modifies=True, params=params, ) self.log("Received API response from 'get_device_list': {0}".format(str(response)), "DEBUG") @@ -751,12 +756,18 @@ class Swim(DnacBase): "site_id": site_id, "device_family": device_family } - response = self.dnac._exec( - family="sites", - function='get_membership', - op_modifies=True, - params=site_params, - ) + + try: + response = self.dnac._exec( + family="sites", + function='get_membership', + op_modifies=True, + params=site_params, + ) + except Exception as e: + self.log("Unable to fetch the device(s) associated to the site '{0}' due to '{1}'".format(site_name, str(e)), "WARNING") + return device_uuid_list + self.log("Received API response from 'get_membership': {0}".format(str(response)), "DEBUG") response = response['device'] @@ -1291,6 +1302,7 @@ class Swim(DnacBase): response = self.dnac._exec( family="devices", function='get_device_list', + op_modifies=True, params={"id": device_id} ) self.log("Received API response from 'get_device_list': {0}".format(str(response)), "DEBUG") diff --git a/ansible_collections/cisco/dnac/plugins/modules/syslog_config_create.py b/ansible_collections/cisco/dnac/plugins/modules/syslog_config_create.py index d9058d44e..c4804a3b3 100644 --- a/ansible_collections/cisco/dnac/plugins/modules/syslog_config_create.py +++ b/ansible_collections/cisco/dnac/plugins/modules/syslog_config_create.py @@ -35,8 +35,8 @@ options: description: Protocol. type: str requirements: -- dnacentersdk >= 2.5.5 -- python >= 3.5 +- dnacentersdk >= 2.6.0 +- python >= 3.9 seealso: - name: Cisco DNA Center documentation for Event Management CreateSyslogDestination description: Complete reference of the CreateSyslogDestination API. diff --git a/ansible_collections/cisco/dnac/plugins/modules/syslog_config_update.py b/ansible_collections/cisco/dnac/plugins/modules/syslog_config_update.py index 79d319fea..653555ac9 100644 --- a/ansible_collections/cisco/dnac/plugins/modules/syslog_config_update.py +++ b/ansible_collections/cisco/dnac/plugins/modules/syslog_config_update.py @@ -35,8 +35,8 @@ options: description: Protocol. type: str requirements: -- dnacentersdk >= 2.5.5 -- python >= 3.5 +- dnacentersdk >= 2.6.0 +- python >= 3.9 seealso: - name: Cisco DNA Center documentation for Event Management UpdateSyslogDestination description: Complete reference of the UpdateSyslogDestination API. diff --git a/ansible_collections/cisco/dnac/plugins/modules/system_health_count_info.py b/ansible_collections/cisco/dnac/plugins/modules/system_health_count_info.py index b8e6b135c..bf9b72361 100644 --- a/ansible_collections/cisco/dnac/plugins/modules/system_health_count_info.py +++ b/ansible_collections/cisco/dnac/plugins/modules/system_health_count_info.py @@ -32,8 +32,8 @@ options: here /dna/platform/app/consumer-portal/developer-toolkit/events. type: str requirements: -- dnacentersdk >= 2.5.5 -- python >= 3.5 +- dnacentersdk >= 2.6.0 +- python >= 3.9 seealso: - name: Cisco DNA Center documentation for Health and Performance SystemHealthCountAPI description: Complete reference of the SystemHealthCountAPI API. diff --git a/ansible_collections/cisco/dnac/plugins/modules/system_health_info.py b/ansible_collections/cisco/dnac/plugins/modules/system_health_info.py index c0d2ea881..01a23ee64 100644 --- a/ansible_collections/cisco/dnac/plugins/modules/system_health_info.py +++ b/ansible_collections/cisco/dnac/plugins/modules/system_health_info.py @@ -44,8 +44,8 @@ options: - Offset query parameter. type: int requirements: -- dnacentersdk >= 2.5.5 -- python >= 3.5 +- dnacentersdk >= 2.6.0 +- python >= 3.9 seealso: - name: Cisco DNA Center documentation for Health and Performance SystemHealthAPI description: Complete reference of the SystemHealthAPI API. diff --git a/ansible_collections/cisco/dnac/plugins/modules/system_performance_historical_info.py b/ansible_collections/cisco/dnac/plugins/modules/system_performance_historical_info.py index 9cdbef7d6..11476ed6f 100644 --- a/ansible_collections/cisco/dnac/plugins/modules/system_performance_historical_info.py +++ b/ansible_collections/cisco/dnac/plugins/modules/system_performance_historical_info.py @@ -36,8 +36,8 @@ options: be fetched. type: int requirements: -- dnacentersdk >= 2.5.5 -- python >= 3.5 +- dnacentersdk >= 2.6.0 +- python >= 3.9 seealso: - name: Cisco DNA Center documentation for Health and Performance SystemPerformanceHistoricalAPI description: Complete reference of the SystemPerformanceHistoricalAPI API. diff --git a/ansible_collections/cisco/dnac/plugins/modules/system_performance_info.py b/ansible_collections/cisco/dnac/plugins/modules/system_performance_info.py index 8460d7265..41b14ccdd 100644 --- a/ansible_collections/cisco/dnac/plugins/modules/system_performance_info.py +++ b/ansible_collections/cisco/dnac/plugins/modules/system_performance_info.py @@ -40,8 +40,8 @@ options: be fetched. type: int requirements: -- dnacentersdk >= 2.5.5 -- python >= 3.5 +- dnacentersdk >= 2.6.0 +- python >= 3.9 seealso: - name: Cisco DNA Center documentation for Health and Performance SystemPerformanceAPI description: Complete reference of the SystemPerformanceAPI API. diff --git a/ansible_collections/cisco/dnac/plugins/modules/tag.py b/ansible_collections/cisco/dnac/plugins/modules/tag.py index 7630c2e61..0b26448c0 100644 --- a/ansible_collections/cisco/dnac/plugins/modules/tag.py +++ b/ansible_collections/cisco/dnac/plugins/modules/tag.py @@ -63,8 +63,8 @@ options: description: SystemTag flag. type: bool requirements: -- dnacentersdk >= 2.5.5 -- python >= 3.5 +- dnacentersdk >= 2.6.0 +- python >= 3.9 seealso: - name: Cisco DNA Center documentation for Tag CreateTag description: Complete reference of the CreateTag API. diff --git a/ansible_collections/cisco/dnac/plugins/modules/tag_count_info.py b/ansible_collections/cisco/dnac/plugins/modules/tag_count_info.py index 4624d65ed..7562f71fc 100644 --- a/ansible_collections/cisco/dnac/plugins/modules/tag_count_info.py +++ b/ansible_collections/cisco/dnac/plugins/modules/tag_count_info.py @@ -44,8 +44,8 @@ options: - SystemTag query parameter. type: str requirements: -- dnacentersdk >= 2.5.5 -- python >= 3.5 +- dnacentersdk >= 2.6.0 +- python >= 3.9 seealso: - name: Cisco DNA Center documentation for Tag GetTagCount description: Complete reference of the GetTagCount API. diff --git a/ansible_collections/cisco/dnac/plugins/modules/tag_info.py b/ansible_collections/cisco/dnac/plugins/modules/tag_info.py index bc09f0ba5..c7c32e7d5 100644 --- a/ansible_collections/cisco/dnac/plugins/modules/tag_info.py +++ b/ansible_collections/cisco/dnac/plugins/modules/tag_info.py @@ -72,8 +72,8 @@ options: - Id path parameter. Tag ID. type: str requirements: -- dnacentersdk >= 2.5.5 -- python >= 3.5 +- dnacentersdk >= 2.6.0 +- python >= 3.9 seealso: - name: Cisco DNA Center documentation for Tag GetTag description: Complete reference of the GetTag API. diff --git a/ansible_collections/cisco/dnac/plugins/modules/tag_member.py b/ansible_collections/cisco/dnac/plugins/modules/tag_member.py index 017fd1c23..2ffe6ce10 100644 --- a/ansible_collections/cisco/dnac/plugins/modules/tag_member.py +++ b/ansible_collections/cisco/dnac/plugins/modules/tag_member.py @@ -30,8 +30,8 @@ options: description: Map of member type and member ids. type: dict requirements: -- dnacentersdk >= 2.5.5 -- python >= 3.5 +- dnacentersdk >= 2.6.0 +- python >= 3.9 seealso: - name: Cisco DNA Center documentation for Tag AddMembersToTheTag description: Complete reference of the AddMembersToTheTag API. diff --git a/ansible_collections/cisco/dnac/plugins/modules/tag_member_count_info.py b/ansible_collections/cisco/dnac/plugins/modules/tag_member_count_info.py index 13bfd2c4c..82dbf33d0 100644 --- a/ansible_collections/cisco/dnac/plugins/modules/tag_member_count_info.py +++ b/ansible_collections/cisco/dnac/plugins/modules/tag_member_count_info.py @@ -36,8 +36,8 @@ options: - Level query parameter. type: str requirements: -- dnacentersdk >= 2.5.5 -- python >= 3.5 +- dnacentersdk >= 2.6.0 +- python >= 3.9 seealso: - name: Cisco DNA Center documentation for Tag GetTagMemberCount description: Complete reference of the GetTagMemberCount API. diff --git a/ansible_collections/cisco/dnac/plugins/modules/tag_member_info.py b/ansible_collections/cisco/dnac/plugins/modules/tag_member_info.py index 077114139..57401f152 100644 --- a/ansible_collections/cisco/dnac/plugins/modules/tag_member_info.py +++ b/ansible_collections/cisco/dnac/plugins/modules/tag_member_info.py @@ -50,8 +50,8 @@ options: - Level query parameter. type: str requirements: -- dnacentersdk >= 2.5.5 -- python >= 3.5 +- dnacentersdk >= 2.6.0 +- python >= 3.9 seealso: - name: Cisco DNA Center documentation for Tag GetTagMembersById description: Complete reference of the GetTagMembersById API. diff --git a/ansible_collections/cisco/dnac/plugins/modules/tag_member_type_info.py b/ansible_collections/cisco/dnac/plugins/modules/tag_member_type_info.py index 4fcb8ca42..a7e4cd1c9 100644 --- a/ansible_collections/cisco/dnac/plugins/modules/tag_member_type_info.py +++ b/ansible_collections/cisco/dnac/plugins/modules/tag_member_type_info.py @@ -20,8 +20,8 @@ options: description: Additional headers. type: dict requirements: -- dnacentersdk >= 2.5.5 -- python >= 3.5 +- dnacentersdk >= 2.6.0 +- python >= 3.9 seealso: - name: Cisco DNA Center documentation for Tag GetTagResourceTypes description: Complete reference of the GetTagResourceTypes API. diff --git a/ansible_collections/cisco/dnac/plugins/modules/tag_membership.py b/ansible_collections/cisco/dnac/plugins/modules/tag_membership.py index e7516549e..9366e9ed2 100644 --- a/ansible_collections/cisco/dnac/plugins/modules/tag_membership.py +++ b/ansible_collections/cisco/dnac/plugins/modules/tag_membership.py @@ -32,8 +32,8 @@ options: description: Tag Membership's memberType. type: str requirements: -- dnacentersdk >= 2.5.5 -- python >= 3.5 +- dnacentersdk >= 2.6.0 +- python >= 3.9 seealso: - name: Cisco DNA Center documentation for Tag UpdatesTagMembership description: Complete reference of the UpdatesTagMembership API. diff --git a/ansible_collections/cisco/dnac/plugins/modules/task_count_info.py b/ansible_collections/cisco/dnac/plugins/modules/task_count_info.py index bb95a22fc..a1eedd445 100644 --- a/ansible_collections/cisco/dnac/plugins/modules/task_count_info.py +++ b/ansible_collections/cisco/dnac/plugins/modules/task_count_info.py @@ -60,8 +60,8 @@ options: - ParentId query parameter. Fetch tasks that have this parent Id. type: str requirements: -- dnacentersdk >= 2.5.5 -- python >= 3.5 +- dnacentersdk >= 2.6.0 +- python >= 3.9 seealso: - name: Cisco DNA Center documentation for Task GetTaskCount description: Complete reference of the GetTaskCount API. diff --git a/ansible_collections/cisco/dnac/plugins/modules/task_info.py b/ansible_collections/cisco/dnac/plugins/modules/task_info.py index 9b2b19b01..9adaf195a 100644 --- a/ansible_collections/cisco/dnac/plugins/modules/task_info.py +++ b/ansible_collections/cisco/dnac/plugins/modules/task_info.py @@ -82,8 +82,8 @@ options: - TaskId path parameter. UUID of the Task. type: str requirements: -- dnacentersdk >= 2.5.5 -- python >= 3.5 +- dnacentersdk >= 2.6.0 +- python >= 3.9 seealso: - name: Cisco DNA Center documentation for Task GetTaskById description: Complete reference of the GetTaskById API. diff --git a/ansible_collections/cisco/dnac/plugins/modules/task_operation_info.py b/ansible_collections/cisco/dnac/plugins/modules/task_operation_info.py index f5578940c..ea08f3306 100644 --- a/ansible_collections/cisco/dnac/plugins/modules/task_operation_info.py +++ b/ansible_collections/cisco/dnac/plugins/modules/task_operation_info.py @@ -34,8 +34,8 @@ options: value is 1. type: int requirements: -- dnacentersdk >= 2.5.5 -- python >= 3.5 +- dnacentersdk >= 2.6.0 +- python >= 3.9 seealso: - name: Cisco DNA Center documentation for Task GetTaskByOperationId description: Complete reference of the GetTaskByOperationId API. diff --git a/ansible_collections/cisco/dnac/plugins/modules/task_tree_info.py b/ansible_collections/cisco/dnac/plugins/modules/task_tree_info.py index bda7d8c51..9e80665b3 100644 --- a/ansible_collections/cisco/dnac/plugins/modules/task_tree_info.py +++ b/ansible_collections/cisco/dnac/plugins/modules/task_tree_info.py @@ -24,8 +24,8 @@ options: - TaskId path parameter. UUID of the Task. type: str requirements: -- dnacentersdk >= 2.5.5 -- python >= 3.5 +- dnacentersdk >= 2.6.0 +- python >= 3.9 seealso: - name: Cisco DNA Center documentation for Task GetTaskTree description: Complete reference of the GetTaskTree API. diff --git a/ansible_collections/cisco/dnac/plugins/modules/template_intent.py b/ansible_collections/cisco/dnac/plugins/modules/template_intent.py index c6e3042de..53c42e0ce 100644 --- a/ansible_collections/cisco/dnac/plugins/modules/template_intent.py +++ b/ansible_collections/cisco/dnac/plugins/modules/template_intent.py @@ -1104,7 +1104,7 @@ options: requirements: - dnacentersdk == 2.4.5 -- python >= 3.5 +- python >= 3.9 notes: - SDK Method used are configuration_templates.ConfigurationTemplates.create_template, @@ -1896,6 +1896,7 @@ class DnacTemplate(DnacBase): items = self.dnac_apply['exec']( family="configuration_templates", function="get_template_details", + op_modifies=True, params={"template_id": config.get("templateId")} ) if items: @@ -1980,6 +1981,7 @@ class DnacTemplate(DnacBase): template_list = self.dnac_apply['exec']( family="configuration_templates", function="gets_the_templates_available", + op_modifies=True, params={"projectNames": config.get("projectName")}, ) have_template["isCommitPending"] = True @@ -2371,8 +2373,8 @@ class DnacTemplate(DnacBase): response = self.dnac_apply['exec']( family="configuration_templates", function="update_template", - params=template_params, op_modifies=True, + params=template_params, ) template_updated = True self.log("Updating existing template '{0}'." @@ -2442,6 +2444,7 @@ class DnacTemplate(DnacBase): response = self.dnac._exec( family="configuration_templates", function='export_projects', + op_modifies=True, params={"payload": export_project}, ) validation_string = "successfully exported project" @@ -2458,6 +2461,7 @@ class DnacTemplate(DnacBase): response = self.dnac._exec( family="configuration_templates", function='export_templates', + op_modifies=True, params={"payload": self.export_template}, ) validation_string = "successfully exported template" @@ -2501,6 +2505,7 @@ class DnacTemplate(DnacBase): response = self.dnac._exec( family="configuration_templates", function='imports_the_projects_provided', + op_modifies=True, params=_import_project, ) validation_string = "successfully imported project" @@ -2529,6 +2534,7 @@ class DnacTemplate(DnacBase): response = self.dnac._exec( family="configuration_templates", function='imports_the_templates_provided', + op_modifies=True, params=import_template, ) validation_string = "successfully imported template" @@ -2592,6 +2598,7 @@ class DnacTemplate(DnacBase): response = self.dnac_apply['exec']( family="configuration_templates", function=deletion_value, + op_modifies=True, params=params_key, ) task_id = response.get("response").get("taskId") @@ -2716,6 +2723,7 @@ class DnacTemplate(DnacBase): template_list = self.dnac_apply['exec']( family="configuration_templates", function="gets_the_templates_available", + op_modifies=True, params={"projectNames": config.get("projectName")}, ) if template_list and isinstance(template_list, list): diff --git a/ansible_collections/cisco/dnac/plugins/modules/template_preview.py b/ansible_collections/cisco/dnac/plugins/modules/template_preview.py index bcd466a54..cb1657ccc 100644 --- a/ansible_collections/cisco/dnac/plugins/modules/template_preview.py +++ b/ansible_collections/cisco/dnac/plugins/modules/template_preview.py @@ -29,8 +29,8 @@ options: description: UUID of template to get template preview. type: str requirements: -- dnacentersdk >= 2.5.5 -- python >= 3.5 +- dnacentersdk >= 2.6.0 +- python >= 3.9 seealso: - name: Cisco DNA Center documentation for Configuration Templates PreviewTemplate description: Complete reference of the PreviewTemplate API. diff --git a/ansible_collections/cisco/dnac/plugins/modules/template_workflow_manager.py b/ansible_collections/cisco/dnac/plugins/modules/template_workflow_manager.py index 13e81da9a..fbd91685e 100644 --- a/ansible_collections/cisco/dnac/plugins/modules/template_workflow_manager.py +++ b/ansible_collections/cisco/dnac/plugins/modules/template_workflow_manager.py @@ -47,382 +47,385 @@ options: required: true suboptions: configuration_templates: - description: Create/Update/Delete template. + description: Perform operations such as Create/Update/Delete on a template. type: dict suboptions: author: - description: Author of template. + description: Identifies the creator of the template. type: str composite: - description: Is it composite template. + description: Specifies if the template is composite. type: bool containing_templates: - description: Configuration Template Create's containingTemplates. + description: + - Refer to a set of templates within the main template to define more complex or modular configurations. + - This is particularly useful in systems that support hierarchical or nested templates. + - Here parent templates may contain child templates to form a complete configuration. suboptions: composite: - description: Is it composite template. + description: Specifies if the template is composite. type: bool description: - description: Description of template. + description: Provides a description of the template. type: str device_types: - description: deviceTypes on which templates would be applied. + description: List of dictionaries details the types of devices that the templates can be applied to. type: list elements: dict suboptions: product_family: - description: Device family. + description: Denotes the family to which the device belongs. type: str product_series: - description: Device series. + description: Specifies the series classification of the device. type: str product_type: - description: Device type. + description: Describes the exact type of the device. type: str id: - description: UUID of template. + description: Unique identifier for the template, represented as a UUID. type: str language: - description: Template language + description: Programming language used for templating. Options are 'JINJA' for Jinja templating or 'VELOCITY' for Apache Velocity. choices: - JINJA - VELOCITY type: str name: - description: Name of template. + description: Designation of the template, serving as its unique name. type: str project_name: - description: Name of the project under which templates are managed. + description: Title of the project within which the template is categorized and managed. type: str project_description: - description: Description of the project created. + description: Narrative that elaborates on the purpose and scope of the project. type: str rollback_template_params: - description: Params required for template rollback. + description: A list of dictionaries defining parameters necessary for the rollback functionality of a template. type: list elements: dict suboptions: binding: - description: Bind to source. + description: Associates the parameter with its source. type: str custom_order: - description: CustomOrder of template param. + description: Specifies a user-defined ordering for the parameter. type: int data_type: - description: Datatype of template param. + description: Identifies the data type of the parameter (e.g., string, integer, boolean). type: str default_value: - description: Default value of template param. + description: Establishes a default value for the parameter, used if no other value is provided. type: str description: - description: Description of template param. + description: Provides a descriptive explanation of the parameter's purpose. type: str display_name: - description: Display name of param. + description: The name of the parameter as displayed to users. type: str group: - description: Group. + description: Categorizes the parameter into a named group for organizational purposes. type: str id: - description: UUID of template param. + description: A unique identifier for the parameter, formatted as a UUID. type: str instruction_text: - description: Instruction text for param. + description: Gives guidance or instructions regarding the parameter's use. type: str key: - description: Key. + description: A unique key that identifies the parameter within the template. type: str not_param: - description: Is it not a variable. + description: Indicates whether the entry is not to be treated as a parameter. type: bool order: - description: Order of template param. + description: Determines the sequence in which the parameter appears relative to others. type: int param_array: - description: Is it an array. + description: Specifies if the parameter should be treated as an array. type: bool parameter_name: - description: Name of template param. + description: The name of the parameter. type: str provider: - description: Provider. + description: Denotes the provider associated with the parameter. type: str range: - description: Configuration Template Create's range. + description: Defines the permissible range for the parameter's value. type: list elements: dict suboptions: id: - description: UUID of range. + description: Unique identifier for the range, represented as a UUID. type: str max_value: - description: Max value of range. + description: Specifies the maximum allowable value for the parameter. type: int min_value: - description: Min value of range. + description: Specifies the minimum allowable value for the parameter. type: int required: - description: Is param required. + description: Dictates whether the parameter is mandatory for template operations. type: bool selection: - description: Configuration Template Create's selection. + description: Contains options for parameter selection when a choice is available. suboptions: default_selected_values: - description: Default selection values. + description: Lists the default values that are preselected. elements: str type: list id: - description: UUID of selection. + description: A unique identifier for the selection entity, represented as a UUID. type: str selection_type: - description: Type of selection(SINGLE_SELECT or MULTI_SELECT). + description: Specifies the type of selection, such as 'SINGLE_SELECT' or 'MULTI_SELECT'. type: str selection_values: - description: Selection values. + description: A dictionary of available values for selection. type: dict type: dict tags: - description: Configuration Template Create's tags. + description: A list of dictionaries representing tags associated with the Configuration Template during creation. suboptions: id: - description: UUID of tag. + description: The unique identifier for each tag, presented as a UUID. type: str name: - description: Name of tag. + description: The descriptive label or name assigned to the tag. type: str type: list elements: dict template_content: - description: Template content. + description: The actual script or code constituting the body of the template. type: str template_params: - description: Configuration Template Create's templateParams. + description: The customization of the contents within the template. elements: dict suboptions: binding: - description: Bind to source. + description: Associates the parameter with its source. type: str custom_order: - description: CustomOrder of template param. + description: Specifies a user-defined ordering for the parameter. type: int data_type: - description: Datatype of template param. + description: Identifies the data type of the parameter (e.g., string, integer, boolean). type: str default_value: - description: Default value of template param. + description: Establishes a default value for the parameter, used if no other value is provided. type: str description: - description: Description of template param. + description: Provides a descriptive explanation of the parameter's purpose. type: str display_name: - description: Display name of param. + description: The name of the parameter as displayed to users. type: str group: - description: Group. + description: Categorizes the parameter into a named group for organizational purposes. type: str id: - description: UUID of template param. + description: A unique identifier for the parameter, formatted as a UUID. type: str instruction_text: - description: Instruction text for param. + description: Gives guidance or instructions regarding the parameter's use. type: str key: - description: Key. + description: A unique key that identifies the parameter within the template. type: str not_param: - description: Is it not a variable. + description: Indicates whether the entry is not to be treated as a parameter. type: bool order: - description: Order of template param. + description: Determines the sequence in which the parameter appears relative to others. type: int param_array: - description: Is it an array. + description: Specifies if the parameter should be treated as an array. type: bool parameter_name: - description: Name of template param. + description: The name of the parameter. type: str provider: - description: Provider. + description: Denotes the provider associated with the parameter. type: str range: - description: Configuration Template Create's range. + description: Defines the permissible range for the parameter's value. suboptions: id: - description: UUID of range. + description: Unique identifier for the range, represented as a UUID. type: str max_value: - description: Max value of range. + description: Specifies the maximum allowable value for the parameter. type: int min_value: - description: Min value of range. + description: Specifies the minimum allowable value for the parameter. type: int type: list elements: dict required: - description: Is param required. + description: Dictates whether the parameter is mandatory for template operations. type: bool selection: - description: Configuration Template Create's selection. + description: Contains options for parameter selection when a choice is available. suboptions: default_selected_values: - description: Default selection values. + description: Lists the default values that are preselected. elements: str type: list id: - description: UUID of selection. + description: A unique identifier for the selection entity, represented as a UUID. type: str selection_type: - description: Type of selection(SINGLE_SELECT or MULTI_SELECT). + description: Specifies the type of selection, such as 'SINGLE_SELECT' or 'MULTI_SELECT'. type: str selection_values: - description: Selection values. + description: A dictionary of available values for selection. type: dict type: dict type: list version: - description: Current version of template. + description: The current version of template. type: str type: list elements: dict create_time: - description: Create time of template. + description: The creation time of the template refers to the initial development. type: int custom_params_order: - description: Custom Params Order. + description: Specifies the sequence in which custom parameters or variables should be arranged within the template. type: bool template_description: - description: Description of template. + description: Provides a overview of the template. type: str device_types: - description: Configuration Template Create's deviceTypes. This field is mandatory to create a new template. + description: List of dictionaries details the types of devices that the templates can be applied to. + type: list + elements: dict suboptions: product_family: - description: Device family. + description: Denotes the family to which the device belongs. type: str product_series: - description: Device series. + description: Specifies the series classification of the device. type: str product_type: - description: Device type. + description: Describes the exact type of the device. type: str - type: list - elements: dict failure_policy: description: Define failure policy if template provisioning fails. type: str id: - description: UUID of template. + description: A unique identifier, represented as a UUID. type: str language: - description: Template language + description: Programming language used for templating. Options are 'JINJA' for Jinja templating or 'VELOCITY' for Apache Velocity. choices: - JINJA - VELOCITY type: str last_update_time: - description: Update time of template. + description: Indicates the most recent timestamp when the template was modified or revised. type: int latest_version_time: - description: Latest versioned template time. + description: Indicates when the most recent version of a template was released or updated. type: int template_name: description: Name of template. This field is mandatory to create a new template. type: str parent_template_id: - description: Parent templateID. + description: Refers to the unique identifier of a template from which another template derives. type: str project_id: - description: Project UUID. + description: A unique identifier for the project, formatted as a UUID. type: str project_name: - description: Project name. + description: Title of the project within which the template is categorized and managed. type: str project_description: - description: Project Description. + description: Narrative that elaborates on the purpose and scope of the project. type: str rollback_template_content: - description: Rollback template content. + description: Refers to the process of reverting the content of a template back to a previous version or state. type: str rollback_template_params: - description: Configuration Template Create's rollbackTemplateParams. + description: A list of dictionaries defining parameters necessary for the rollback functionality of a template. suboptions: binding: - description: Bind to source. + description: Associates the parameter with its source. type: str custom_order: - description: CustomOrder of template param. + description: Specifies a user-defined ordering for the parameter. type: int data_type: - description: Datatype of template param. + description: Identifies the data type of the parameter (e.g., string, integer, boolean). type: str default_value: - description: Default value of template param. + description: Establishes a default value for the parameter, used if no other value is provided. type: str description: - description: Description of template param. + description: Provides a descriptive explanation of the parameter's purpose. type: str display_name: - description: Display name of param. + description: The name of the parameter as displayed to users. type: str group: - description: Group. + description: Categorizes the parameter into a named group for organizational purposes. type: str id: - description: UUID of template param. + description: A unique identifier for the parameter, formatted as a UUID. type: str instruction_text: - description: Instruction text for param. + description: Gives guidance or instructions regarding the parameter's use. type: str key: - description: Key. + description: A unique key that identifies the parameter within the template. type: str not_param: - description: Is it not a variable. + description: Indicates whether the entry is not to be treated as a parameter. type: bool order: - description: Order of template param. + description: Determines the sequence in which the parameter appears relative to others. type: int param_array: - description: Is it an array. + description: Specifies if the parameter should be treated as an array. type: bool parameter_name: - description: Name of template param. + description: The name of the parameter. type: str provider: - description: Provider. + description: Denotes the provider associated with the parameter. type: str range: - description: Configuration Template Create's range. + description: Defines the permissible range for the parameter's value. suboptions: id: - description: UUID of range. + description: Unique identifier for the range, represented as a UUID. type: str max_value: - description: Max value of range. + description: Specifies the maximum allowable value for the parameter. type: int min_value: - description: Min value of range. + description: Specifies the minimum allowable value for the parameter. type: int type: list elements: dict required: - description: Is param required. + description: Dictates whether the parameter is mandatory for template operations. type: bool selection: - description: Configuration Template Create's selection. + description: Contains options for parameter selection when a choice is available. suboptions: default_selected_values: - description: Default selection values. + description: Lists the default values that are preselected. elements: str type: list id: - description: UUID of selection. + description: A unique identifier for the selection entity, represented as a UUID. type: str selection_type: - description: Type of selection(SINGLE_SELECT or MULTI_SELECT). + description: Specifies the type of selection, such as 'SINGLE_SELECT' or 'MULTI_SELECT'. type: str selection_values: - description: Selection values. + description: A dictionary of available values for selection. type: dict type: dict type: list @@ -431,143 +434,143 @@ options: description: Applicable device software type. This field is mandatory to create a new template. type: str software_variant: - description: Applicable device software variant. + description: Refers to a version or edition of a software application that differs from the main or standard release. type: str software_version: description: Applicable device software version. type: str template_tag: - description: Configuration Template Create's tags. + description: Refers to a keyword, label, or metadata assigned to a template. suboptions: id: - description: UUID of tag. + description: A unique identifier for the tag, represented as a UUID. type: str name: - description: Name of tag. + description: The name of the tag. type: str type: list elements: dict template_content: - description: Template content. + description: The actual script or code constituting the body of the template. type: str template_params: - description: Configuration Template Create's templateParams. + description: The customization of the contents within the template. suboptions: binding: - description: Bind to source. + description: Associates the parameter with its source. type: str custom_order: - description: CustomOrder of template param. + description: Specifies a user-defined ordering for the parameter. type: int data_type: - description: Datatype of template param. + description: Identifies the data type of the parameter (e.g., string, integer, boolean). type: str default_value: - description: Default value of template param. + description: Establishes a default value for the parameter, used if no other value is provided. type: str description: - description: Description of template param. + description: Provides a descriptive explanation of the parameter's purpose. type: str display_name: - description: Display name of param. + description: The name of the parameter as displayed to users. type: str group: - description: Group. + description: Categorizes the parameter into a named group for organizational purposes. type: str id: - description: UUID of template param. + description: A unique identifier for the parameter, formatted as a UUID. type: str instruction_text: - description: Instruction text for param. + description: Gives guidance or instructions regarding the parameter's use. type: str key: - description: Key. + description: A unique key that identifies the parameter within the template. type: str not_param: - description: Is it not a variable. + description: Indicates whether the entry is not to be treated as a parameter. type: bool order: - description: Order of template param. + description: Determines the sequence in which the parameter appears relative to others. type: int param_array: - description: Is it an array. + description: Specifies if the parameter should be treated as an array. type: bool parameter_name: - description: Name of template param. + description: The name of the parameter. type: str provider: - description: Provider. + description: Denotes the provider associated with the parameter. type: str range: - description: Configuration Template Create's range. + description: Defines the permissible range for the parameter's value. suboptions: id: - description: UUID of range. + description: Unique identifier for the range, represented as a UUID. type: str max_value: - description: Max value of range. + description: Specifies the maximum allowable value for the parameter. type: int min_value: - description: Min value of range. + description: Specifies the minimum allowable value for the parameter. type: int type: list elements: dict required: - description: Is param required. + description: Dictates whether the parameter is mandatory for template operations. type: bool selection: - description: Configuration Template Create's selection. + description: Contains options for parameter selection when a choice is available. suboptions: default_selected_values: - description: Default selection values. + description: Lists the default values that are preselected. elements: str type: list id: - description: UUID of selection. + description: A unique identifier for the selection entity, represented as a UUID. type: str selection_type: - description: Type of selection(SINGLE_SELECT or MULTI_SELECT). + description: Specifies the type of selection, such as 'SINGLE_SELECT' or 'MULTI_SELECT'. type: str selection_values: - description: Selection values. + description: A dictionary of available values for selection. type: dict type: dict type: list elements: dict validation_errors: - description: Configuration Template Create's validationErrors. + description: Refer to issues or discrepancies identified during the validation process. suboptions: rollback_template_errors: description: Validation or design conflicts errors of rollback template. elements: dict type: list template_errors: - description: Validation or design conflicts errors. + description: Refer to issues or discrepancies encountered during the processing of a template within a software application. elements: dict type: list template_id: - description: UUID of template. + description: A unique identifier for the template, represented as a UUID. type: str template_version: - description: Current version of template. + description: The current version of validation process in the template. type: str type: dict version: - description: Current version of template. + description: The current version of template. type: str version_description: description: Template version comments. type: str export: - description: Export the project/template details. + description: Perform export on the projects and templates. type: dict suboptions: project: - description: Export the project. + description: Export the project(s) details. type: list elements: str template: - description: Export the template. + description: Export the template(s) details. type: list elements: dict suboptions: @@ -575,14 +578,14 @@ options: description: Name of the project under the template available. type: str template_name: - description: Name of the template which we need to export + description: Name of the template which we need to be exported. type: str import: - description: Import the project/template details. + description: Perform import on the projects and templates. type: dict suboptions: project: - description: Import the project details. + description: Import the projects. type: dict suboptions: do_version: @@ -592,7 +595,7 @@ options: fails with 'Template already exists' error. type: bool template: - description: Import the template details. + description: Import the templates. type: dict suboptions: do_version: @@ -601,502 +604,524 @@ options: exists. " If false and if template already exists, then operation fails with 'Template already exists' error. type: bool + template_file: + description: + - Specifies the path to a JSON file that contains an import template. + - If both 'template_file' and 'payload' are provided, the 'template_file' will be given priority. + type: str payload: - description: Configuration Template Import Template's payload. + description: + - The payload parameter is used to directly import configuration data into the system. + - The payload provides an alternative way to import configurations without the need to reference an external file. + - If both 'template_file' and 'payload' are provided, the 'template_file' will be given priority. + type: list elements: dict suboptions: author: - description: Author of template. + description: Identifies the creator of the template. type: str composite: - description: Is it composite template. + description: Specifies if the template is composite. type: bool containing_templates: - description: Configuration Template Import Template's containingTemplates. - elements: dict + description: + - Refer to a set of templates within the main template to define more complex or modular configurations. + - This is particularly useful in systems that support hierarchical or nested templates. + - Here parent templates may contain child templates to form a complete configuration. suboptions: composite: - description: Is it composite template. + description: Specifies if the template is composite. type: bool description: - description: Description of template. + description: Provides a description of the template. type: str device_types: - description: Configuration Template Import Template's deviceTypes. + description: List of dictionaries details the types of devices that the templates can be applied to. + type: list elements: dict suboptions: product_family: - description: Device family. + description: Denotes the family to which the device belongs. type: str product_series: - description: Device series. + description: Specifies the series classification of the device. type: str product_type: - description: Device type. + description: Describes the exact type of the device. type: str - type: list id: - description: UUID of template. + description: Unique identifier for the template, represented as a UUID. type: str language: - description: Template language (JINJA or VELOCITY). + description: Programming language used for templating. Options are 'JINJA' for Jinja templating or 'VELOCITY' for Apache Velocity. + choices: + - JINJA + - VELOCITY type: str name: - description: Name of template. + description: Designation of the template, serving as its unique name. type: str project_name: - description: Project name. + description: Title of the project within which the template is categorized and managed. type: str rollback_template_params: - description: Configuration Template Import Template's rollbackTemplateParams. + description: A list of dictionaries defining parameters necessary for the rollback functionality of a template. + type: list elements: dict suboptions: binding: - description: Bind to source. + description: Associates the parameter with its source. type: str custom_order: - description: CustomOrder of template param. + description: Specifies a user-defined ordering for the parameter. type: int data_type: - description: Datatype of template param. + description: Identifies the data type of the parameter (e.g., string, integer, boolean). type: str default_value: - description: Default value of template param. + description: Establishes a default value for the parameter, used if no other value is provided. type: str description: - description: Description of template param. + description: Provides a descriptive explanation of the parameter's purpose. type: str display_name: - description: Display name of param. + description: The name of the parameter as displayed to users. type: str group: - description: Group. + description: Categorizes the parameter into a named group for organizational purposes. type: str id: - description: UUID of template param. + description: A unique identifier for the parameter, formatted as a UUID. type: str instruction_text: - description: Instruction text for param. + description: Gives guidance or instructions regarding the parameter's use. type: str key: - description: Key. + description: A unique key that identifies the parameter within the template. type: str not_param: - description: Is it not a variable. + description: Indicates whether the entry is not to be treated as a parameter. type: bool order: - description: Order of template param. + description: Determines the sequence in which the parameter appears relative to others. type: int param_array: - description: Is it an array. + description: Specifies if the parameter should be treated as an array. type: bool parameter_name: - description: Name of template param. + description: The name of the parameter. type: str provider: - description: Provider. + description: Denotes the provider associated with the parameter. type: str range: - description: Configuration Template Import Template's range. + description: Defines the permissible range for the parameter's value. + type: list elements: dict suboptions: id: - description: UUID of range. + description: Unique identifier for the range, represented as a UUID. type: str max_value: - description: Max value of range. + description: Specifies the maximum allowable value for the parameter. type: int min_value: - description: Min value of range. + description: Specifies the minimum allowable value for the parameter. type: int - type: list required: - description: Is param required. + description: Dictates whether the parameter is mandatory for template operations. type: bool selection: - description: Configuration Template Import Template's selection. + description: Contains options for parameter selection when a choice is available. suboptions: default_selected_values: - description: Default selection values. + description: Lists the default values that are preselected. elements: str type: list id: - description: UUID of selection. + description: A unique identifier for the selection entity, represented as a UUID. type: str selection_type: - description: Type of selection(SINGLE_SELECT or MULTI_SELECT). + description: Specifies the type of selection, such as 'SINGLE_SELECT' or 'MULTI_SELECT'. type: str selection_values: - description: Selection values. + description: A dictionary of available values for selection. type: dict type: dict - type: list tags: - description: Configuration Template Import Template's tags. - elements: dict + description: A list of dictionaries representing tags associated with the Configuration Template during creation. suboptions: id: - description: UUID of tag. + description: The unique identifier for each tag, presented as a UUID. type: str name: - description: Name of tag. + description: The descriptive label or name assigned to the tag. type: str type: list + elements: dict template_content: - description: Template content. + description: The actual script or code constituting the body of the template. type: str template_params: - description: Configuration Template Import Template's templateParams. + description: The customization of the contents within the template. elements: dict suboptions: binding: - description: Bind to source. + description: Associates the parameter with its source. type: str custom_order: - description: CustomOrder of template param. + description: Specifies a user-defined ordering for the parameter. type: int data_type: - description: Datatype of template param. + description: Identifies the data type of the parameter (e.g., string, integer, boolean). type: str default_value: - description: Default value of template param. + description: Establishes a default value for the parameter, used if no other value is provided. type: str description: - description: Description of template param. + description: Provides a descriptive explanation of the parameter's purpose. type: str display_name: - description: Display name of param. + description: The name of the parameter as displayed to users. type: str group: - description: Group. + description: Categorizes the parameter into a named group for organizational purposes. type: str id: - description: UUID of template param. + description: A unique identifier for the parameter, formatted as a UUID. type: str instruction_text: - description: Instruction text for param. + description: Gives guidance or instructions regarding the parameter's use. type: str key: - description: Key. + description: A unique key that identifies the parameter within the template. type: str not_param: - description: Is it not a variable. + description: Indicates whether the entry is not to be treated as a parameter. type: bool order: - description: Order of template param. + description: Determines the sequence in which the parameter appears relative to others. type: int param_array: - description: Is it an array. + description: Specifies if the parameter should be treated as an array. type: bool parameter_name: - description: Name of template param. + description: The name of the parameter. type: str provider: - description: Provider. + description: Denotes the provider associated with the parameter. type: str range: - description: Configuration Template Import Template's range. - elements: dict + description: Defines the permissible range for the parameter's value. suboptions: id: - description: UUID of range. + description: Unique identifier for the range, represented as a UUID. type: str max_value: - description: Max value of range. + description: Specifies the maximum allowable value for the parameter. type: int min_value: - description: Min value of range. + description: Specifies the minimum allowable value for the parameter. type: int type: list + elements: dict required: - description: Is param required. + description: Dictates whether the parameter is mandatory for template operations. type: bool selection: - description: Configuration Template Import Template's selection. + description: Contains options for parameter selection when a choice is available. suboptions: default_selected_values: - description: Default selection values. + description: Lists the default values that are preselected. elements: str type: list id: - description: UUID of selection. + description: A unique identifier for the selection entity, represented as a UUID. type: str selection_type: - description: Type of selection(SINGLE_SELECT or MULTI_SELECT). + description: Specifies the type of selection, such as 'SINGLE_SELECT' or 'MULTI_SELECT'. type: str selection_values: - description: Selection values. + description: A dictionary of available values for selection. type: dict type: dict type: list version: - description: Current version of template. + description: The current version of template. type: str type: list + elements: dict create_time: - description: Create time of template. + description: The creation time of the template refers to the initial development. type: int custom_params_order: - description: Custom Params Order. + description: Specifies the sequence in which custom parameters or variables should be arranged within the template. type: bool - description: - description: Description of template. + template_description: + description: Provides a overview of the template. type: str device_types: - description: Configuration Template Import Template's deviceTypes. + description: List of dictionaries details the types of devices that the templates can be applied to. + type: list elements: dict suboptions: product_family: - description: Device family. + description: Denotes the family to which the device belongs. type: str product_series: - description: Device series. + description: Specifies the series classification of the device. type: str product_type: - description: Device type. + description: Describes the exact type of the device. type: str - type: list failure_policy: description: Define failure policy if template provisioning fails. type: str id: - description: UUID of template. + description: A unique identifier, represented as a UUID. type: str language: - description: Template language (JINJA or VELOCITY). + description: Programming language used for templating. Options are 'JINJA' for Jinja templating or 'VELOCITY' for Apache Velocity. + choices: + - JINJA + - VELOCITY type: str last_update_time: - description: Update time of template. + description: Indicates the most recent timestamp when the template was modified or revised. type: int latest_version_time: - description: Latest versioned template time. + description: Indicates when the most recent version of a template was released or updated. type: int - name: - description: Name of template. + template_name: + description: Name of template. This field is mandatory to create a new template. type: str parent_template_id: - description: Parent templateID. + description: Refers to the unique identifier of a template from which another template derives. type: str project_id: - description: Project UUID. + description: A unique identifier for the project, formatted as a UUID. type: str project_name: - description: Project name. + description: Title of the project within which the template is categorized and managed. + type: str + project_description: + description: Narrative that elaborates on the purpose and scope of the project. type: str rollback_template_content: - description: Rollback template content. + description: Refers to the process of reverting the content of a template back to a previous version or state. type: str rollback_template_params: - description: Configuration Template Import Template's rollbackTemplateParams. - elements: dict + description: A list of dictionaries defining parameters necessary for the rollback functionality of a template. suboptions: binding: - description: Bind to source. + description: Associates the parameter with its source. type: str custom_order: - description: CustomOrder of template param. + description: Specifies a user-defined ordering for the parameter. type: int data_type: - description: Datatype of template param. + description: Identifies the data type of the parameter (e.g., string, integer, boolean). type: str default_value: - description: Default value of template param. + description: Establishes a default value for the parameter, used if no other value is provided. type: str description: - description: Description of template param. + description: Provides a descriptive explanation of the parameter's purpose. type: str display_name: - description: Display name of param. + description: The name of the parameter as displayed to users. type: str group: - description: Group. + description: Categorizes the parameter into a named group for organizational purposes. type: str id: - description: UUID of template param. + description: A unique identifier for the parameter, formatted as a UUID. type: str instruction_text: - description: Instruction text for param. + description: Gives guidance or instructions regarding the parameter's use. type: str key: - description: Key. + description: A unique key that identifies the parameter within the template. type: str not_param: - description: Is it not a variable. + description: Indicates whether the entry is not to be treated as a parameter. type: bool order: - description: Order of template param. + description: Determines the sequence in which the parameter appears relative to others. type: int param_array: - description: Is it an array. + description: Specifies if the parameter should be treated as an array. type: bool parameter_name: - description: Name of template param. + description: The name of the parameter. type: str provider: - description: Provider. + description: Denotes the provider associated with the parameter. type: str range: - description: Configuration Template Import Template's range. - elements: dict + description: Defines the permissible range for the parameter's value. suboptions: id: - description: UUID of range. + description: Unique identifier for the range, represented as a UUID. type: str max_value: - description: Max value of range. + description: Specifies the maximum allowable value for the parameter. type: int min_value: - description: Min value of range. + description: Specifies the minimum allowable value for the parameter. type: int type: list + elements: dict required: - description: Is param required. + description: Dictates whether the parameter is mandatory for template operations. type: bool selection: - description: Configuration Template Import Template's selection. + description: Contains options for parameter selection when a choice is available. suboptions: default_selected_values: - description: Default selection values. + description: Lists the default values that are preselected. elements: str type: list id: - description: UUID of selection. + description: A unique identifier for the selection entity, represented as a UUID. type: str selection_type: - description: Type of selection(SINGLE_SELECT or MULTI_SELECT). + description: Specifies the type of selection, such as 'SINGLE_SELECT' or 'MULTI_SELECT'. type: str selection_values: - description: Selection values. + description: A dictionary of available values for selection. type: dict type: dict type: list + elements: dict software_type: - description: Applicable device software type. + description: Applicable device software type. This field is mandatory to create a new template. type: str software_variant: - description: Applicable device software variant. + description: Refers to a version or edition of a software application that differs from the main or standard release. type: str software_version: description: Applicable device software version. type: str - tags: - description: Configuration Template Import Template's tags. - elements: dict + template_tag: + description: Refers to a keyword, label, or metadata assigned to a template. suboptions: id: - description: UUID of tag. + description: A unique identifier for the tag, represented as a UUID. type: str name: - description: Name of tag. + description: The name of the tag. type: str type: list + elements: dict template_content: - description: Template content. + description: The actual script or code constituting the body of the template. type: str template_params: - description: Configuration Template Import Template's templateParams. - elements: dict + description: The customization of the contents within the template. suboptions: binding: - description: Bind to source. + description: Associates the parameter with its source. type: str custom_order: - description: CustomOrder of template param. + description: Specifies a user-defined ordering for the parameter. type: int data_type: - description: Datatype of template param. + description: Identifies the data type of the parameter (e.g., string, integer, boolean). type: str default_value: - description: Default value of template param. + description: Establishes a default value for the parameter, used if no other value is provided. type: str description: - description: Description of template param. + description: Provides a descriptive explanation of the parameter's purpose. type: str display_name: - description: Display name of param. + description: The name of the parameter as displayed to users. type: str group: - description: Group. + description: Categorizes the parameter into a named group for organizational purposes. type: str id: - description: UUID of template param. + description: A unique identifier for the parameter, formatted as a UUID. type: str instruction_text: - description: Instruction text for param. + description: Gives guidance or instructions regarding the parameter's use. type: str key: - description: Key. + description: A unique key that identifies the parameter within the template. type: str not_param: - description: Is it not a variable. + description: Indicates whether the entry is not to be treated as a parameter. type: bool order: - description: Order of template param. + description: Determines the sequence in which the parameter appears relative to others. type: int param_array: - description: Is it an array. + description: Specifies if the parameter should be treated as an array. type: bool parameter_name: - description: Name of template param. + description: The name of the parameter. type: str provider: - description: Provider. + description: Denotes the provider associated with the parameter. type: str range: - description: Configuration Template Import Template's range. - elements: dict + description: Defines the permissible range for the parameter's value. suboptions: id: - description: UUID of range. + description: Unique identifier for the range, represented as a UUID. type: str max_value: - description: Max value of range. + description: Specifies the maximum allowable value for the parameter. type: int min_value: - description: Min value of range. + description: Specifies the minimum allowable value for the parameter. type: int type: list + elements: dict required: - description: Is param required. + description: Dictates whether the parameter is mandatory for template operations. type: bool selection: - description: Configuration Template Import Template's selection. + description: Contains options for parameter selection when a choice is available. suboptions: default_selected_values: - description: Default selection values. + description: Lists the default values that are preselected. elements: str type: list id: - description: UUID of selection. + description: A unique identifier for the selection entity, represented as a UUID. type: str selection_type: - description: Type of selection(SINGLE_SELECT or MULTI_SELECT). + description: Specifies the type of selection, such as 'SINGLE_SELECT' or 'MULTI_SELECT'. type: str selection_values: - description: Selection values. + description: A dictionary of available values for selection. type: dict type: dict type: list + elements: dict validation_errors: - description: Configuration Template Import Template's validationErrors. + description: Refer to issues or discrepancies identified during the validation process. suboptions: rollback_template_errors: - description: Validation or design conflicts errors of rollback template. - type: dict + description: Refer to errors or issues encountered during the process of reverting a template to a previous version or state. + elements: dict + type: list template_errors: - description: Validation or design conflicts errors. - type: dict + description: Refer to issues or discrepancies encountered during the processing of a template within a software application. + elements: dict + type: list template_id: - description: UUID of template. + description: A unique identifier for the template, represented as a UUID. type: str template_version: - description: Current version of template. + description: The current version of validation process in the template. type: str type: dict version: - description: Current version of template. + description: The current version of template. type: str - type: list project_name: description: ProjectName path parameter. Project name to create template under the project. @@ -1104,7 +1129,7 @@ options: requirements: - dnacentersdk == 2.4.5 -- python >= 3.5 +- python >= 3.9 notes: - SDK Method used are configuration_templates.ConfigurationTemplates.create_template, @@ -1239,6 +1264,26 @@ EXAMPLES = r""" - name: string - name: string +- name: Import the Templates. + cisco.dnac.template_workflow_manager: + dnac_host: "{{dnac_host}}" + dnac_username: "{{dnac_username}}" + dnac_password: "{{dnac_password}}" + dnac_verify: "{{dnac_verify}}" + dnac_port: "{{dnac_port}}" + dnac_version: "{{dnac_version}}" + dnac_debug: "{{dnac_debug}}" + dnac_log: True + dnac_log_level: "{{dnac_log_level}}" + state: merged + config_verify: True + config: + import: + template: + do_version: false + project_name: string + template_file: string + """ RETURN = r""" @@ -1312,6 +1357,7 @@ response_5: """ import copy +import json from ansible.module_utils.basic import AnsibleModule from ansible_collections.cisco.dnac.plugins.module_utils.dnac import ( DnacBase, @@ -1331,7 +1377,11 @@ class Template(DnacBase): self.supported_states = ["merged", "deleted"] self.accepted_languages = ["JINJA", "VELOCITY"] self.export_template = [] - self.result['response'].append({}) + self.result['response'] = [ + {"configurationTemplate": {"response": {}, "msg": {}}}, + {"export": {"response": {}}}, + {"import": {"response": {}}} + ] def validate_input(self): """ @@ -1367,7 +1417,7 @@ class Template(DnacBase): 'containing_templates': {'type': 'list'}, 'create_time': {'type': 'int'}, 'custom_params_order': {'type': 'bool'}, - 'description': {'type': 'str'}, + 'template_description': {'type': 'str'}, 'device_types': { 'type': 'list', 'elements': 'dict', @@ -1394,8 +1444,7 @@ class Template(DnacBase): 'template_params': {'type': 'list'}, 'template_name': {'type': 'str'}, 'validation_errors': {'type': 'dict'}, - 'version': {'type': 'str'}, - 'version_description': {'type': 'str'} + 'version': {'type': 'str'} }, 'export': { 'type': 'dict', @@ -1425,7 +1474,7 @@ class Template(DnacBase): 'containing_templates': {'type': 'list'}, 'create_time': {'type': 'int'}, 'custom_params_order': {'type': 'bool'}, - 'description': {'type': 'str'}, + 'template_description': {'type': 'str'}, 'device_types': { 'type': 'list', 'elements': 'dict', @@ -1857,7 +1906,6 @@ class Template(DnacBase): """ self.log("Template params playbook details: {0}".format(params), "DEBUG") - self.log(str(params)) temp_params = { "tags": self.get_tags(params.get("template_tag")), "author": params.get("author"), @@ -1917,7 +1965,7 @@ class Template(DnacBase): self.status = "failed" return self.check_return_status() - temp_params.update({"project_name": projectName}) + temp_params.update({"projectName": projectName}) softwareType = params.get("software_type") if not softwareType: @@ -1932,7 +1980,6 @@ class Template(DnacBase): for item in copy_temp_params: if temp_params[item] is None: del temp_params[item] - self.log(str(temp_params)) return temp_params def get_template(self, config): @@ -1950,13 +1997,14 @@ class Template(DnacBase): items = self.dnac_apply['exec']( family="configuration_templates", function="get_template_details", + op_modifies=True, params={"template_id": config.get("templateId")} ) if items: result = items self.log("Received API response from 'get_template_details': {0}".format(items), "DEBUG") - self.result['response'] = items + self.result['response'][0].get("configurationTemplate").update({"items": items}) return result def get_have_project(self, config): @@ -2034,6 +2082,7 @@ class Template(DnacBase): template_list = self.dnac_apply['exec']( family="configuration_templates", function="gets_the_templates_available", + op_modifies=True, params={"projectNames": config.get("projectName")}, ) have_template["isCommitPending"] = True @@ -2290,8 +2339,6 @@ class Template(DnacBase): # Mandate fields required for creating a new template. # Store it with other template parameters. - self.log(str(template_params)) - self.log(str(self.have_project)) template_params["projectId"] = self.have_project.get("id") template_params["project_id"] = self.have_project.get("id") # Update language,deviceTypes and softwareType if not provided for existing template. @@ -2419,7 +2466,7 @@ class Template(DnacBase): if is_template_found: if not self.requires_update(): # Template does not need update - self.result.update({ + self.result['response'][0].get("configurationTemplate").update({ 'response': self.have_template.get("template"), 'msg': "Template does not need update" }) @@ -2433,8 +2480,8 @@ class Template(DnacBase): response = self.dnac_apply['exec']( family="configuration_templates", function="update_template", - params=template_params, op_modifies=True, + params=template_params, ) template_updated = True self.log("Updating existing template '{0}'." @@ -2466,12 +2513,12 @@ class Template(DnacBase): return self task_details = self.get_task_details(task_id) self.result['changed'] = True - self.result['msg'] = task_details.get('progress') - self.result['diff'] = configuration_templates + self.result['response'][0].get("configurationTemplate")['msg'] = task_details.get('progress') + self.result['response'][0].get("configurationTemplate")['diff'] = configuration_templates self.log("Task details for 'version_template': {0}".format(task_details), "DEBUG") - self.result['response'] = task_details if task_details else response + self.result['response'][0].get("configurationTemplate")['response'] = task_details if task_details else response - if not self.result.get('msg'): + if not self.result['response'][0].get("configurationTemplate").get('msg'): self.msg = "Error while versioning the template" self.status = "failed" return self @@ -2494,16 +2541,16 @@ class Template(DnacBase): response = self.dnac._exec( family="configuration_templates", function='export_projects', + op_modifies=True, params={ "payload": export_project, - "active_validation": False, }, ) validation_string = "successfully exported project" self.check_task_response_status(response, validation_string, True).check_return_status() - self.result['response'][0].update({"exportProject": self.msg}) + self.result['response'][1].get("export").get("response").update({"exportProject": self.msg}) export_values = export.get("template") if export_values: @@ -2513,16 +2560,16 @@ class Template(DnacBase): response = self.dnac._exec( family="configuration_templates", function='export_templates', + op_modifies=True, params={ "payload": self.export_template, - "active_validation": False, }, ) validation_string = "successfully exported template" self.check_task_response_status(response, validation_string, True).check_return_status() - self.result['response'][0].update({"exportTemplate": self.msg}) + self.result['response'][1].get("export").get("response").update({"exportTemplate": self.msg}) return self @@ -2558,7 +2605,6 @@ class Template(DnacBase): _import_project = { "do_version": do_version, "payload": final_payload, - "active_validation": False, } self.log("Importing project details from the playbook: {0}" .format(_import_project), "DEBUG") @@ -2566,14 +2612,15 @@ class Template(DnacBase): response = self.dnac._exec( family="configuration_templates", function='imports_the_projects_provided', + op_modifies=True, params=_import_project, ) validation_string = "successfully imported project" self.check_task_response_status(response, validation_string).check_return_status() - self.result['response'][0].update({"importProject": validation_string}) + self.result['response'][2].get("import").get("response").update({"importProject": validation_string}) else: self.msg = "Projects '{0}' already available.".format(payload) - self.result['response'][0].update({ + self.result['response'][2].get("import").get("response").update({ "importProject": "Projects '{0}' already available.".format(payload) }) @@ -2582,39 +2629,71 @@ class Template(DnacBase): do_version = _import_template.get("do_version") if not do_version: do_version = False + + project_name = _import_template.get("project_name") if not _import_template.get("project_name"): self.msg = "Mandatory parameter project_name is not found under import template" self.status = "failed" return self - if not _import_template.get("payload"): - self.msg = "Mandatory parameter payload is not found under import template" + is_project_exists = self.get_project_details(project_name) + if not is_project_exists: + self.msg = "Project '{0}' is not found.".format(project_name) self.status = "failed" return self payload = _import_template.get("payload") - final_payload = [] - for item in payload: - self.log(str(item)) - final_payload.append(self.get_template_params(item)) - self.log(str(final_payload)) + template_file = _import_template.get("template_file") + if not (payload or template_file): + self.msg = "Mandatory parameter 'payload' or 'template_file' is not found under import template" + self.status = "failed" + return self + + final_payload = None + if template_file: + is_path_exists = self.is_path_exists(template_file) + if not is_path_exists: + self.msg = "Import template file path '{0}' does not exist.".format(template_file) + self.status = "failed" + return self + + is_json = self.is_json(template_file) + if not is_json: + self.msg = "Import template file '{0}' is not in JSON format".format(template_file) + self.status = "failed" + return self + try: + with open(template_file, 'r') as file: + json_data = file.read() + json_template = json.loads(json_data) + final_payload = json_template + except Exception as msg: + self.msg = "An unexpected error occurred while processing the file '{0}': {1}".format(template_file, msg) + self.status = "failed" + return self + + elif payload: + final_payload = [] + for item in payload: + final_payload.append(self.get_template_params(item)) import_template = { - "do_version": _import_template.get("do_version"), - "project_name": _import_template.get("project_name"), + "do_version": do_version, + "project_name": project_name, "payload": final_payload, - "active_validation": False, } self.log("Import template details from the playbook: {0}" - .format(_import_template), "DEBUG") + .format(import_template), "DEBUG") if _import_template: response = self.dnac._exec( family="configuration_templates", function='imports_the_templates_provided', + op_modifies=True, params=import_template ) validation_string = "successfully imported template" self.check_task_response_status(response, validation_string).check_return_status() - self.result['response'][0].update({"importTemplate": validation_string}) + self.result['response'][2].get("import").get("response") \ + .update({"importTemplate": "Successfully imported the templates"}) return self @@ -2679,19 +2758,20 @@ class Template(DnacBase): response = self.dnac_apply['exec']( family="configuration_templates", function=deletion_value, + op_modifies=True, params=params_key, ) task_id = response.get("response").get("taskId") if task_id: task_details = self.get_task_details(task_id) self.result['changed'] = True - self.result['msg'] = task_details.get('progress') - self.result['diff'] = config.get("configuration_templates") + self.result['response'][0].get("configurationTemplate")['msg'] = task_details.get('progress') + self.result['response'][0].get("configurationTemplate")['diff'] = config.get("configuration_templates") self.log("Task details for '{0}': {1}".format(deletion_value, task_details), "DEBUG") - self.result['response'] = task_details if task_details else response - if not self.result['msg']: - self.result['msg'] = "Error while deleting {name} : " + self.result['response'][0].get("configurationTemplate")['response'] = task_details if task_details else response + if not self.result['response'][0].get("configurationTemplate")['msg']: + self.result['response'][0].get("configurationTemplate")['msg'] = "Error while deleting {name} : " self.status = "failed" return self @@ -2774,11 +2854,11 @@ class Template(DnacBase): "softwareVariant", "templateContent"] for item in template_params: if self.have_template.get("template").get(item) != self.want.get("template_params").get(item): - self.msg = " Configuration Template config is not applied to the Cisco Catalyst Center." + self.msg = "Configuration Template config is not applied to the Cisco Catalyst Center." self.status = "failed" return self self.log("Successfully validated the Template in the Catalyst Center.", "INFO") - self.result.get("response").update({"Validation": "Success"}) + self.result['response'][0].get("configurationTemplate").get("response").update({"Validation": "Success"}) self.msg = "Successfully validated the Configuration Templates." self.status = "success" @@ -2803,6 +2883,7 @@ class Template(DnacBase): template_list = self.dnac_apply['exec']( family="configuration_templates", function="gets_the_templates_available", + op_modifies=True, params={"projectNames": config.get("projectName")}, ) if template_list and isinstance(template_list, list): @@ -2816,7 +2897,7 @@ class Template(DnacBase): return self self.log("Successfully validated absence of template in the Catalyst Center.", "INFO") - self.result.get("response").update({"Validation": "Success"}) + self.result['response'][0].get("configurationTemplate").get("response").update({"Validation": "Success"}) self.msg = "Successfully validated the absence of Template in the Cisco Catalyst Center." self.status = "success" @@ -2841,24 +2922,25 @@ class Template(DnacBase): def main(): """ main entry point for module execution""" - element_spec = {'dnac_host': {'required': True, 'type': 'str'}, - 'dnac_port': {'type': 'str', 'default': '443'}, - 'dnac_username': {'type': 'str', 'default': 'admin', 'aliases': ['user']}, - 'dnac_password': {'type': 'str', 'no_log': True}, - 'dnac_verify': {'type': 'bool', 'default': 'True'}, - 'dnac_version': {'type': 'str', 'default': '2.2.3.3'}, - 'dnac_debug': {'type': 'bool', 'default': False}, - 'dnac_log': {'type': 'bool', 'default': False}, - "dnac_log_level": {"type": 'str', "default": 'WARNING'}, - "dnac_log_file_path": {"type": 'str', "default": 'dnac.log'}, - "dnac_log_append": {"type": 'bool', "default": True}, - 'validate_response_schema': {'type': 'bool', 'default': True}, - "config_verify": {"type": 'bool', "default": False}, - 'dnac_api_task_timeout': {'type': 'int', "default": 1200}, - 'dnac_task_poll_interval': {'type': 'int', "default": 2}, - 'config': {'required': True, 'type': 'list', 'elements': 'dict'}, - 'state': {'default': 'merged', 'choices': ['merged', 'deleted']} - } + element_spec = { + 'dnac_host': {'required': True, 'type': 'str'}, + 'dnac_port': {'type': 'str', 'default': '443'}, + 'dnac_username': {'type': 'str', 'default': 'admin', 'aliases': ['user']}, + 'dnac_password': {'type': 'str', 'no_log': True}, + 'dnac_verify': {'type': 'bool', 'default': 'True'}, + 'dnac_version': {'type': 'str', 'default': '2.2.3.3'}, + 'dnac_debug': {'type': 'bool', 'default': False}, + 'dnac_log': {'type': 'bool', 'default': False}, + "dnac_log_level": {"type": 'str', "default": 'WARNING'}, + "dnac_log_file_path": {"type": 'str', "default": 'dnac.log'}, + "dnac_log_append": {"type": 'bool', "default": True}, + 'validate_response_schema': {'type': 'bool', 'default': True}, + "config_verify": {"type": 'bool', "default": False}, + 'dnac_api_task_timeout': {'type': 'int', "default": 1200}, + 'dnac_task_poll_interval': {'type': 'int', "default": 2}, + 'config': {'required': True, 'type': 'list', 'elements': 'dict'}, + 'state': {'default': 'merged', 'choices': ['merged', 'deleted']} + } module = AnsibleModule(argument_spec=element_spec, supports_check_mode=False) ccc_template = Template(module) diff --git a/ansible_collections/cisco/dnac/plugins/modules/templates_details_info.py b/ansible_collections/cisco/dnac/plugins/modules/templates_details_info.py index d8d2b0704..f2f45271c 100644 --- a/ansible_collections/cisco/dnac/plugins/modules/templates_details_info.py +++ b/ansible_collections/cisco/dnac/plugins/modules/templates_details_info.py @@ -89,8 +89,8 @@ options: - Limit query parameter. Limits number of results. type: int requirements: -- dnacentersdk >= 2.5.5 -- python >= 3.5 +- dnacentersdk >= 2.6.0 +- python >= 3.9 seealso: - name: Cisco DNA Center documentation for Configuration Templates GetTemplatesDetails description: Complete reference of the GetTemplatesDetails API. diff --git a/ansible_collections/cisco/dnac/plugins/modules/threat_detail.py b/ansible_collections/cisco/dnac/plugins/modules/threat_detail.py index 685b60b15..0bcfac62c 100644 --- a/ansible_collections/cisco/dnac/plugins/modules/threat_detail.py +++ b/ansible_collections/cisco/dnac/plugins/modules/threat_detail.py @@ -44,8 +44,8 @@ options: elements: str type: list requirements: -- dnacentersdk >= 2.5.5 -- python >= 3.5 +- dnacentersdk >= 2.6.0 +- python >= 3.9 notes: - SDK Method used are devices.Devices.threat_details, diff --git a/ansible_collections/cisco/dnac/plugins/modules/threat_detail_count.py b/ansible_collections/cisco/dnac/plugins/modules/threat_detail_count.py index fab706a16..7a21cd1ad 100644 --- a/ansible_collections/cisco/dnac/plugins/modules/threat_detail_count.py +++ b/ansible_collections/cisco/dnac/plugins/modules/threat_detail_count.py @@ -44,8 +44,8 @@ options: elements: str type: list requirements: -- dnacentersdk >= 2.5.5 -- python >= 3.5 +- dnacentersdk >= 2.6.0 +- python >= 3.9 notes: - SDK Method used are devices.Devices.threat_detail_count, diff --git a/ansible_collections/cisco/dnac/plugins/modules/threat_summary.py b/ansible_collections/cisco/dnac/plugins/modules/threat_summary.py index e3f3742bb..635b0c43c 100644 --- a/ansible_collections/cisco/dnac/plugins/modules/threat_summary.py +++ b/ansible_collections/cisco/dnac/plugins/modules/threat_summary.py @@ -35,8 +35,8 @@ options: elements: str type: list requirements: -- dnacentersdk >= 2.5.5 -- python >= 3.5 +- dnacentersdk >= 2.6.0 +- python >= 3.9 notes: - SDK Method used are devices.Devices.threat_summary, diff --git a/ansible_collections/cisco/dnac/plugins/modules/topology_layer_2_info.py b/ansible_collections/cisco/dnac/plugins/modules/topology_layer_2_info.py index 2d9324000..2ba3667e2 100644 --- a/ansible_collections/cisco/dnac/plugins/modules/topology_layer_2_info.py +++ b/ansible_collections/cisco/dnac/plugins/modules/topology_layer_2_info.py @@ -24,8 +24,8 @@ options: - VlanID path parameter. Vlan Name for e.g Vlan1, Vlan23 etc. type: str requirements: -- dnacentersdk >= 2.5.5 -- python >= 3.5 +- dnacentersdk >= 2.6.0 +- python >= 3.9 seealso: - name: Cisco DNA Center documentation for Topology GetTopologyDetails description: Complete reference of the GetTopologyDetails API. diff --git a/ansible_collections/cisco/dnac/plugins/modules/topology_layer_3_info.py b/ansible_collections/cisco/dnac/plugins/modules/topology_layer_3_info.py index fc09e3f56..008b5d1ac 100644 --- a/ansible_collections/cisco/dnac/plugins/modules/topology_layer_3_info.py +++ b/ansible_collections/cisco/dnac/plugins/modules/topology_layer_3_info.py @@ -24,8 +24,8 @@ options: - TopologyType path parameter. Type of topology(OSPF,ISIS,etc). type: str requirements: -- dnacentersdk >= 2.5.5 -- python >= 3.5 +- dnacentersdk >= 2.6.0 +- python >= 3.9 seealso: - name: Cisco DNA Center documentation for Topology GetL3TopologyDetails description: Complete reference of the GetL3TopologyDetails API. diff --git a/ansible_collections/cisco/dnac/plugins/modules/topology_network_health_info.py b/ansible_collections/cisco/dnac/plugins/modules/topology_network_health_info.py index 907a87c5f..b9c856316 100644 --- a/ansible_collections/cisco/dnac/plugins/modules/topology_network_health_info.py +++ b/ansible_collections/cisco/dnac/plugins/modules/topology_network_health_info.py @@ -26,8 +26,8 @@ options: - Timestamp query parameter. Epoch time(in milliseconds) when the Network health data is required. type: str requirements: -- dnacentersdk >= 2.5.5 -- python >= 3.5 +- dnacentersdk >= 2.6.0 +- python >= 3.9 seealso: - name: Cisco DNA Center documentation for Topology GetOverallNetworkHealth description: Complete reference of the GetOverallNetworkHealth API. diff --git a/ansible_collections/cisco/dnac/plugins/modules/topology_physical_info.py b/ansible_collections/cisco/dnac/plugins/modules/topology_physical_info.py index 89afc87f2..6a9573d57 100644 --- a/ansible_collections/cisco/dnac/plugins/modules/topology_physical_info.py +++ b/ansible_collections/cisco/dnac/plugins/modules/topology_physical_info.py @@ -24,8 +24,8 @@ options: - NodeType query parameter. type: str requirements: -- dnacentersdk >= 2.5.5 -- python >= 3.5 +- dnacentersdk >= 2.6.0 +- python >= 3.9 seealso: - name: Cisco DNA Center documentation for Topology GetPhysicalTopology description: Complete reference of the GetPhysicalTopology API. diff --git a/ansible_collections/cisco/dnac/plugins/modules/topology_site_info.py b/ansible_collections/cisco/dnac/plugins/modules/topology_site_info.py index 034c84c96..d63661b43 100644 --- a/ansible_collections/cisco/dnac/plugins/modules/topology_site_info.py +++ b/ansible_collections/cisco/dnac/plugins/modules/topology_site_info.py @@ -20,8 +20,8 @@ options: description: Additional headers. type: dict requirements: -- dnacentersdk >= 2.5.5 -- python >= 3.5 +- dnacentersdk >= 2.6.0 +- python >= 3.9 seealso: - name: Cisco DNA Center documentation for Topology GetSiteTopology description: Complete reference of the GetSiteTopology API. diff --git a/ansible_collections/cisco/dnac/plugins/modules/topology_vlan_details_info.py b/ansible_collections/cisco/dnac/plugins/modules/topology_vlan_details_info.py index c8585d26a..555b5b9d8 100644 --- a/ansible_collections/cisco/dnac/plugins/modules/topology_vlan_details_info.py +++ b/ansible_collections/cisco/dnac/plugins/modules/topology_vlan_details_info.py @@ -20,8 +20,8 @@ options: description: Additional headers. type: dict requirements: -- dnacentersdk >= 2.5.5 -- python >= 3.5 +- dnacentersdk >= 2.6.0 +- python >= 3.9 seealso: - name: Cisco DNA Center documentation for Topology GetVLANDetails description: Complete reference of the GetVLANDetails API. diff --git a/ansible_collections/cisco/dnac/plugins/modules/transit_peer_network.py b/ansible_collections/cisco/dnac/plugins/modules/transit_peer_network.py index 29c9889c1..38125e4d3 100644 --- a/ansible_collections/cisco/dnac/plugins/modules/transit_peer_network.py +++ b/ansible_collections/cisco/dnac/plugins/modules/transit_peer_network.py @@ -49,8 +49,8 @@ options: description: Transit Peer Network Type. type: str requirements: -- dnacentersdk >= 2.5.5 -- python >= 3.5 +- dnacentersdk >= 2.6.0 +- python >= 3.9 seealso: - name: Cisco DNA Center documentation for AddTransitPeerNetwork description: Complete reference of the AddTransitPeerNetwork API. diff --git a/ansible_collections/cisco/dnac/plugins/modules/transit_peer_network_info.py b/ansible_collections/cisco/dnac/plugins/modules/transit_peer_network_info.py index ef9ecac22..75ca07d7a 100644 --- a/ansible_collections/cisco/dnac/plugins/modules/transit_peer_network_info.py +++ b/ansible_collections/cisco/dnac/plugins/modules/transit_peer_network_info.py @@ -24,8 +24,8 @@ options: - TransitPeerNetworkName query parameter. Transit or Peer Network Name. type: str requirements: -- dnacentersdk >= 2.5.5 -- python >= 3.5 +- dnacentersdk >= 2.6.0 +- python >= 3.9 seealso: - name: Cisco DNA Center documentation for GetTransitPeerNetworkInfo description: Complete reference of the GetTransitPeerNetworkInfo API. diff --git a/ansible_collections/cisco/dnac/plugins/modules/user.py b/ansible_collections/cisco/dnac/plugins/modules/user.py index 21769bb83..4567de33d 100644 --- a/ansible_collections/cisco/dnac/plugins/modules/user.py +++ b/ansible_collections/cisco/dnac/plugins/modules/user.py @@ -40,8 +40,8 @@ options: description: Username. type: str requirements: -- dnacentersdk >= 2.5.5 -- python >= 3.5 +- dnacentersdk >= 2.6.0 +- python >= 3.9 seealso: - name: Cisco DNA Center documentation for User and Roles AddUserAPI description: Complete reference of the AddUserAPI API. diff --git a/ansible_collections/cisco/dnac/plugins/modules/user_enrichment_details_info.py b/ansible_collections/cisco/dnac/plugins/modules/user_enrichment_details_info.py index 246dd7a83..bcffca746 100644 --- a/ansible_collections/cisco/dnac/plugins/modules/user_enrichment_details_info.py +++ b/ansible_collections/cisco/dnac/plugins/modules/user_enrichment_details_info.py @@ -22,8 +22,8 @@ options: description: Additional headers. type: dict requirements: -- dnacentersdk >= 2.5.5 -- python >= 3.5 +- dnacentersdk >= 2.6.0 +- python >= 3.9 seealso: - name: Cisco DNA Center documentation for Users GetUserEnrichmentDetails description: Complete reference of the GetUserEnrichmentDetails API. diff --git a/ansible_collections/cisco/dnac/plugins/modules/user_info.py b/ansible_collections/cisco/dnac/plugins/modules/user_info.py index f00e1d66e..d4c20af69 100644 --- a/ansible_collections/cisco/dnac/plugins/modules/user_info.py +++ b/ansible_collections/cisco/dnac/plugins/modules/user_info.py @@ -24,8 +24,8 @@ options: - InvokeSource query parameter. The source that invokes this API. type: str requirements: -- dnacentersdk >= 2.5.5 -- python >= 3.5 +- dnacentersdk >= 2.6.0 +- python >= 3.9 seealso: - name: Cisco DNA Center documentation for User and Roles GetUsersAPI description: Complete reference of the GetUsersAPI API. diff --git a/ansible_collections/cisco/dnac/plugins/modules/users_external_servers_info.py b/ansible_collections/cisco/dnac/plugins/modules/users_external_servers_info.py index 536f958c8..0373d2c85 100644 --- a/ansible_collections/cisco/dnac/plugins/modules/users_external_servers_info.py +++ b/ansible_collections/cisco/dnac/plugins/modules/users_external_servers_info.py @@ -24,8 +24,8 @@ options: - InvokeSource query parameter. The source that invokes this API. type: str requirements: -- dnacentersdk >= 2.5.5 -- python >= 3.5 +- dnacentersdk >= 2.6.0 +- python >= 3.9 seealso: - name: Cisco DNA Center documentation for User and Roles GetExternalAuthenticationServersAPI description: Complete reference of the GetExternalAuthenticationServersAPI API. diff --git a/ansible_collections/cisco/dnac/plugins/modules/wireless_accespoint_configuration.py b/ansible_collections/cisco/dnac/plugins/modules/wireless_accespoint_configuration.py index 94dee6c5d..6a1cf2946 100644 --- a/ansible_collections/cisco/dnac/plugins/modules/wireless_accespoint_configuration.py +++ b/ansible_collections/cisco/dnac/plugins/modules/wireless_accespoint_configuration.py @@ -238,8 +238,8 @@ options: type: str type: dict requirements: -- dnacentersdk >= 2.5.5 -- python >= 3.5 +- dnacentersdk >= 2.6.0 +- python >= 3.9 seealso: - name: Cisco DNA Center documentation for Wireless ConfigureAccessPoints description: Complete reference of the ConfigureAccessPoints API. diff --git a/ansible_collections/cisco/dnac/plugins/modules/wireless_accesspoint_configuration_summary_info.py b/ansible_collections/cisco/dnac/plugins/modules/wireless_accesspoint_configuration_summary_info.py index 3c2130868..ba43fe052 100644 --- a/ansible_collections/cisco/dnac/plugins/modules/wireless_accesspoint_configuration_summary_info.py +++ b/ansible_collections/cisco/dnac/plugins/modules/wireless_accesspoint_configuration_summary_info.py @@ -24,8 +24,8 @@ options: - Key query parameter. The ethernet MAC address of Access point. type: str requirements: -- dnacentersdk >= 2.5.5 -- python >= 3.5 +- dnacentersdk >= 2.6.0 +- python >= 3.9 seealso: - name: Cisco DNA Center documentation for Wireless GetAccessPointConfiguration description: Complete reference of the GetAccessPointConfiguration API. diff --git a/ansible_collections/cisco/dnac/plugins/modules/wireless_dynamic_interface.py b/ansible_collections/cisco/dnac/plugins/modules/wireless_dynamic_interface.py index ea48c7970..ed933a268 100644 --- a/ansible_collections/cisco/dnac/plugins/modules/wireless_dynamic_interface.py +++ b/ansible_collections/cisco/dnac/plugins/modules/wireless_dynamic_interface.py @@ -27,8 +27,8 @@ options: description: Vlan Id. type: int requirements: -- dnacentersdk >= 2.5.5 -- python >= 3.5 +- dnacentersdk >= 2.6.0 +- python >= 3.9 seealso: - name: Cisco DNA Center documentation for Wireless CreateUpdateDynamicInterface description: Complete reference of the CreateUpdateDynamicInterface API. diff --git a/ansible_collections/cisco/dnac/plugins/modules/wireless_dynamic_interface_info.py b/ansible_collections/cisco/dnac/plugins/modules/wireless_dynamic_interface_info.py index d1736fb20..152b1c339 100644 --- a/ansible_collections/cisco/dnac/plugins/modules/wireless_dynamic_interface_info.py +++ b/ansible_collections/cisco/dnac/plugins/modules/wireless_dynamic_interface_info.py @@ -26,8 +26,8 @@ options: will be retrieved. type: str requirements: -- dnacentersdk >= 2.5.5 -- python >= 3.5 +- dnacentersdk >= 2.6.0 +- python >= 3.9 seealso: - name: Cisco DNA Center documentation for Wireless GetDynamicInterface description: Complete reference of the GetDynamicInterface API. diff --git a/ansible_collections/cisco/dnac/plugins/modules/wireless_enterprise_ssid.py b/ansible_collections/cisco/dnac/plugins/modules/wireless_enterprise_ssid.py index eb8790381..f288aaada 100644 --- a/ansible_collections/cisco/dnac/plugins/modules/wireless_enterprise_ssid.py +++ b/ansible_collections/cisco/dnac/plugins/modules/wireless_enterprise_ssid.py @@ -81,8 +81,8 @@ options: description: Traffic Type Enum (voicedata or data ). type: str requirements: -- dnacentersdk >= 2.5.5 -- python >= 3.5 +- dnacentersdk >= 2.6.0 +- python >= 3.9 seealso: - name: Cisco DNA Center documentation for Wireless CreateEnterpriseSSID description: Complete reference of the CreateEnterpriseSSID API. diff --git a/ansible_collections/cisco/dnac/plugins/modules/wireless_enterprise_ssid_info.py b/ansible_collections/cisco/dnac/plugins/modules/wireless_enterprise_ssid_info.py index 8abacd832..b277d03bd 100644 --- a/ansible_collections/cisco/dnac/plugins/modules/wireless_enterprise_ssid_info.py +++ b/ansible_collections/cisco/dnac/plugins/modules/wireless_enterprise_ssid_info.py @@ -26,8 +26,8 @@ options: enterprise SSIDs will be retrieved. type: str requirements: -- dnacentersdk >= 2.5.5 -- python >= 3.5 +- dnacentersdk >= 2.6.0 +- python >= 3.9 seealso: - name: Cisco DNA Center documentation for Wireless GetEnterpriseSSID description: Complete reference of the GetEnterpriseSSID API. diff --git a/ansible_collections/cisco/dnac/plugins/modules/wireless_profile.py b/ansible_collections/cisco/dnac/plugins/modules/wireless_profile.py index 4c696f0d6..7c837cca7 100644 --- a/ansible_collections/cisco/dnac/plugins/modules/wireless_profile.py +++ b/ansible_collections/cisco/dnac/plugins/modules/wireless_profile.py @@ -68,8 +68,8 @@ options: description: WirelessProfileName path parameter. Wireless Profile Name. type: str requirements: -- dnacentersdk >= 2.5.5 -- python >= 3.5 +- dnacentersdk >= 2.6.0 +- python >= 3.9 seealso: - name: Cisco DNA Center documentation for Wireless CreateWirelessProfile description: Complete reference of the CreateWirelessProfile API. diff --git a/ansible_collections/cisco/dnac/plugins/modules/wireless_profile_info.py b/ansible_collections/cisco/dnac/plugins/modules/wireless_profile_info.py index f88760c14..fb175dedf 100644 --- a/ansible_collections/cisco/dnac/plugins/modules/wireless_profile_info.py +++ b/ansible_collections/cisco/dnac/plugins/modules/wireless_profile_info.py @@ -24,8 +24,8 @@ options: - ProfileName query parameter. Wireless Network Profile Name. type: str requirements: -- dnacentersdk >= 2.5.5 -- python >= 3.5 +- dnacentersdk >= 2.6.0 +- python >= 3.9 seealso: - name: Cisco DNA Center documentation for Wireless GetWirelessProfile description: Complete reference of the GetWirelessProfile API. diff --git a/ansible_collections/cisco/dnac/plugins/modules/wireless_provision_access_point.py b/ansible_collections/cisco/dnac/plugins/modules/wireless_provision_access_point.py index f8db0233c..d4651745f 100644 --- a/ansible_collections/cisco/dnac/plugins/modules/wireless_provision_access_point.py +++ b/ansible_collections/cisco/dnac/plugins/modules/wireless_provision_access_point.py @@ -47,8 +47,8 @@ options: type: str type: list requirements: -- dnacentersdk >= 2.5.5 -- python >= 3.5 +- dnacentersdk >= 2.6.0 +- python >= 3.9 seealso: - name: Cisco DNA Center documentation for Wireless APProvision description: Complete reference of the APProvision API. diff --git a/ansible_collections/cisco/dnac/plugins/modules/wireless_provision_device_create.py b/ansible_collections/cisco/dnac/plugins/modules/wireless_provision_device_create.py index d626052a7..84622d990 100644 --- a/ansible_collections/cisco/dnac/plugins/modules/wireless_provision_device_create.py +++ b/ansible_collections/cisco/dnac/plugins/modules/wireless_provision_device_create.py @@ -55,8 +55,8 @@ options: type: str type: list requirements: -- dnacentersdk >= 2.5.5 -- python >= 3.5 +- dnacentersdk >= 2.6.0 +- python >= 3.9 seealso: - name: Cisco DNA Center documentation for Wireless Provision description: Complete reference of the Provision API. diff --git a/ansible_collections/cisco/dnac/plugins/modules/wireless_provision_device_update.py b/ansible_collections/cisco/dnac/plugins/modules/wireless_provision_device_update.py index 07e983f30..c76487739 100644 --- a/ansible_collections/cisco/dnac/plugins/modules/wireless_provision_device_update.py +++ b/ansible_collections/cisco/dnac/plugins/modules/wireless_provision_device_update.py @@ -55,8 +55,8 @@ options: type: list type: list requirements: -- dnacentersdk >= 2.5.5 -- python >= 3.5 +- dnacentersdk >= 2.6.0 +- python >= 3.9 seealso: - name: Cisco DNA Center documentation for Wireless ProvisionUpdate description: Complete reference of the ProvisionUpdate API. diff --git a/ansible_collections/cisco/dnac/plugins/modules/wireless_provision_ssid_create_provision.py b/ansible_collections/cisco/dnac/plugins/modules/wireless_provision_ssid_create_provision.py index 5a7322ea9..a0627c125 100644 --- a/ansible_collections/cisco/dnac/plugins/modules/wireless_provision_ssid_create_provision.py +++ b/ansible_collections/cisco/dnac/plugins/modules/wireless_provision_ssid_create_provision.py @@ -78,8 +78,8 @@ options: description: SSID Type. type: str requirements: -- dnacentersdk >= 2.5.5 -- python >= 3.5 +- dnacentersdk >= 2.6.0 +- python >= 3.9 seealso: - name: Cisco DNA Center documentation for Wireless CreateAndProvisionSSID description: Complete reference of the CreateAndProvisionSSID API. diff --git a/ansible_collections/cisco/dnac/plugins/modules/wireless_provision_ssid_delete_reprovision.py b/ansible_collections/cisco/dnac/plugins/modules/wireless_provision_ssid_delete_reprovision.py index fed3cb2ca..8d713ce13 100644 --- a/ansible_collections/cisco/dnac/plugins/modules/wireless_provision_ssid_delete_reprovision.py +++ b/ansible_collections/cisco/dnac/plugins/modules/wireless_provision_ssid_delete_reprovision.py @@ -26,8 +26,8 @@ options: description: SsidName path parameter. type: str requirements: -- dnacentersdk >= 2.5.5 -- python >= 3.5 +- dnacentersdk >= 2.6.0 +- python >= 3.9 seealso: - name: Cisco DNA Center documentation for Wireless DeleteSSIDAndProvisionItToDevices description: Complete reference of the DeleteSSIDAndProvisionItToDevices API. diff --git a/ansible_collections/cisco/dnac/plugins/modules/wireless_psk_override.py b/ansible_collections/cisco/dnac/plugins/modules/wireless_psk_override.py index 0afada7c5..163ea45b5 100644 --- a/ansible_collections/cisco/dnac/plugins/modules/wireless_psk_override.py +++ b/ansible_collections/cisco/dnac/plugins/modules/wireless_psk_override.py @@ -34,8 +34,8 @@ options: type: str type: list requirements: -- dnacentersdk >= 2.5.5 -- python >= 3.5 +- dnacentersdk >= 2.6.0 +- python >= 3.9 seealso: - name: Cisco DNA Center documentation for Wireless PSKOverride description: Complete reference of the PSKOverride API. diff --git a/ansible_collections/cisco/dnac/plugins/modules/wireless_rf_profile.py b/ansible_collections/cisco/dnac/plugins/modules/wireless_rf_profile.py index 4aa97f651..86c7ad953 100644 --- a/ansible_collections/cisco/dnac/plugins/modules/wireless_rf_profile.py +++ b/ansible_collections/cisco/dnac/plugins/modules/wireless_rf_profile.py @@ -130,8 +130,8 @@ options: *non-custom RF profile cannot be deleted. type: str requirements: -- dnacentersdk >= 2.5.5 -- python >= 3.5 +- dnacentersdk >= 2.6.0 +- python >= 3.9 seealso: - name: Cisco DNA Center documentation for Wireless CreateOrUpdateRFProfile description: Complete reference of the CreateOrUpdateRFProfile API. diff --git a/ansible_collections/cisco/dnac/plugins/modules/wireless_rf_profile_info.py b/ansible_collections/cisco/dnac/plugins/modules/wireless_rf_profile_info.py index 722ddfc40..281f87b6d 100644 --- a/ansible_collections/cisco/dnac/plugins/modules/wireless_rf_profile_info.py +++ b/ansible_collections/cisco/dnac/plugins/modules/wireless_rf_profile_info.py @@ -24,8 +24,8 @@ options: - Rf-profile-name query parameter. RF Profile Name. type: str requirements: -- dnacentersdk >= 2.5.5 -- python >= 3.5 +- dnacentersdk >= 2.6.0 +- python >= 3.9 seealso: - name: Cisco DNA Center documentation for Wireless RetrieveRFProfiles description: Complete reference of the RetrieveRFProfiles API. diff --git a/ansible_collections/cisco/dnac/plugins/modules/wireless_sensor_test_results_info.py b/ansible_collections/cisco/dnac/plugins/modules/wireless_sensor_test_results_info.py index 41d727dd5..f316a4602 100644 --- a/ansible_collections/cisco/dnac/plugins/modules/wireless_sensor_test_results_info.py +++ b/ansible_collections/cisco/dnac/plugins/modules/wireless_sensor_test_results_info.py @@ -36,8 +36,8 @@ options: - TestFailureBy query parameter. Obtain failure statistics group by "area", "building", or "floor". type: str requirements: -- dnacentersdk >= 2.5.5 -- python >= 3.5 +- dnacentersdk >= 2.6.0 +- python >= 3.9 seealso: - name: Cisco DNA Center documentation for Wireless SensorTestResults description: Complete reference of the SensorTestResults API. diff --git a/ansible_collections/cisco/intersight/CHANGELOG.md b/ansible_collections/cisco/intersight/CHANGELOG.md index 20035122b..1ed1a5e3e 100644 --- a/ansible_collections/cisco/intersight/CHANGELOG.md +++ b/ansible_collections/cisco/intersight/CHANGELOG.md @@ -1,5 +1,8 @@ # cisco.intersight Ansible Collection Changelog +## Version 2.0.8 +- Fix issue #111 to allow User Policy updates + ## Version 2.0.7 - Fix issue #101 to support IMM Server Policies. - Update deploy_server_profiles playbook to support Unassign diff --git a/ansible_collections/cisco/intersight/FILES.json b/ansible_collections/cisco/intersight/FILES.json index 32d2289e2..95315ee60 100644 --- a/ansible_collections/cisco/intersight/FILES.json +++ b/ansible_collections/cisco/intersight/FILES.json @@ -46,7 +46,7 @@ "name": "CHANGELOG.md", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "e12da2fc549bdadafdd809c920214a67f6fb569d016359e3d81a514d575ded3f", + "chksum_sha256": "184c0ed03fe6bbd200481b356aab0a3e8c92fbb08bcf3ca6057c53fac6e65e1d", "format": 1 }, { @@ -116,7 +116,7 @@ "name": "plugins/modules/intersight_server_profile.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "957fd1ca38a9a759a24e6b8f0a245be48f711f4ffce14b816799ea06cf2924c8", + "chksum_sha256": "4de9635cc96bb2469e78e7b0be17fa85a4692ee3821f3b7d490d9d2376fef6e3", "format": 1 }, { @@ -151,7 +151,7 @@ "name": "plugins/modules/intersight_local_user_policy.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "7113b95de82882c33ca13674cc7210db4e9d11ffb753a53776dd3f8ced8ab4cd", + "chksum_sha256": "37256848d5a123bcae5204c7fcdde7aba8a4eb0f3ca117473cce0a6a418e2373", "format": 1 }, { diff --git a/ansible_collections/cisco/intersight/MANIFEST.json b/ansible_collections/cisco/intersight/MANIFEST.json index 6b211f2c6..990405175 100644 --- a/ansible_collections/cisco/intersight/MANIFEST.json +++ b/ansible_collections/cisco/intersight/MANIFEST.json @@ -2,7 +2,7 @@ "collection_info": { "namespace": "cisco", "name": "intersight", - "version": "2.0.7", + "version": "2.0.8", "authors": [ "David Soper (@dsoper2)" ], @@ -27,7 +27,7 @@ "name": "FILES.json", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "0a61cf97c55cb7fea120fa4d211ada5f4c5929bd8b617b9213d7b19cc3302c68", + "chksum_sha256": "7958d8bc5047610831777f3a56171c17f505aff4bd24acfe861039c60da2c771", "format": 1 }, "format": 1 diff --git a/ansible_collections/cisco/intersight/plugins/modules/intersight_local_user_policy.py b/ansible_collections/cisco/intersight/plugins/modules/intersight_local_user_policy.py index 9bb58065d..1124da980 100644 --- a/ansible_collections/cisco/intersight/plugins/modules/intersight_local_user_policy.py +++ b/ansible_collections/cisco/intersight/plugins/modules/intersight_local_user_policy.py @@ -197,14 +197,28 @@ def main(): ) intersight = IntersightModule(module) + organization_moid = None + # get Organization Moid + intersight.get_resource( + resource_path='/organization/Organizations', + query_params={ + '$filter': "Name eq '" + intersight.module.params['organization'] + "'", + '$select': 'Moid', + }, + ) + if intersight.result['api_response'].get('Moid'): + # resource exists and moid was returned + organization_moid = intersight.result['api_response']['Moid'] intersight.result['api_response'] = {} intersight.result['trace_id'] = '' # get the current state of the resource + filter_str = "Name eq '" + intersight.module.params['name'] + "'" + filter_str += "and Organization.Moid eq '" + organization_moid + "'" intersight.get_resource( resource_path='/iam/EndPointUserPolicies', query_params={ - '$filter': "Name eq '" + intersight.module.params['name'] + "'", + '$filter': filter_str, '$expand': 'EndPointUserRoles($expand=EndPointRole,EndPointUser),Organization', }, ) @@ -269,34 +283,18 @@ def main(): 'EnablePasswordExpiry': intersight.module.params['enable_password_expiry'], 'PasswordHistory': intersight.module.params['password_history'], }, + 'Organization': { + 'Moid': organization_moid + }, } - organization_moid = None - if not user_policy_moid or module.params['purge']: - # get Organization Moid which is needed when resources are created - saved_response = intersight.result['api_response'] - intersight.get_resource( - resource_path='/organization/Organizations', - query_params={ - '$filter': "Name eq '" + intersight.module.params['organization'] + "'", - '$select': 'Moid', - }, - ) - if intersight.result['api_response'].get('Moid'): - # resource exists and moid was returned - organization_moid = intersight.result['api_response']['Moid'] - intersight.result['api_response'] = saved_response - if not user_policy_moid: - # Initial create: Organization must be set, but can't be changed after initial POST - intersight.api_body['Organization'] = { - 'Moid': organization_moid, - } - elif module.params['purge']: - # update existing resource and purge any existing users - for end_point_user_role in intersight.result['api_response']['EndPointUserRoles']: - intersight.delete_resource( - moid=end_point_user_role['Moid'], - resource_path='/iam/EndPointUserRoles', - ) + + if module.params['purge']: + # update existing resource and purge any existing users + for end_point_user_role in intersight.result['api_response']['EndPointUserRoles']: + intersight.delete_resource( + moid=end_point_user_role['Moid'], + resource_path='/iam/EndPointUserRoles', + ) # configure the top-level policy resource intersight.result['api_response'] = {} intersight.configure_resource( diff --git a/ansible_collections/cisco/intersight/plugins/modules/intersight_server_profile.py b/ansible_collections/cisco/intersight/plugins/modules/intersight_server_profile.py index 49cdb61b6..8746bdc31 100644 --- a/ansible_collections/cisco/intersight/plugins/modules/intersight_server_profile.py +++ b/ansible_collections/cisco/intersight/plugins/modules/intersight_server_profile.py @@ -330,15 +330,15 @@ def main(): if moid and intersight.module.params['boot_order_policy']: post_profile_to_policy(intersight, moid, resource_path='/boot/PrecisionPolicies', policy_name=intersight.module.params['boot_order_policy']) if moid and intersight.module.params['certificate_policy']: - post_profile_to_policy(intersight, moid, resource_path='/security/CertificatePolicies', policy_name=intersight.module.params['certificate_policy']) + post_profile_to_policy(intersight, moid, resource_path='/certificatemanagement/Policies', policy_name=intersight.module.params['certificate_policy']) if moid and intersight.module.params['drive_security_policy']: - post_profile_to_policy(intersight, moid, resource_path='/security/DriveSecurityPolicies', policy_name=intersight.module.params['drive_security_policy']) + post_profile_to_policy(intersight, moid, resource_path='/storage/DriveSecurityPolicies', policy_name=intersight.module.params['drive_security_policy']) if moid and intersight.module.params['firmware_policy']: post_profile_to_policy(intersight, moid, resource_path='/firmware/Policies', policy_name=intersight.module.params['firmware_policy']) if moid and intersight.module.params['imc_access_policy']: post_profile_to_policy(intersight, moid, resource_path='/access/Policies', policy_name=intersight.module.params['imc_access_policy']) if moid and intersight.module.params['ipmi_over_lan_policy']: - post_profile_to_policy(intersight, moid, resource_path='/ipmi/Policies', policy_name=intersight.module.params['ipmi_over_lan_policy']) + post_profile_to_policy(intersight, moid, resource_path='/ipmioverlan/Policies', policy_name=intersight.module.params['ipmi_over_lan_policy']) if moid and intersight.module.params['lan_connectivity_policy']: post_profile_to_policy(intersight, moid, resource_path='/vnic/LanConnectivityPolicies', policy_name=intersight.module.params['lan_connectivity_policy']) if moid and intersight.module.params['local_user_policy']: @@ -348,7 +348,7 @@ def main(): if moid and intersight.module.params['san_connectivity_policy']: post_profile_to_policy(intersight, moid, resource_path='/vnic/SanConnectivityPolicies', policy_name=intersight.module.params['san_connectivity_policy']) if moid and intersight.module.params['serial_over_lan_policy']: - post_profile_to_policy(intersight, moid, resource_path='/serial/Policies', policy_name=intersight.module.params['serial_over_lan_policy']) + post_profile_to_policy(intersight, moid, resource_path='/sol/Policies', policy_name=intersight.module.params['serial_over_lan_policy']) if moid and intersight.module.params['snmp_policy']: post_profile_to_policy(intersight, moid, resource_path='/snmp/Policies', policy_name=intersight.module.params['snmp_policy']) if moid and intersight.module.params['storage_policy']: diff --git a/ansible_collections/cisco/ise/.DS_Store b/ansible_collections/cisco/ise/.DS_Store deleted file mode 100644 index f79cfc1f5..000000000 Binary files a/ansible_collections/cisco/ise/.DS_Store and /dev/null differ diff --git a/ansible_collections/cisco/ise/.vscode/launch.json b/ansible_collections/cisco/ise/.vscode/launch.json deleted file mode 100644 index 306f58eb3..000000000 --- a/ansible_collections/cisco/ise/.vscode/launch.json +++ /dev/null @@ -1,16 +0,0 @@ -{ - // Use IntelliSense to learn about possible attributes. - // Hover to view descriptions of existing attributes. - // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 - "version": "0.2.0", - "configurations": [ - { - "name": "Python: Current File", - "type": "python", - "request": "launch", - "program": "${file}", - "console": "integratedTerminal", - "justMyCode": true - } - ] -} \ No newline at end of file diff --git a/ansible_collections/cisco/ise/.vscode/settings.json b/ansible_collections/cisco/ise/.vscode/settings.json deleted file mode 100644 index 4f6146612..000000000 --- a/ansible_collections/cisco/ise/.vscode/settings.json +++ /dev/null @@ -1,24 +0,0 @@ -{ - "esbonio.sphinx.confDir": "", - "ansible.python.interpreterPath": "/usr/local/bin/python3.10", - "workbench.colorCustomizations": { - "activityBar.activeBackground": "#65c89b", - "activityBar.background": "#65c89b", - "activityBar.foreground": "#15202b", - "activityBar.inactiveForeground": "#15202b99", - "activityBarBadge.background": "#945bc4", - "activityBarBadge.foreground": "#e7e7e7", - "commandCenter.border": "#15202b99", - "sash.hoverBorder": "#65c89b", - "statusBar.background": "#42b883", - "statusBar.foreground": "#15202b", - "statusBarItem.hoverBackground": "#359268", - "statusBarItem.remoteBackground": "#42b883", - "statusBarItem.remoteForeground": "#15202b", - "titleBar.activeBackground": "#42b883", - "titleBar.activeForeground": "#15202b", - "titleBar.inactiveBackground": "#42b88399", - "titleBar.inactiveForeground": "#15202b99" - }, - "peacock.remoteColor": "#42b883" -} \ No newline at end of file diff --git a/ansible_collections/cisco/ise/FILES.json b/ansible_collections/cisco/ise/FILES.json index 4c183e093..68d896522 100644 --- a/ansible_collections/cisco/ise/FILES.json +++ b/ansible_collections/cisco/ise/FILES.json @@ -7,13 +7,6 @@ "chksum_sha256": null, "format": 1 }, - { - "name": ".DS_Store", - "ftype": "file", - "chksum_type": "sha256", - "chksum_sha256": "437cf9da8611bcc8837aef2444e9e00fc44f8f071f750224be185a74168f2e5f", - "format": 1 - }, { "name": "LICENSE", "ftype": "file", @@ -35,13 +28,6 @@ "chksum_sha256": null, "format": 1 }, - { - "name": "plugins/.DS_Store", - "ftype": "file", - "chksum_type": "sha256", - "chksum_sha256": "389b6b15b162e5db97c1c6d4ddc0f1161590c016eb06e49734d10373aabc3c56", - "format": 1 - }, { "name": "plugins/doc_fragments", "ftype": "dir", @@ -6269,7 +6255,7 @@ "name": "changelogs/changelog.yaml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "1193073224fb370f3d397b81858a7bda59568a510fa6c8e925f2b29479326d20", + "chksum_sha256": "46af54b2672389b7a9e635b04c480f0697afee607e2e84199b8c5777e1018017", "format": 1 }, { @@ -6279,6 +6265,13 @@ "chksum_sha256": "e0770ec263df253ef1ee1b8f727e1e03c18f8c1198efbd85d7ed1c63006b3b4a", "format": 1 }, + { + "name": "Pipfile", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "17a27a28cca40c85447113986ef3f6491f1e5cae1a17d460adfda229f5296969", + "format": 1 + }, { "name": ".gitignore", "ftype": "file", @@ -6341,27 +6334,6 @@ "chksum_type": "sha256", "chksum_sha256": "1f103c6a9dd07cd13a9a6f17ace6b813f47747eb9cb7e00488cb2073caaf91bb", "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": "ff058b88424cd36c92374f3465470d0c24191746d224d3729d623881464c651e", - "format": 1 - }, - { - "name": ".vscode/launch.json", - "ftype": "file", - "chksum_type": "sha256", - "chksum_sha256": "6a62b2b5cbd6e0edb4942e59fc4451e2e59f12472965990a24029ae24264fcb2", - "format": 1 } ], "format": 1 diff --git a/ansible_collections/cisco/ise/MANIFEST.json b/ansible_collections/cisco/ise/MANIFEST.json index 81f5e1e9f..cd7253ccb 100644 --- a/ansible_collections/cisco/ise/MANIFEST.json +++ b/ansible_collections/cisco/ise/MANIFEST.json @@ -2,7 +2,7 @@ "collection_info": { "namespace": "cisco", "name": "ise", - "version": "2.8.0", + "version": "2.8.1", "authors": [ "Rafael Campos ", "William Astorga ", @@ -21,7 +21,7 @@ "license": [], "license_file": "LICENSE", "dependencies": { - "ansible.utils": ">=2.0.0,<4.0" + "ansible.utils": ">=2.0.0,<5.0" }, "repository": "https://github.com/CiscoISE/ansible-ise", "documentation": "https://ciscoise.github.io/ansible-ise/", @@ -32,7 +32,7 @@ "name": "FILES.json", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "43d93ef4489b0ae7fbc8e57931e7dece5b2d87c9e3cdbae66359cce957ce2875", + "chksum_sha256": "c0a3e92ae466e59573dc00981d4201e0f64a87340c6ddbbcbdd2a58ed18f8a0a", "format": 1 }, "format": 1 diff --git a/ansible_collections/cisco/ise/Pipfile b/ansible_collections/cisco/ise/Pipfile new file mode 100644 index 000000000..2bc8501b5 --- /dev/null +++ b/ansible_collections/cisco/ise/Pipfile @@ -0,0 +1,13 @@ +[[source]] +url = "https://pypi.org/simple" +verify_ssl = true +name = "pypi" + +[packages] +ciscoisesdk = ">=2.1.1" +requests = ">=2.25.1" + +[dev-packages] + +[requires] +python_version = "3.9" diff --git a/ansible_collections/cisco/ise/changelogs/changelog.yaml b/ansible_collections/cisco/ise/changelogs/changelog.yaml index 929f94bb5..6ecbe5f31 100644 --- a/ansible_collections/cisco/ise/changelogs/changelog.yaml +++ b/ansible_collections/cisco/ise/changelogs/changelog.yaml @@ -976,4 +976,10 @@ releases: changes: release_summary: Changes the minimum supported version of Ansible to v2.14.0 minor_changes: - - Changes the minimum supported version from Ansible v2.9.10 to v2.14.0 \ No newline at end of file + - Changes the minimum supported version from Ansible v2.9.10 to v2.14.0 + 2.8.1: + release_date: "2024-04-02" + changes: + release_summary: Changes the requirements of ansible.utils to allow > 4.0.0 versions. + bugfixes: + - ansible.utils changes to `">=2.0.0,<5.0"` in galaxy.yml dependencies. \ No newline at end of file diff --git a/ansible_collections/cisco/ise/plugins/.DS_Store b/ansible_collections/cisco/ise/plugins/.DS_Store deleted file mode 100644 index 874d3d2c6..000000000 Binary files a/ansible_collections/cisco/ise/plugins/.DS_Store and /dev/null differ diff --git a/ansible_collections/cisco/meraki/.vscode/settings.json b/ansible_collections/cisco/meraki/.vscode/settings.json deleted file mode 100644 index a7d0fc7b7..000000000 --- a/ansible_collections/cisco/meraki/.vscode/settings.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "esbonio.sphinx.confDir": "" -} \ No newline at end of file diff --git a/ansible_collections/cisco/meraki/FILES.json b/ansible_collections/cisco/meraki/FILES.json index 8de741f1a..b254fc063 100644 --- a/ansible_collections/cisco/meraki/FILES.json +++ b/ansible_collections/cisco/meraki/FILES.json @@ -109,7 +109,7 @@ "name": "plugins/action/devices_live_tools_ping_device.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "c1f55d548e09211d2af66832ca498eb5ec21c59c4828aa08ec9e62acd10204a7", + "chksum_sha256": "0305a1dbac1fd49c393527d3520ebc896f400f0375c05090f86c064426b92535", "format": 1 }, { @@ -123,14 +123,14 @@ "name": "plugins/action/networks_clients_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "91e2ab89a2bf528e5b1e23fe507761bcedda663fa52c0521aed035d48bfd07a8", + "chksum_sha256": "843d03abf712b294d979f07b2194405d60846d0b0ef40a2f47be0731a5b2d022", "format": 1 }, { "name": "plugins/action/devices_camera_wireless_profiles.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "4be5ea964ca1145f37c501744ac2cfa367e1181e91182f1adf3f376467a12356", + "chksum_sha256": "777067a93b237d6eff35c1cf221b57caccbacebbdba0c3b66950e9040991c950", "format": 1 }, { @@ -144,7 +144,7 @@ "name": "plugins/action/networks_cellular_gateway_dhcp.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "dc6313fe7ff6e7650807fe49d1ed3f48912f9156a4f85d12827f9735e0a1a28c", + "chksum_sha256": "9daaf09d4cf66158843fced90e83b6b5770e3e69e11b7379cff004e2f367593f", "format": 1 }, { @@ -165,7 +165,7 @@ "name": "plugins/action/devices_switch_ports.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "48fabca42a2d562cbab45f416fda7141eb993c8f7ccb30a656697a05b2120e3a", + "chksum_sha256": "dae2abc4c84fc075a87f97e1941c73d218d68428471980eb6319247281eaf839", "format": 1 }, { @@ -186,7 +186,7 @@ "name": "plugins/action/organizations_adaptive_policy_policies.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "5fc0c7c7b323aa1f3a9aa72e9a07e1e866421bc1c496c390d9d129375b0b58d2", + "chksum_sha256": "fcbd4d25d8db4c6b4f4e2cea0de85df6b99572a23ca581e100fcc648e95951d2", "format": 1 }, { @@ -242,14 +242,14 @@ "name": "plugins/action/networks_wireless_ssids_eap_override.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "75be7d33fe28f5279a2fc700f94416a21bbb1629aa187570f65f178dacb8b73d", + "chksum_sha256": "bb4f2d3f2cdd0696677c2631617428b45ca192254cb1160d3ce9470fbf43ede0", "format": 1 }, { "name": "plugins/action/networks_wireless_ssids_device_type_group_policies.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "3a503d4061d1f8765e6277d1edbc1dc943d54e12da66318bcb3b5eef72566711", + "chksum_sha256": "32fbe5fde3de7c9c3244f1df792bc416f9e75f8954ea64859f8ac9892c5711cc", "format": 1 }, { @@ -263,7 +263,7 @@ "name": "plugins/action/devices_cellular_sims.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "345e4368244cb62e1ebf31dc4e2176d9a90d0ef27e4641eaec2e8ea747945b1c", + "chksum_sha256": "f9d27903b41dc552b75f048134a1dab27805b9a59498c94c4191715811c8c2fc", "format": 1 }, { @@ -287,6 +287,13 @@ "chksum_sha256": "766731e76b0bd223a12afd277e9d5798cdf64bc3bc09c1b79322a54f7f140196", "format": 1 }, + { + "name": "plugins/action/networks_appliance_traffic_shaping_vpn_exclusions.py", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "5a9a4db2b17ad98b95ebbbe026819160e16608bd0b919a976371b9ae76ff205e", + "format": 1 + }, { "name": "plugins/action/organizations_summary_top_switches_by_energy_usage_info.py", "ftype": "file", @@ -298,14 +305,14 @@ "name": "plugins/action/networks_appliance_vlans.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "c7384adc08b6b6dd9f90feff6e01fbd6b7525f21c648cbd8caac891c649e6854", + "chksum_sha256": "c761dfdb7567afd656b5788e4370d50eb72b6a9e94932379a1042f357ca249d5", "format": 1 }, { "name": "plugins/action/networks_netflow.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "327806d70a79c91d0151f537f560862b4133e2cbd1163a6ca762c6425f4520c9", + "chksum_sha256": "5e45703f236953211adcf1a0567d2b304ad4ca12415a8c4564997dd7b42f280a", "format": 1 }, { @@ -350,6 +357,13 @@ "chksum_sha256": "443d095120d73f12de8f189dfd10936fb8b5bac9f208b44e9decdc634f78d8a4", "format": 1 }, + { + "name": "plugins/action/devices_live_tools_throughput_test.py", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "71d02ad300aec8b1bd7313503a1fd0d7f1040507c7608c9eab028cc630ab9e8b", + "format": 1 + }, { "name": "plugins/action/organizations_clients_bandwidth_usage_history_info.py", "ftype": "file", @@ -371,6 +385,13 @@ "chksum_sha256": "8e30c457f77f4adfb2f575079770a83765160e3feebfbc97a2998ad85aa0f806", "format": 1 }, + { + "name": "plugins/action/devices_live_tools_cable_test.py", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "79dac59cb5971ee77aa180a65edfc2860395b0babd61c84d6e244021ec33b068", + "format": 1 + }, { "name": "plugins/action/organizations_licenses_overview_info.py", "ftype": "file", @@ -378,6 +399,13 @@ "chksum_sha256": "39583ff6dee8971251b6d6f9a25aac8d0e1e0840f096fa6c564e7eb542e9fc41", "format": 1 }, + { + "name": "plugins/action/networks_wireless_ethernet_ports_profiles_info.py", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "e61420642f6322fc4fb8970183a95fbb6a76883b1f51036d68ad7209697d1c6d", + "format": 1 + }, { "name": "plugins/action/networks_appliance_vpn_bgp_info.py", "ftype": "file", @@ -389,7 +417,14 @@ "name": "plugins/action/networks_bind.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "61d1573547c60fcedaad4fd5a9ef27fdbe0a65e432ada54f3b4af7d482e097f1", + "chksum_sha256": "8a6b18d9f62d7da215dcfbc1b4b5ea08a49eba0dfd07dcc6a47cbb05693f6bd4", + "format": 1 + }, + { + "name": "plugins/action/networks_wireless_ethernet_ports_profiles_set_default.py", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "756b1e454b52a886510d9a355daed1f92c81731a641aa290d5a2a414a06fca2b", "format": 1 }, { @@ -403,7 +438,7 @@ "name": "plugins/action/networks_traffic_analysis.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "3b204be704b7bbff6f6175f116facf5918fc840452d5dc57776a3ae9c4a93cea", + "chksum_sha256": "d390b9cbabc169966f2898f1ecefa475d42a0a6a22f1620669452e69e054409a", "format": 1 }, { @@ -445,7 +480,7 @@ "name": "plugins/action/networks_wireless_ssids.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "6f873d232d527b0b3f700a7e5dad3bbe5aa87c09a739bfd687e2c9bfdc847d77", + "chksum_sha256": "73d65b8e5f3dec87baf7749cc38cf7336e21df1e33dc93b1b4b8ea553f6ce5ec", "format": 1 }, { @@ -466,14 +501,14 @@ "name": "plugins/action/networks_firmware_upgrades_staged_events_rollbacks.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "d24d826b4e3d4dfd3117363264e43d722ebca07955bb6491fc18f92f2ac9285c", + "chksum_sha256": "4e002d75fcb479e6a5a5eae6f34df6b90d54187bffbd676d35624926a8840aec", "format": 1 }, { "name": "plugins/action/networks_settings.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "a56a03e8a399d3bcf4d9e4d11f672c636d36ac6b6780078265ad2a437cad6d42", + "chksum_sha256": "9710ed184638be99ab6db382fe1f55946710c7b1810c08d409f7a17a0ee4ff65", "format": 1 }, { @@ -494,14 +529,14 @@ "name": "plugins/action/networks_camera_quality_retention_profiles.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "60cee9e90932c52d4a8bcfdedb2144adc35e777152cb8849dff6c6c45eb64376", + "chksum_sha256": "13a0b1c9af236e07c7374806a24e7bc21821c982bf31b790de1ea4fffce3e4b6", "format": 1 }, { "name": "plugins/action/organizations_early_access_features_opt_ins.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "d44b97307f31a3670ded279b646350185bcb2cda7a6c40899dbcd5984950b800", + "chksum_sha256": "5aca094ab1a817a0bc44a7e0ac788a331b0f58c1149c3d2f6202aa6ac935adfc", "format": 1 }, { @@ -515,21 +550,21 @@ "name": "plugins/action/devices_cellular_gateway_lan.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "a980fec69c4c3cbed2a54d377f94f41fd1a078e7b8c7834c51a363f84985aacb", + "chksum_sha256": "04b2352c171f904a0cc0e52208d8f9d9b1ce436e8935eb55c8e736cf0e23d872", "format": 1 }, { "name": "plugins/action/organizations_alerts_profiles.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "446f3e6c23a53f81310951278cfd923b337c3156789f5eff55d0b210e903a7ae", + "chksum_sha256": "2c27c697ee3ad4d902882482d857490b96b4c3d404d556f15ea1109f062e1e98", "format": 1 }, { "name": "plugins/action/networks_group_policies.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "816083c2545087118d12104c57f51e23c34a27ee918ad811b808e1c28dc10435", + "chksum_sha256": "8c5586b9b6e188921139fbfcc67d6bff020bd454a34b0cb90a76acc634a065e6", "format": 1 }, { @@ -546,18 +581,25 @@ "chksum_sha256": "13064a44259f1edd73279aaeb3d57404983db6ba61fd41d501896483e34be105", "format": 1 }, + { + "name": "plugins/action/administered_licensing_subscription_subscriptions_info.py", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "2cd49df297191ec6b00e7d750e1c68d7857ed8d40407e06dc4f25dea45b2297e", + "format": 1 + }, { "name": "plugins/action/devices_switch_routing_static_routes.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "0777b51b7749d7d3860b011cdb077710c54c980956e777dd0304246d15b76d44", + "chksum_sha256": "c08a1eb5e12539535e65491b4ecf244e0d8bf88ec4ad1a9302e5d851633a1b46", "format": 1 }, { "name": "plugins/action/organizations_openapi_spec_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "e0b214cd63d937c2ab16c8ec4bf1bd35f13ff36a29c2f78ac7eb489ac835399b", + "chksum_sha256": "ecb6affb8bc79d30cebf8f3b85583f5b0b4bb4ca1efb400cc50bd9e6ec49f11a", "format": 1 }, { @@ -613,7 +655,7 @@ "name": "plugins/action/networks_wireless_settings.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "98f02332e0e8aa8cf8ae3cd757c324892a8c391a961fa8eb272164fc48a79cae", + "chksum_sha256": "ac806d38e4f3e222bbce3002fbc012b50d7000ebfd3a7ab6542ca597af332191", "format": 1 }, { @@ -627,14 +669,14 @@ "name": "plugins/action/networks_switch_settings.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "ee6bbafb359c99d3948b376b027eb50c30ef4a97415499363f721a104ce5585b", + "chksum_sha256": "73864954874b2cbcb8cbeffef89d34b2f588148ed4a8cf41c50b6e61ec547d8b", "format": 1 }, { "name": "plugins/action/networks_switch_dhcp_server_policy.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "393642e80f78628ce071ae196f48d76330e7051e8dbab6ddc32b7a429a0db1e4", + "chksum_sha256": "9582a8d31d544f395d5a50d0076185c5c0dd170b5924088b5f5cdd9f76154105", "format": 1 }, { @@ -676,14 +718,14 @@ "name": "plugins/action/networks_sm_devices_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "bd7f3792dd73ed21decdae15896d7ea8a60bbb8bd7f8a3cb3e8cef9858cf24a2", + "chksum_sha256": "407513c3d238200643e1400e5cf8456a2e7b8ea5552736fdf4ca88215164bcb8", "format": 1 }, { "name": "plugins/action/networks_wireless_bluetooth_settings.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "30516cd8b037cb951c6a1dbc69fcac6e3a506aaef0edcfaca122175b08966a09", + "chksum_sha256": "0f0e3d19016c64f50fbe87ea01ba43558286602ffe9466f2f46c6e89c1a5b0fa", "format": 1 }, { @@ -714,6 +756,13 @@ "chksum_sha256": "91282a5be26b055e4711f63d74d33df10af7722b177a6f7028a730e5be72227c", "format": 1 }, + { + "name": "plugins/action/networks_appliance_rf_profiles_info.py", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "416f032fe7e639c3b017aee5196234c69f00bc4ba261bfff2a1e67e06737ee3a", + "format": 1 + }, { "name": "plugins/action/organizations_saml_roles_info.py", "ftype": "file", @@ -767,7 +816,7 @@ "name": "plugins/action/networks_appliance_vpn_bgp.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "285e41b4b628c5805f5f664e49473dac6ecdbd9d4a767a0862c9f30e8ba75c2b", + "chksum_sha256": "a63dde24c5b08eb8a4c473ebf04f22931e3b9da834389eaf44a899222d3eedb2", "format": 1 }, { @@ -781,7 +830,7 @@ "name": "plugins/action/devices_blink_leds.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "28d16ffe598d82bb91b1fd84f46977d416921e4c5771333cd00a14fe4b598f69", + "chksum_sha256": "a16973cd9acab6937163aca421c64a561bc5069b986b9ef2192744f211ffeedf", "format": 1 }, { @@ -809,21 +858,21 @@ "name": "plugins/action/networks_wireless_rf_profiles.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "76bbe3a233181d0984b708b5e974bf1f4d30efbc818b6ae89cd1cfac182c39d0", + "chksum_sha256": "a3991fc97a830ea6898fafe95f523c5bc0f8aab902866dbb6a5e5a83b7579d80", "format": 1 }, { "name": "plugins/action/devices_camera_sense.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "19a130eebea23c61ed66eca4c2a75d1f2b2ecd4600451b6c5e58d3d908e1d952", + "chksum_sha256": "46e6eb26fd9babd5c5af3e9c969ee0c1ee8f7067106e339c671fed6892430831", "format": 1 }, { "name": "plugins/action/organizations_inventory_onboarding_cloud_monitoring_networks_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "ab0b0b788ad1a766e6c555772a0cb34d233d16a3a522f5793af2917e0ef92e9b", + "chksum_sha256": "03504cbbd26819a6e258ba9afee2d073cc0908291154c819821b6f853627b65e", "format": 1 }, { @@ -833,6 +882,13 @@ "chksum_sha256": "b0c4640124306286064ed2039a819ada770c2a3a14af434a222cc49a462f452c", "format": 1 }, + { + "name": "plugins/action/organizations_camera_permissions_info.py", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "754da51029ac942d3930fe5e53ff50977278c917e79d7fe277edf509e7a61ef7", + "format": 1 + }, { "name": "plugins/action/organizations_switch_ports_by_switch_info.py", "ftype": "file", @@ -844,7 +900,7 @@ "name": "plugins/action/networks_switch_alternate_management_interface.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "8bcf9922f13f03eebaef7af2ddd05c64a14e3b9cfd6a7f3d35f8beb58bfad97d", + "chksum_sha256": "5925677b320733154104c00b8ec7cc4a355eb41b508c55bf54431d5bd296f429", "format": 1 }, { @@ -903,11 +959,18 @@ "chksum_sha256": "2091b5c97c0d80582b6aa7fa64170901fb586a54286338c243131dd2c90ffbe0", "format": 1 }, + { + "name": "plugins/action/organizations_wireless_devices_packet_loss_by_device_info.py", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "ad42c4c0af3d6fe409b20190e319e0e0b875d7aa70f6fffb150c081686a3bbaa", + "format": 1 + }, { "name": "plugins/action/devices_camera_generate_snapshot.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "28ff182ebdc9409322811d4215d98b63677fcc9fc354658e56f4b58113b7db84", + "chksum_sha256": "47100426ff418d7d14c6b86387bb1fc855de68766ec882a318758caae31d473a", "format": 1 }, { @@ -942,7 +1005,7 @@ "name": "plugins/action/networks_wireless_ssids_hotspot20.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "5c0ea0dab98a510c147ec75817befd02852428fec3c66d266c356177f17fab9e", + "chksum_sha256": "eed447ba0b5c6e2647a68288de2d03f9be927b7f6a3469e5130769bc3de926a7", "format": 1 }, { @@ -977,7 +1040,7 @@ "name": "plugins/action/networks_wireless_alternate_management_interface.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "27345a94623c7200cc793377365b5240ae410f63ce3ea6e7efdcf82fca333f19", + "chksum_sha256": "f635b1ccefe9c05e1eb61326a946c4fc20077e8577746f085b4c2446b1acccf4", "format": 1 }, { @@ -991,7 +1054,7 @@ "name": "plugins/action/networks_sm_devices_move.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "b93d6147029dc41ed78f8e7a4d5f29b9c67350d718f4a7fb3d079c648ac53af9", + "chksum_sha256": "3f84a597dcd9676e1f405e150f3fea914950dcaab6e7835e6c0e7529a82d3142", "format": 1 }, { @@ -1022,6 +1085,20 @@ "chksum_sha256": "0c4a3bac7e7afd5aa59836df5da15b9313cb48b539809e9fbd12c371070d5941", "format": 1 }, + { + "name": "plugins/action/devices_live_tools_cable_test_info.py", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "044ab01319420b7fb6f989a5435115918bd59fad7b6d705670ade10667efdc16", + "format": 1 + }, + { + "name": "plugins/action/organizations_sm_sentry_policies_assignments.py", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "59bdc154ed08d86acb03078cd6f9f20bd69949ba85a2f3f60154f40aec8b5772", + "format": 1 + }, { "name": "plugins/action/networks_wireless_latency_stats_info.py", "ftype": "file", @@ -1036,6 +1113,13 @@ "chksum_sha256": "d7a37454f66a026b0944eefaa95cc3bfdd8b58f2eb29a3d9141068e87d8cd2bc", "format": 1 }, + { + "name": "plugins/action/networks_sm_devices_reboot.py", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "3ef6b74c75867e6bd18e1d4312b42ac54fe776c31670041cefab403f202aaa36", + "format": 1 + }, { "name": "plugins/action/networks_wireless_ssids_firewall_l3_firewall_rules_info.py", "ftype": "file", @@ -1050,6 +1134,13 @@ "chksum_sha256": "4a311e4ca4e552fdc1ba5bbb93cfed51023a7c83d00d71bef5b120a36836714d", "format": 1 }, + { + "name": "plugins/action/organizations_wireless_devices_channel_utilization_history_by_device_by_interval_info.py", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "2e053e8a6a83efd0b0ef268b16ed73880e4b0b788f447645ed8136052df4b02f", + "format": 1 + }, { "name": "plugins/action/networks_info.py", "ftype": "file", @@ -1071,6 +1162,13 @@ "chksum_sha256": "cf043ac659174cbeb81caf5a516c4d50b3d3602a29f3ce9d80deeb4acd92e397", "format": 1 }, + { + "name": "plugins/action/networks_wireless_ethernet_ports_profiles_assign.py", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "a30cb6d251c0d50c204699633bead086f9b1346ea852cf0acc75ab7ac6ded9bb", + "format": 1 + }, { "name": "plugins/action/organizations_adaptive_policy_groups_info.py", "ftype": "file", @@ -1082,7 +1180,7 @@ "name": "plugins/action/organizations_firmware_upgrades_by_device_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "86a29f2f63ff2e802d981239a781f2c31cebc52168814ac67ac16972f941f1f3", + "chksum_sha256": "ba836b95647f419df5343966a1dec6f02db423d9fd94ed1ff3669fbc992c50b5", "format": 1 }, { @@ -1117,14 +1215,14 @@ "name": "plugins/action/networks_switch_stacks_routing_static_routes.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "618ffc3af9c960daa0f8656389450a4d769d5a8f69552270eaae70b1761f5140", + "chksum_sha256": "3c14eebce4ac06b7599c626e81225cb8cd752cad26ea290540e4be5e9731d071", "format": 1 }, { "name": "plugins/action/networks_appliance_security_malware.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "caca343b6fa3ba13a8a0e8657cbf3e4d53946a46203f648e9bfa9218fa320c7c", + "chksum_sha256": "b389c716d51424a6cd25d265c4606c8c789e1d5b01f77beb25596eaa693e4ac2", "format": 1 }, { @@ -1152,7 +1250,7 @@ "name": "plugins/action/networks_switch_dhcp_server_policy_arp_inspection_trusted_servers.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "33189281debc8dff9a2799b8159b13ed803fd35c6a671fdb5b5cd4b71c6c377d", + "chksum_sha256": "83fb1385c92624d88cce83bc273654fc35d9c526bba17b8f32fbe5434afb9cc8", "format": 1 }, { @@ -1173,14 +1271,21 @@ "name": "plugins/action/organizations_saml_roles.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "b6aaddd387d31bfac6f4c20358436aa8e3cd0915aa362d06c1da349834b73562", + "chksum_sha256": "484ebc0b239bacc37d64a8ddca1dd966848c31f3679d05f56b1d7784a028fbd5", + "format": 1 + }, + { + "name": "plugins/action/networks_vlan_profiles_assignments_reassign.py", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "7c965303108f4a8880cce3f608cb790b46c7df4bc4c32cceea48a4f111a3f83b", "format": 1 }, { "name": "plugins/action/networks_sm_devices_lock.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "1eb87a04f06d3c5cfcdfea0415a6bccacc8d220ba5dfbbce2560b453587d7c3b", + "chksum_sha256": "c2087fed2683e46f6b642fce237067aa40ddc0d730d990f6cb1adaee83fec1ca", "format": 1 }, { @@ -1194,14 +1299,14 @@ "name": "plugins/action/networks_sm_profiles_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "f1fde702fbe5f3ac739463087c647fc61b30ed8dec2acdac46edbe1e5d7aab98", + "chksum_sha256": "6c304c71e7dd2cf752cca86b9866f664ca7625a55af10fd1dce422df177b7275", "format": 1 }, { "name": "plugins/action/networks_wireless_ssids_vpn.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "f1df4f365093c1d959fe61ed1c0c1d75edae426f7a971eac2fe9ea24ceee81ba", + "chksum_sha256": "c5f61f99085ce6380a915f26db4d773c80f7ebb559d6c8048e28e317e94800c9", "format": 1 }, { @@ -1222,7 +1327,7 @@ "name": "plugins/action/networks_appliance_traffic_shaping_custom_performance_classes.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "9dc16f38dcb94dab74df94ac706d5fbb5a57a7d40f31c5683ceb642f08a48ee7", + "chksum_sha256": "a5f5a03b7e558235143f968a9ded6c8b540791169077af55d10550c2ada59fb4", "format": 1 }, { @@ -1243,14 +1348,14 @@ "name": "plugins/action/networks_webhooks_http_servers.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "f7e5892e89af829437cb386299b555b6386a5f37a3e213d523aca9f81e8f1ff9", + "chksum_sha256": "2c361e2bbed0f92a7956c09dbd8f3db22cdf02712afb29a3406ec32622a6f4c2", "format": 1 }, { "name": "plugins/action/organizations_config_templates_switch_profiles_ports.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "cdc187dcb687420633a80777efa76f2cd413fa30f4772848f6d910365f7cc30c", + "chksum_sha256": "5680de144715e3b45d1a88d25c44d78d7063a4b8f537e829a17e5b78da0d593e", "format": 1 }, { @@ -1264,7 +1369,14 @@ "name": "plugins/action/organizations_inventory_onboarding_cloud_monitoring_export_events.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "66443417f8f2153e201139e8358788d28bbdc09f0bedb5f22ae03758aef8a6bb", + "chksum_sha256": "e26476935c85571d37f691d79a24873cc712232ab0f4913537c7370238b625df", + "format": 1 + }, + { + "name": "plugins/action/organizations_camera_boundaries_areas_by_device_info.py", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "dd3670f3b5298a47f324b8184442f3f4677e04e695776aa2784416a0481320a6", "format": 1 }, { @@ -1292,35 +1404,42 @@ "name": "plugins/action/networks_appliance_traffic_shaping_uplink_selection.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "82a4ff4d864a47c443301763130cd570c988f4ff87911d8c319e7344de9b855c", + "chksum_sha256": "5f394df5adcaea7d67b45a6a04ff4d175b7bf8a627b860768593a56f5b794917", "format": 1 }, { "name": "plugins/action/networks_sm_devices_wipe.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "a5d0b9da224b9904cba2ea5922287414570ad7928f44f1067af591a49f525054", + "chksum_sha256": "0522106f60eafaa7010f9147ba29a12027b68476a2b5c5f9b61b023783b9301d", "format": 1 }, { "name": "plugins/action/networks_appliance_content_filtering.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "cee24dee36495de5c8f7f7ebeff3278289d5b8a9e4a43bf50249347a1da57236", + "chksum_sha256": "c1df30fbb991becc3279f1adc45ad819bfff33e48774bf9562166ed6d8b17b64", "format": 1 }, { "name": "plugins/action/devices_switch_routing_interfaces.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "adc527362d40d1ba143f0abeaf564cd4952c20bebed859df5c391c1b2d9837f7", + "chksum_sha256": "b4d9cb0befc9aeb9f2ff6b248db60f066fe53e5626acdf00b6ffe6cd5322fe69", "format": 1 }, { "name": "plugins/action/networks_wireless_ssids_bonjour_forwarding.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "5416e12dc36a39b5b5576ce36fbf0de83cdca996495da2e28022d3b0f7e55971", + "chksum_sha256": "5a20953c7aea7a955b2b652a9033448ece79e2863dc64384b2057aa1c231b978", + "format": 1 + }, + { + "name": "plugins/action/organizations_camera_boundaries_lines_by_device_info.py", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "15e50b102e4dd509cf288d204e17a2a4cacf3df0c034f459f1fdece35e8eee04", "format": 1 }, { @@ -1397,7 +1516,7 @@ "name": "plugins/action/networks_switch_routing_ospf.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "04d9dfdbc320038b416600bd9a5153dea6b6fe0c9e8f379e3c82c6d5fc9271a7", + "chksum_sha256": "4f094f3881f5f2b9671a97f10a64fff80208185cf5d09dff61708b01526ccbc6", "format": 1 }, { @@ -1418,7 +1537,14 @@ "name": "plugins/action/organizations_branding_policies.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "bc6d01f6590205772e571a73073f7d9b0848deebe1860c0bb4fa184bd5917a78", + "chksum_sha256": "31865e7abbcfd1a379687e302500d265dd534ce338a7ed0db2b3b90765febe6c", + "format": 1 + }, + { + "name": "plugins/action/organizations_wireless_devices_packet_loss_by_client_info.py", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "b90dfccc35f2739cbf4b803ccbef197377af320cbf9390316ee4b07bcd065292", "format": 1 }, { @@ -1432,7 +1558,7 @@ "name": "plugins/action/networks_cellular_gateway_subnet_pool.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "d1dde15c4b309aa624bb77e22a0b6378584bb2cfe760b50d879ac87f071c0de4", + "chksum_sha256": "698c2073767ff9b45b5dadf364a6c6454e51e843fa7eec422d22d130720703c1", "format": 1 }, { @@ -1551,7 +1677,7 @@ "name": "plugins/action/networks_alerts_settings.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "45f2db3b35096951b61847f3385fea34191886d7646f117019354cdb23664ac3", + "chksum_sha256": "b01670216f41a4ae23016026aa8e1581c6a86c7fae56fba935b9ad0ea37d6cb5", "format": 1 }, { @@ -1603,6 +1729,13 @@ "chksum_sha256": "0827d7876fb191e698b4b5d511aaeccbd2aae0f7ce69f56fba58a4005fe112ad", "format": 1 }, + { + "name": "plugins/action/administered_licensing_subscription_subscriptions_compliance_statuses_info.py", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "5c92d3a89dbc02d5eff0be27a54a6b823954fcbc010c3f8c9cde684da310ba07", + "format": 1 + }, { "name": "plugins/action/organizations_summary_top_clients_manufacturers_by_usage_info.py", "ftype": "file", @@ -1628,7 +1761,7 @@ "name": "plugins/action/devices_camera_custom_analytics.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "c61b040eef23a19c4c923dd573f737c42e796089a9866889857e53eac5da8b35", + "chksum_sha256": "0210beaf6e41b8170f89505bed3cb2bac8e23cc4395142eae1369a6d9a825982", "format": 1 }, { @@ -1638,6 +1771,13 @@ "chksum_sha256": "ab9a84c5644557cc701e4cc489e80e9b8a770d8966cc75781fb6415a9632694a", "format": 1 }, + { + "name": "plugins/action/administered_licensing_subscription_subscriptions_bind.py", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "9d0848fc63669c2b22be3f24bb9655befb06dd94226a9f636a14708db17f121f", + "format": 1 + }, { "name": "plugins/action/networks_appliance_firewall_settings_info.py", "ftype": "file", @@ -1663,14 +1803,14 @@ "name": "plugins/action/organizations_saml_idps.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "aebe2bf7b5b1688821632f814ff87161682b88afa7c94f65decd9a24d9b9196a", + "chksum_sha256": "f6c9cd71d955d453ee5a93a42952800be8cbb4c378602f040a6e7471925d7876", "format": 1 }, { "name": "plugins/action/organizations_config_templates.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "d3585c841dfee532d3c14aaf270c0eea25d0eccb88c9117149d18c3fb5b3943b", + "chksum_sha256": "dfb94e7a2d31cf4cde7ce263393b54b809332b3694d15f9606ff9af949882935", "format": 1 }, { @@ -1712,7 +1852,7 @@ "name": "plugins/action/organizations_policy_objects_groups.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "6e8c0ef146477202f9234ccc68ef14031af671cfcd65f59ac87868a7f707991d", + "chksum_sha256": "eba12e7942d11ed86d4f0ce5cee4c152e7611a6e312bca29a87a255173fef4dc", "format": 1 }, { @@ -1740,7 +1880,7 @@ "name": "plugins/action/networks_switch_qos_rules_order.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "ee61133cd80644b44b9c6bc2b822cd0366de35d5ba5608f8f593331542ae12d7", + "chksum_sha256": "cf745cdab8e0411d902ef2083575945e41da6e68826edce49106af8bc0785235", "format": 1 }, { @@ -1754,14 +1894,21 @@ "name": "plugins/action/devices_live_tools_ping.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "34377f9169e9be60bb2e85649aa13c412d9bae99ac91a0696055e048c42cddda", + "chksum_sha256": "3693d9e35027a400d4413e60642dbd1b45c03bd4ea7f7e5551d1d791bee3d3b1", "format": 1 }, { "name": "plugins/action/networks_meraki_auth_users.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "594c78ccf4c0d793f306d36f0267e3911bb7a891f3afaba4c9f27f4fdd5f9fa9", + "chksum_sha256": "c30b5fa4503d7e62dc2ea8485d2b1ef8db2b13cf772494ab96ec913be56d9787", + "format": 1 + }, + { + "name": "plugins/action/organizations_camera_roles.py", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "ca305cf3d96fc4ef3495ba70a5c356fc3d896cc285a7327e157afbc778c8899e", "format": 1 }, { @@ -1810,7 +1957,7 @@ "name": "plugins/action/networks.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "316e6e25a0f1f5655e6e6e720c1dc910cbb237c51864d57518b42192994d7772", + "chksum_sha256": "060a0905a7a9f6d28732177152e285077e86478757f70891072ac4dd2a5663ac", "format": 1 }, { @@ -1827,6 +1974,13 @@ "chksum_sha256": "a22a2dd9a5cd76af73e2f953952d66a0bcc0b74473382a23a95aa9fbd72ae02b", "format": 1 }, + { + "name": "plugins/action/devices_live_tools_throughput_test_info.py", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "044ab01319420b7fb6f989a5435115918bd59fad7b6d705670ade10667efdc16", + "format": 1 + }, { "name": "plugins/action/devices_camera_sense_info.py", "ftype": "file", @@ -1866,7 +2020,7 @@ "name": "plugins/action/networks_switch_stacks_routing_interfaces.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "e537e725ae27c7c6ee1ad1fab3b2a85bd7ff3109d8ca48b94f1380bd82d9e4b1", + "chksum_sha256": "ff9ecb15042c54c28c2350a62960c65ca13201505f3beae3ea20eecf7b340fa6", "format": 1 }, { @@ -1908,7 +2062,7 @@ "name": "plugins/action/organizations_claim.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "aaab0e0d170a43efcfa77009ee99707ac0d96cef2167d1031243f267685a50ce", + "chksum_sha256": "1bff3668070c43abec6348f989d2514b0812479c4897ac88c857bc468c42fd4d", "format": 1 }, { @@ -1925,11 +2079,18 @@ "chksum_sha256": "34ad9cb55ee749bab0675e709508c6949ca5e1f2a5366af4984520cd837b24d8", "format": 1 }, + { + "name": "plugins/action/administered_licensing_subscription_subscriptions_claim.py", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "c7cf4d0859068ab61b35cf8ab0c224b7f3647bd15e81b12629a76a152b737811", + "format": 1 + }, { "name": "plugins/action/networks_appliance_ssids.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "2ae6f719332e436324ad99a1c167ebd7e7dc73d56c0c1622f94d28659710a2d9", + "chksum_sha256": "bd0325343811e3c23d4a7de7d869a65cf213c5682eec5829800727ae445e9620", "format": 1 }, { @@ -1946,6 +2107,13 @@ "chksum_sha256": "30be8db3ae4706435388cc2e21c586f4218f08a7859dcfd9100e6bea7793412a", "format": 1 }, + { + "name": "plugins/action/organizations_appliance_traffic_shaping_vpn_exclusions_by_network_info.py", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "804a2f13c4a38a6aa59f3179cc3d7545691581689ac06fd1a8b2818eb91ece4b", + "format": 1 + }, { "name": "plugins/action/organizations_uplinks_statuses_info.py", "ftype": "file", @@ -1953,11 +2121,18 @@ "chksum_sha256": "244d4636e83a69809b133c0aa470e50a4d552535ad1204c319860825c523952f", "format": 1 }, + { + "name": "plugins/action/devices_wireless_alternate_management_interface_ipv6.py", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "135c68c6e13daf685d2b0a88972313e8c8b2529f55c8b3b7d48c90a214ea9f35", + "format": 1 + }, { "name": "plugins/action/networks_appliance_single_lan.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "9bb51fb3995a25a9fd9418067aa16d0733bcee21046604046257195f2642c4ed", + "chksum_sha256": "481e89b4146b20348a7c1ddb05014406417ea0b76d6388201fd4a7d4ad1e2277", "format": 1 }, { @@ -1978,7 +2153,7 @@ "name": "plugins/action/networks_switch_stacks_routing_interfaces_dhcp.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "871a83e486415bef334f20bcc18e005c7e97269450b40a5317516454c8e43379", + "chksum_sha256": "7f88e1e6059c8e8f4dc0c46327851a0deca3dfb2a68cba5e814951044b5dbba1", "format": 1 }, { @@ -1992,7 +2167,7 @@ "name": "plugins/action/organizations_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "d5a17cb1555241fdd0af7d48a040394092825401c6b79edd999eae3607d8c642", + "chksum_sha256": "cceb95d07a5d9585021734e73ab798158eaba2728b1cb3d85d89c71531f21aa6", "format": 1 }, { @@ -2006,7 +2181,7 @@ "name": "plugins/action/organizations_adaptive_policy_acls.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "770fee0b3d5b9e131144e1e84bdc9d16e7702d4f41fd5e5520a02ef816326b95", + "chksum_sha256": "467f0a935221250788dfb2c9821610ef5098f5f3fe8e705db071140b3dfa30f7", "format": 1 }, { @@ -2041,14 +2216,14 @@ "name": "plugins/action/devices_wireless_bluetooth_settings.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "26a76ea9fa8c1ae1ee281c17d6e4b2ca29b42d370dc2406cc79abe4cb0bbaef3", + "chksum_sha256": "5b08537ab472b899a49b31fb8425809b25b622a6417782c25460b378cf7b60d8", "format": 1 }, { "name": "plugins/action/networks_sensor_alerts_profiles.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "486dba6e745a9e7a9941e40de5f9d5c536392a80c903039517e141ea2f319c4e", + "chksum_sha256": "69da6dd0a4d3b8db0f3fb9881703cdf2a3af2762e840c1ea24f59b389ba3fd97", "format": 1 }, { @@ -2072,6 +2247,13 @@ "chksum_sha256": "bc3c7c3e4fe38c43331b4333b16f5a11c2e967345953be65e2a69a0c4b9d5eb9", "format": 1 }, + { + "name": "plugins/action/devices_appliance_radio_settings_info.py", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "e90fc927566badf06952b6d5d3f48200127ba95409be8f41513f9ce9372521c0", + "format": 1 + }, { "name": "plugins/action/networks_appliance_security_intrusion_info.py", "ftype": "file", @@ -2107,6 +2289,13 @@ "chksum_sha256": "282a4cb8c7178fead3a0014a1412a028fe9ac37b74e6b4aaec7cb56aadd11db0", "format": 1 }, + { + "name": "plugins/action/devices_live_tools_arp_table.py", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "d562dfa28fc6a7085ad6d1359dbb5d7b9543c0c9e46c582635cf54096f1f3c4a", + "format": 1 + }, { "name": "plugins/action/organizations_api_requests_overview_response_codes_by_interval_info.py", "ftype": "file", @@ -2125,7 +2314,7 @@ "name": "plugins/action/networks_camera_wireless_profiles.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "8b5e67e768d0ea1efe496a2193988e5099b3200fdaa43e5238228d284e1b71a2", + "chksum_sha256": "f835135bd7b060af41b3dc21366e9148040afe41293d75d9b44822796f221d4c", "format": 1 }, { @@ -2142,11 +2331,18 @@ "chksum_sha256": "4b368dd799dafe66cd97ce67e68d9ec5abe51fe69a80833d809945370ea29ea7", "format": 1 }, + { + "name": "plugins/action/networks_vlan_profiles.py", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "0593cbd6b69dd91e0610f67e768294bc2ac28fba166bdf162a30460887680440", + "format": 1 + }, { "name": "plugins/action/organizations.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "6e78d416c6548f29f39ea2ca463a51cc4f1edb5d4eb85f6a6f81ed50acedfd8b", + "chksum_sha256": "985e4441a9d9018a20bde175c801602c9511cee40534d8745f54a4e517c0afbf", "format": 1 }, { @@ -2195,7 +2391,7 @@ "name": "plugins/action/organizations_inventory_claim.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "bd816af11d3c8a1cdf111377e8d07d12e8e42ee269ea68328e08f99c73ff7d97", + "chksum_sha256": "cb517b5f833ec6b32fa371b5c994b5333781cf80b75be6ac054b244c37081c37", "format": 1 }, { @@ -2251,7 +2447,7 @@ "name": "plugins/action/networks_switch_access_policies.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "ab6b359e89b979ff14fea54328c16f58cda6c452ede041798b162ecfc9cc9f6e", + "chksum_sha256": "b182bee6b7fa31fe228bd026fa0867711abdaa1f745c0442fa1bc901b6aadf55", "format": 1 }, { @@ -2265,14 +2461,14 @@ "name": "plugins/action/networks_mqtt_brokers.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "52372febb9a0c8008fff1cece130bed0d0595b3144280f9a363dc22dfcdcaf0d", + "chksum_sha256": "8dc380c3f6eb9bea43baa67e9c919721484ae6f3c67fdadc38515ce9b7832a57", "format": 1 }, { "name": "plugins/action/devices_camera_quality_and_retention.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "4d8c304090222f19f677d4cdcc41cdd50795abf34ae8c5ed0a435c7229d17e54", + "chksum_sha256": "c658d0ff695c9fb3e9a12185788ad13d8f14f30c0c087254342ceecd0ee0c5a1", "format": 1 }, { @@ -2300,7 +2496,7 @@ "name": "plugins/action/networks_webhooks_payload_templates.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "a3a8e080905d002f4070b84aeed14b382954590e90b70a0ac0c5762d65910fa7", + "chksum_sha256": "3b5adb1d1344bbe66fc3606cab076d34bb3664b394e3fd7c7cacd61c6fcf75cc", "format": 1 }, { @@ -2335,7 +2531,7 @@ "name": "plugins/action/organizations_login_security.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "cfd253ac346ab0ec33d9a4b3eb576f157fe1f735c783927dffc1be2aefc81346", + "chksum_sha256": "631037db87ccdb1ad1f77584023d74bd3032727480bd58551f844822f2ec8349", "format": 1 }, { @@ -2363,7 +2559,14 @@ "name": "plugins/action/networks_appliance_ports.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "c8e5d786e3b68b40dfa7b6dc8b5b44cf893caae803d5e5fb968d1068433dd5d0", + "chksum_sha256": "12e9d244eefc958ca2785f5ffb1bf37d77be5132f6866fb2337d85c5419e1b2f", + "format": 1 + }, + { + "name": "plugins/action/organizations_sm_sentry_policies_assignments_by_network_info.py", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "ca3e36720f3008880ee6f19299f5c38b28e8b3fb3d6c4850a725d3e313d94569", "format": 1 }, { @@ -2377,7 +2580,7 @@ "name": "plugins/action/networks_floor_plans.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "f956a6b69a341976f7d5fc84761b9b6eea8505572778335db76a106f1693c033", + "chksum_sha256": "33df6fc5e3bcb5e98a679f67fa74b0b4e97b67718373c5ae74c46ec7fcda8538", "format": 1 }, { @@ -2408,6 +2611,13 @@ "chksum_sha256": "58995bd2435ee09d804cc59ee6a3e1e74e05b7dc07476b8c2269ae872b041312", "format": 1 }, + { + "name": "plugins/action/organizations_camera_roles_info.py", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "d8ff8755d3faaf8583dc6c6e9ef24a96487890a3e7f3076a7fe9d68e4b669d5e", + "format": 1 + }, { "name": "plugins/action/organizations_summary_top_ssids_by_usage_info.py", "ftype": "file", @@ -2419,28 +2629,28 @@ "name": "plugins/action/networks_sm_devices_checkin.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "74cdcef4d2a12680b23e46fd1ee74c74946bb7dadd3c3bc64f02c008efdbe5d1", + "chksum_sha256": "247a9769c7b39f5329db326f07077d4d288bb7da3ec29ca2682981cfc9a2db63", "format": 1 }, { "name": "plugins/action/networks_wireless_ssids_splash_settings.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "275c2fe6581c2591b8e3b9019bc6e210507b6670e85a50a4c98e9e660c687abb", + "chksum_sha256": "2c7710606ed84a26bd8886ac957ac979f98c86d832d411d42377274045f1d1b0", "format": 1 }, { "name": "plugins/action/organizations_networks_combine.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "cbd6c6ef4df423eb438caf5672f36dfea894ffa91afb1894fa6679403dd900fd", + "chksum_sha256": "4c474bf360fc5dc5d2c5055cb7a2096c360eb3d46439e0ed283406fa7941a6dc", "format": 1 }, { "name": "plugins/action/networks_firmware_upgrades_rollbacks.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "ce6b1d63da85f3573f015d976e12e6acb07c7c8546b3c17230000f48c6c231da", + "chksum_sha256": "3afd7e06aeb59d12dd7c53be4367b5fc76626306ba0bb2da97033813fda27fd1", "format": 1 }, { @@ -2450,6 +2660,27 @@ "chksum_sha256": "777b4994174cc62824aa02320d676a3efbbc26851635921fe28172a267841ff6", "format": 1 }, + { + "name": "plugins/action/organizations_appliance_uplinks_statuses_overview_info.py", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "e3a8b1d43ccd71be33a4a0b751c3461b5a369856461e4f91f78302346126be7a", + "format": 1 + }, + { + "name": "plugins/action/organizations_sm_admins_roles_info.py", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "f7f394cfc3acaaea7a159251e10433ad5fbf0fa7875eb0f23f68d97b4c7e20d2", + "format": 1 + }, + { + "name": "plugins/action/networks_wireless_ethernet_ports_profiles.py", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "c3a15fe7559418b40bdc476ede9cbed4495815d7c592ee92621023c63aac4931", + "format": 1 + }, { "name": "plugins/action/networks_appliance_firewall_l7_firewall_rules_info.py", "ftype": "file", @@ -2475,7 +2706,7 @@ "name": "plugins/action/devices_wireless_radio_settings.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "313df9379adeb7a7e819cc8373b34b3dacadb133550939bd603bdb79f656250a", + "chksum_sha256": "9f3ae078bf261f8898d32b6ab484b0c1a46889456f65c0e6a219d43f742d6ccb", "format": 1 }, { @@ -2485,18 +2716,25 @@ "chksum_sha256": "454ca943612681724701c6a0870cf0087515428769fbdd8a1bed9090c217284b", "format": 1 }, + { + "name": "plugins/action/organizations_camera_detections_history_by_boundary_by_interval_info.py", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "ae05e9a249579de8d2362f291637cdfb7277a690ea0e06a62e80879dcaf09d05", + "format": 1 + }, { "name": "plugins/action/organizations_admins.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "cf3680a7aaac53c272ab5ccc5e2cfcc5ced17f02837c21b4d6516b9e87e3e912", + "chksum_sha256": "06445a9c8ab57ac007e210fdeb9beac54547e14d10d556a0cad1a163a17b21b9", "format": 1 }, { "name": "plugins/action/networks_firmware_upgrades.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "7fa4122428d0608cc07735d12bf8ce33e3248303927088c49e2045711eb7071f", + "chksum_sha256": "ae0f20fa3d906b86bd60f53f48acf8efac8e3d4a96fcf10387ca412eb86a4290", "format": 1 }, { @@ -2517,7 +2755,14 @@ "name": "plugins/action/networks_sm_devices_modify_tags.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "52e1bea3137db4fe14973a2d3e443cbb31f31c5debd6f99004724cb4a68c3b66", + "chksum_sha256": "e37d1aa00b2fcc4cd2e477422ab9eef9a7f9f56672c50c9904b584f176780542", + "format": 1 + }, + { + "name": "plugins/action/networks_vlan_profiles_assignments_by_device_info.py", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "018cfe7b6594a8b4f5c5588d0ffb63671c2689c94b0f1931be48ed659ee5ce4e", "format": 1 }, { @@ -2534,6 +2779,13 @@ "chksum_sha256": "c23dbdce9a985a1400bcbe2c56d47efe213e47b1dd5845ffb817c2eed183e5db", "format": 1 }, + { + "name": "plugins/action/networks_sm_devices_uninstall_apps.py", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "0421dd3de6be540a00fb68ee4e79e2a7e84484b6f2b92fe42593de1b1d50cc0f", + "format": 1 + }, { "name": "plugins/action/networks_sensor_relationships_info.py", "ftype": "file", @@ -2573,14 +2825,14 @@ "name": "plugins/action/organizations_adaptive_policy_groups.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "978180a036ff7b7f65783e030521574a4ece5409088612845fd2b7c989f055bc", + "chksum_sha256": "86582e2a08b5e8c0a74caea2520c4767ff876b660c35078e29f0363a5046dc27", "format": 1 }, { "name": "plugins/action/devices_cellular_gateway_port_forwarding_rules.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "995e3f1f4548a1f80946c0df613933375784ff4b1260e33f4d96b656be716ac9", + "chksum_sha256": "674547a9cb6c604d18542e75160a17118932f41cc5b7926ff7b94ccb45f5cb26", "format": 1 }, { @@ -2594,14 +2846,14 @@ "name": "plugins/action/networks_sm_devices_fields.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "3156d859b4a589458aaaf7fd0b1e04c4adee969d356759a9128e7ade83a08180", + "chksum_sha256": "9394c5d34283eee79086480ea1ed7e38a6da5460f909368cbdc6d319ce13aa87", "format": 1 }, { "name": "plugins/action/networks_firmware_upgrades_staged_events_defer.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "b712f120025452e14464eced504aa1d6c40e18b89cb779efab387a8e12fe0261", + "chksum_sha256": "a56cefb5d2f1f092b15f8f3d10d8dd6777438de88b5841f62318af418e17774c", "format": 1 }, { @@ -2639,11 +2891,18 @@ "chksum_sha256": "41ec6bf13421716f92f1beb4db31b8a6211f04afd935ad1c6f6e1084388607b4", "format": 1 }, + { + "name": "plugins/action/devices_live_tools_wake_on_lan_info.py", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "044ab01319420b7fb6f989a5435115918bd59fad7b6d705670ade10667efdc16", + "format": 1 + }, { "name": "plugins/action/organizations_action_batches.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "14a8f8be895e4ffbd5c0d24b67fbbbddb08f78ecc715592bce74caf84b43133d", + "chksum_sha256": "a55c1f3f347f97e832cf98e28e02325d73e748d89d3d893f80a974a1f4e289e3", "format": 1 }, { @@ -2674,6 +2933,13 @@ "chksum_sha256": "7ceb8c589ea6094d1b961f9dfb684342076d11e3b99889f190358bf9fda9f6b3", "format": 1 }, + { + "name": "plugins/action/networks_appliance_rf_profiles.py", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "721ff3750a984d2ea281aff97d5c5f614497143979484cdaaa90bb4b042f9980", + "format": 1 + }, { "name": "plugins/action/organizations_inventory_devices_info.py", "ftype": "file", @@ -2699,7 +2965,7 @@ "name": "plugins/action/organizations_snmp.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "ea3b1e1ddfdeae21764c84ff7dcc15134149ce0746c4ad3eb0c0c12a2e6c25b7", + "chksum_sha256": "4f7a84704b643422e94a5accd864c4e32c62bef75f5fbf082e0603a3bcf0876d", "format": 1 }, { @@ -2734,7 +3000,7 @@ "name": "plugins/action/networks_wireless_ssids_identity_psks.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "3036c60b97d64d3e947f733e9c149198ee7737d409b93902387c607cd8b342f2", + "chksum_sha256": "898e3514a32b882f21c962a658f4df9cb4cc403b88ea68c34ec8299175266aef", "format": 1 }, { @@ -2751,6 +3017,13 @@ "chksum_sha256": "0a2cfc73b927593786de8ae3a0c988b8d383f6044e8752afaa2ba02e3ce44641", "format": 1 }, + { + "name": "plugins/action/organizations_devices_availabilities_change_history_info.py", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "5d0ce0d3b822b91a583f622100be2aa2a4d9fc791cc3c8b58e237d03774eb86c", + "format": 1 + }, { "name": "plugins/action/networks_switch_link_aggregations_info.py", "ftype": "file", @@ -2765,11 +3038,18 @@ "chksum_sha256": "b8d4ef6b2780166da85feac4d325f8a4bb05be62266221d5aaac58e3470ea41a", "format": 1 }, + { + "name": "plugins/action/organizations_webhooks_callbacks_statuses_info.py", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "aff71d563627c0c9a9be7f1a2e40ee1767733d2239c55683fe1dfa034820a1cf", + "format": 1 + }, { "name": "plugins/action/organizations_policy_objects.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "29ff88c9b9f9957d2b582dfbe10a49f25b53a27eac6de75b28a68a2f65fdbb7c", + "chksum_sha256": "be6b760d260548174a6ad637cb1f3a6603d95d39f50ffc6aac3dcc90c9745c40", "format": 1 }, { @@ -2818,14 +3098,14 @@ "name": "plugins/action/devices.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "4607055ecf8f4610c8d575503661ce5a6bd1ef15121f0516cf7c271d38925516", + "chksum_sha256": "6daea7367c799e68e173a897a79b05e747b1e2e7029f80bcaf61c67ef5a9c126", "format": 1 }, { "name": "plugins/action/devices_switch_routing_interfaces_dhcp.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "73e3e2baac73397aef8ba76c4029395f956a2782c73698cc0b9851dcc13fde38", + "chksum_sha256": "3a413e27c68e0815e428443846fae68a4217c3d296eb1acf714b50cd9894b063", "format": 1 }, { @@ -2842,11 +3122,25 @@ "chksum_sha256": "a07128555cd000411e5a29624df1a94efb0ad8a708607748911a8fd75145bc6a", "format": 1 }, + { + "name": "plugins/action/organizations_wireless_devices_channel_utilization_by_device_info.py", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "88b148ed18f89e7102dbdb4b3cc42f800115f171ba6619e05f0cfde3dac454cd", + "format": 1 + }, { "name": "plugins/action/networks_firmware_upgrades_staged_groups.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "4c7f98976a2cfeb40f9ee108c6efc37863f9745006b291b6234c594136582281", + "chksum_sha256": "883c9c7b268f9d0f2e92fbd7909980d6c0ee076cd96402e681c75f0da697b374", + "format": 1 + }, + { + "name": "plugins/action/devices_live_tools_wake_on_lan.py", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "ae7d8392148b7bd6db4e7a1e76995ad2d5dc5d106191a27a7a310e3ffd226f96", "format": 1 }, { @@ -2856,6 +3150,13 @@ "chksum_sha256": "ab3c4079e7f09b19600345fad952708ef17b9343ff963af3d05ea28395448d50", "format": 1 }, + { + "name": "plugins/action/networks_vlan_profiles_info.py", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "03d1e4b64729fa5061c49b634d440c891e6c76ae7b79e2bc5d090b37b098fe92", + "format": 1 + }, { "name": "plugins/action/networks_wireless_ssids_device_type_group_policies_info.py", "ftype": "file", @@ -2888,7 +3189,7 @@ "name": "plugins/action/networks_appliance_security_intrusion.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "3c77d8a992b703ef9895f5966b9854fa7f60bc25b3dd1602fe80179aa5bc2d3b", + "chksum_sha256": "4c0c426b0cf27863af2837ae828093bdd70e803cbde36873d86f761ede1c392b", "format": 1 }, { @@ -2919,11 +3220,18 @@ "chksum_sha256": "44f6795e7e49fa3f806fb598deeefc12307fa29d7d3e0cea80bca9510919f7d4", "format": 1 }, + { + "name": "plugins/action/networks_sm_devices_install_apps.py", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "d8820f28e29821bc5b84585c4102e374a9e0967a1985d0031040b9d7aebd72a8", + "format": 1 + }, { "name": "plugins/action/networks_appliance_vpn_site_to_site_vpn.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "7f8fb0ad4ea0f917944faede8f1e993eea9c9cf0485aed275dbb3736f282701c", + "chksum_sha256": "c2bf09f1ee54c790be751d44379319a1250b91a1660b70f2438f99ac37f354ab", "format": 1 }, { @@ -2933,6 +3241,20 @@ "chksum_sha256": "34b86f1556434440e985583fa068af59d7e74293355eea7073d00393a0503439", "format": 1 }, + { + "name": "plugins/action/devices_appliance_radio_settings.py", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "dd4c0ac86b9d7168e9170c3f0eabb21f1cb64bcb76ffe84f9008281668bbbee5", + "format": 1 + }, + { + "name": "plugins/action/administered_licensing_subscription_subscriptions_claim_key_validate.py", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "23871bda767e642624098f6326b22f5664bb91103f4617a9a8a0c4aab5e7851e", + "format": 1 + }, { "name": "plugins/action/networks_cellular_gateway_connectivity_monitoring_destinations_info.py", "ftype": "file", @@ -2944,7 +3266,7 @@ "name": "plugins/action/organizations_insight_monitored_media_servers.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "f00b291cac55218e154f1a616d54b7b161a62b2b3ecae8c8230d958083a5bf3d", + "chksum_sha256": "a78fee7f9173bbb09045f8f675da6ce0cc733032842d7f97bef5b0cfb216832a", "format": 1 }, { @@ -2961,6 +3283,13 @@ "chksum_sha256": "bf097c20da889e0542a7b9ae5a6093d0cc5b7f9754520cb01f8a09a2a33ffaf6", "format": 1 }, + { + "name": "plugins/action/organizations_summary_top_networks_by_status_info.py", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "6ce90228e86212cc270de05fe2c7a403c0bfb037534238a9c2530f90c8aa3eb4", + "format": 1 + }, { "name": "plugins/action/organizations_clients_overview_info.py", "ftype": "file", @@ -2975,11 +3304,32 @@ "chksum_sha256": "feff4fec118241088262121c56270725899e89345016a4d3d09fbb26ce41f935", "format": 1 }, + { + "name": "plugins/action/networks_sm_devices_shutdown.py", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "46d19f779864fdc4c9f74f9a350073a23ff0945a13f9f4ceca4ff1ff15a8ead1", + "format": 1 + }, + { + "name": "plugins/action/organizations_wireless_devices_channel_utilization_by_network_info.py", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "da06645abd75fa702fcd6ecf30211b16c990927142e1d9a8043005bbba66ec37", + "format": 1 + }, { "name": "plugins/action/devices_sensor_relationships.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "2956f9f0f457b7d670abc82b1f633c42371d7ebdb9600eb3571cdd762f056644", + "chksum_sha256": "107a7ad0473894d0fa7afe0813ebb626795779498dc3be76297c69c1caf25a29", + "format": 1 + }, + { + "name": "plugins/action/organizations_sm_admins_roles.py", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "03602a4d45ae50c8a9742a5d719dfa234164020683c264bc2596290250bebe8c", "format": 1 }, { @@ -3007,7 +3357,7 @@ "name": "plugins/action/organizations_firmware_upgrades_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "f5dcac54482e2e3ff47346481ffdbde8a179da8d8637a9468ee8a885bf66b6ac", + "chksum_sha256": "71119f8dc746a01f0019f6cdb882b4458349df04dc8ff978f4613376f7da177c", "format": 1 }, { @@ -3024,6 +3374,13 @@ "chksum_sha256": "03fbaab470608a130029200acb30549852d667c556d62d4138854f48e9057433", "format": 1 }, + { + "name": "plugins/action/organizations_devices_boots_history_info.py", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "54249b782c50e3eef484523465887645e39c2b479b5078907b8548fcdcad0569", + "format": 1 + }, { "name": "plugins/action/networks_sm_devices_performance_history_info.py", "ftype": "file", @@ -3038,11 +3395,18 @@ "chksum_sha256": "2e8991c04cd6fda1cb94ae14df78da911327d784a929093c963682d08c81fb8c", "format": 1 }, + { + "name": "plugins/action/organizations_appliance_uplinks_usage_by_network_info.py", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "3fda8166436a1c7e26e8e09377f3c6482e5132e0210d76f28bcf57d3a5202acb", + "format": 1 + }, { "name": "plugins/action/networks_wireless_ssids_traffic_shaping_rules.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "0177417ad2b9ae510bc38b81d5da6734fe1d5a9f42ad2d9fff268093cc647ae6", + "chksum_sha256": "390dea9b990264455f875ce633616b8b35523a383bfdcc0a270fadfafae27a19", "format": 1 }, { @@ -3063,7 +3427,14 @@ "name": "plugins/action/networks_appliance_prefixes_delegated_statics.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "c786ae33e0a6909478edbead1bd5d33878e98dc406b91420c51f8c6b6cb38108", + "chksum_sha256": "a6c7e6b4997cd7e89e6f2f7c6f4a2c9476ea9a7b5a18382813210faa409b5f63", + "format": 1 + }, + { + "name": "plugins/action/organizations_wireless_devices_channel_utilization_history_by_network_by_interval_info.py", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "c53d2d58d9236ade201e436ad3842d8a90e754ebb735f02b74b3a019ecf16120", "format": 1 }, { @@ -3080,6 +3451,27 @@ "chksum_sha256": "e295d2f8febae898fb86c3fbd76e0ac337b3acfb9ab3f083f5a5bf0a7f641793", "format": 1 }, + { + "name": "plugins/action/devices_live_tools_arp_table_info.py", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "044ab01319420b7fb6f989a5435115918bd59fad7b6d705670ade10667efdc16", + "format": 1 + }, + { + "name": "plugins/action/administered_licensing_subscription_entitlements_info.py", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "a3eb4ed3c8e8e0216dd043ab662f96a329c027ac1fed4fc85818dda971ed964d", + "format": 1 + }, + { + "name": "plugins/action/organizations_wireless_devices_packet_loss_by_network_info.py", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "3fd18c0de2a06abb7835400c1ba03075e33a466110e24e3f1fc6d9a90208e2ad", + "format": 1 + }, { "name": "plugins/action/networks_appliance_vpn_site_to_site_vpn_info.py", "ftype": "file", @@ -3091,7 +3483,7 @@ "name": "plugins/action/networks_wireless_ssids_firewall_l3_firewall_rules.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "92c117daef3804f8b320636d0033fcab63adbd6ad26c73f5f63db40af06e13d7", + "chksum_sha256": "32f8451c462ab02cb325d00b4df6d594a21d2a7b3473bff2f2aba30da6a36a9f", "format": 1 }, { @@ -3168,28 +3560,28 @@ "name": "plugins/modules/networks_traffic_shaping_dscp_tagging_options_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "7df2bec103e4b830144f422734362db10904629bc848f2b4939ce3ed1b322fa8", + "chksum_sha256": "b5e0a3d536e6ef9ae1326a867515b97af60a15385304e00f9e063c8db1e03240", "format": 1 }, { "name": "plugins/modules/organizations_sensor_readings_latest_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "1b257b2b2381c0585e4d5be347a24bef2e250015070c04d0f74b381f92674339", + "chksum_sha256": "a5fc6bc7d92177d8a13ed17a567b34e94979bf5b26e26f1ac7d9bef6eebfd8c0", "format": 1 }, { "name": "plugins/modules/devices_live_tools_ping_device.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "064ebb292c3fc275b5fd6644d8aeefec943bc5168d4cfe25914114b0e38e3279", + "chksum_sha256": "30815d3067fe1b76fc5ddb55ee03b550888037f8c58736ac97c224e76e145d07", "format": 1 }, { "name": "plugins/modules/networks_appliance_firewall_l7_firewall_rules_application_categories_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "f3a0dc4ef122c66a371b08fb4a3650be0a6604d6d168e225144f849e1a307fd7", + "chksum_sha256": "c26e417d22e8c8c26c5385ee588279ba25792527f9e85e87a441a0708047f437", "format": 1 }, { @@ -3203,14 +3595,14 @@ "name": "plugins/modules/networks_clients_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "3936c7e542e66dfb06f95f26c16bcd0fbaea9eaa1d5d20ef08c670a94c124a48", + "chksum_sha256": "aa34c1a6a39e50d8a17a349b8682828e92907d14ef5ec1e12025f940f1dbc093", "format": 1 }, { "name": "plugins/modules/devices_camera_wireless_profiles.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "2de73c2a35ce6cf130d487d5b117cdc910ef8d2d4fc5ada83e6b0d927085964a", + "chksum_sha256": "ebdd60e3fb8190d2f7f85cbafdf2b3b958ba25cd4618aecc54417412c2c04350", "format": 1 }, { @@ -3224,28 +3616,28 @@ "name": "plugins/modules/networks_cellular_gateway_dhcp.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "867a6041d7b2caba7a3f32290e2c0e86ba14691ac44b0b873dbbe6a024d22641", + "chksum_sha256": "5edb81e13924d622e0420a4858c60e3b219afde0c8f13ed543ca95c199933e70", "format": 1 }, { "name": "plugins/modules/networks_cellular_gateway_subnet_pool_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "3a2a6c8e712a54557b4035eb36ccdaabc6c6117385888c2eab254bbafd71b1a4", + "chksum_sha256": "c9bc557aea3c7ada33d1039469728b0f8fc749bb6812430c4b3056658945a1ff", "format": 1 }, { "name": "plugins/modules/networks_cellular_gateway_uplink.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "e51cda06b65459e25800d3b3cbc3fc98bd6c6618de07f7128e4a686bec9dd50f", + "chksum_sha256": "ffbf86bcef19753b584da12f802331c09f1ad02807efacd7706c68a5afa1fac2", "format": 1 }, { "name": "plugins/modules/devices_switch_ports.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "6513bb6d4730a2cd7c9481f306e4cd7636a52f47196ed4d9ea56ed65a7d07400", + "chksum_sha256": "e1fef2bf286954a8d045d77864b71f0d5e92e3508691df05b1573d0bbeeb925c", "format": 1 }, { @@ -3259,14 +3651,14 @@ "name": "plugins/modules/networks_clients_splash_authorization_status_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "5cc27094b039827424d16121cb514252787b2124d7516caaaeb39dffc464340c", + "chksum_sha256": "bea4c21f2f0830debd77f5e731def5c119011d5f011154468a7b551c3d744e59", "format": 1 }, { "name": "plugins/modules/organizations_adaptive_policy_policies.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "ccb9c0de70ee8058488158e1afb8dc44b9aa843baebce5fd1de1fa1e3ae3da8b", + "chksum_sha256": "c08d72398b546992d34fe69030abac65e0c0533dee3bb5116632a7e03dbb9152", "format": 1 }, { @@ -3301,14 +3693,14 @@ "name": "plugins/modules/networks_switch_alternate_management_interface_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "d174c4fb3a3c3157b9084f234a27351380e3f1668e88f3c304ec403123c98e49", + "chksum_sha256": "1f56af8a6a216e5ce37669a1a2f52afe7ab9ace252e3cad1ed2e9186b9f6d3ed", "format": 1 }, { "name": "plugins/modules/organizations_licenses_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "8f70362bda2a579e09d80864b8ff7eb81739713a13618132a158c9e5d34ec79b", + "chksum_sha256": "6fad4657e60f96a189b6453d3591ffded2384531035bed3513429829437c2ef3", "format": 1 }, { @@ -3322,14 +3714,14 @@ "name": "plugins/modules/organizations_licenses_renew_seats.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "2b22ebb8ddcef19df781451ffb17edb9cd854e3abbac7940d0f6fea3d8a5209d", + "chksum_sha256": "7f237a7437dbb39cf9eb31badb5bd663c20615d5749433d7538fb7ee5038f546", "format": 1 }, { "name": "plugins/modules/organizations_devices_statuses_overview_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "b6a9ee1fe1069bee82210b00b8a414f2af69cef68bf51a1d535c907195031440", + "chksum_sha256": "fbd3d896033d72e4b2b8bdff36f3c3db4bef653e534d49803e3df262522e07e8", "format": 1 }, { @@ -3343,7 +3735,7 @@ "name": "plugins/modules/networks_wireless_ssids_eap_override.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "b7fef9eb732235cd74170006aace49c48b3a4ac5b46f06db44980a73c1968219", + "chksum_sha256": "defeb74b60a2b329cebf4085e1c8065163a31a67ccc700328f432973456ad871", "format": 1 }, { @@ -3357,63 +3749,70 @@ "name": "plugins/modules/devices_wireless_status_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "76e902c04fc2ac9bf60d2d2325c13943fc0ac602b5719ca96994aef1ccd5e947", + "chksum_sha256": "19ba106396c3f4c34ebed0f4e01776686cb3db1aa20e4e7ebd2230830010cfb5", "format": 1 }, { "name": "plugins/modules/devices_cellular_sims.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "37e3ebd9ef4457d6f2ce2f3fdaeab1f74fd8b32d2935f777ceb09d107b6d9abb", + "chksum_sha256": "b4727fb73215d373ce418d1eccd5b3889b1b6773681da5d5a796d114a33939d7", "format": 1 }, { "name": "plugins/modules/devices_camera_analytics_live_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "6ef5c25f9108fbb60436285fbe1fd8e89f6bf023249fe02276ebf4200db225e1", + "chksum_sha256": "b2772a55418f180a136e3ad34d6b9c02beed7ce510a4b7c895bb04702f2087d8", "format": 1 }, { "name": "plugins/modules/networks_appliance_traffic_shaping_uplink_selection_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "fe812dacb16eea7f7e4c13b670c4362982b8fc890af16fe5a5bf98928b027dfe", + "chksum_sha256": "7fdf0cacea65467934b9faa98f78b3d4e244bca0ea8d9a538c75396c17ea97f4", "format": 1 }, { "name": "plugins/modules/networks_wireless_data_rate_history_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "aba8abd1927311639fb2971032b591e1b0786b95b4b133e53b0fc59489bb0777", + "chksum_sha256": "bce284b4577d976c4f56ac94ffea0756c972af75aa1dc3e67cce7f667fb1769d", + "format": 1 + }, + { + "name": "plugins/modules/networks_appliance_traffic_shaping_vpn_exclusions.py", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "3a59af68dbc67d323783507b32a01fc4a7bd52af961c61f7cfdee998da36c508", "format": 1 }, { "name": "plugins/modules/organizations_summary_top_switches_by_energy_usage_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "9960307612af69edc2657dee80adb3c3f19b78bc381f7ddd690c64538d6c0ed0", + "chksum_sha256": "7f3ce4ff5f5bfbd88a3e9656e69d19697dd780889928405f88f098c919e686a4", "format": 1 }, { "name": "plugins/modules/networks_appliance_vlans.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "dfeec55f84d2d416589f229cbe617b4e0471066034405bd799aca97857b257af", + "chksum_sha256": "5d5d03426c7b66697d9687b25ffdb65b250f1f7be1f79d83ad24b5bae60db695", "format": 1 }, { "name": "plugins/modules/networks_netflow.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "fe5058da451f0c4ef06c5ef8f3a2d2e1a467127be8259b0fa0d9a2e702ba0f3e", + "chksum_sha256": "155f81e842f0e629a7a1a1187ffee82ce90d21fdf86c204fc04c42de5381b47d", "format": 1 }, { "name": "plugins/modules/networks_traffic_shaping_application_categories_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "e75797f3a11bfc017c02ee1e16b9ea26597f886811fa9088c50e54ca725011e2", + "chksum_sha256": "a86076b3df6886db7d567be394b40f10754d9f811f285f6dc9dcedea8f883f71", "format": 1 }, { @@ -3427,21 +3826,21 @@ "name": "plugins/modules/networks_appliance_content_filtering_categories_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "89fe66465c38b911395e5043a9d0ca16906f555b736b2e7f17ebeae1dc6fc2e2", + "chksum_sha256": "a045d4b8c67e6a2d0cf868c964b13587b6f3c430e3f2be09679a0907a0dbeb29", "format": 1 }, { "name": "plugins/modules/devices_appliance_uplinks_settings.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "889c7a4046c8c7fe16ef599f5d9a7cd1e54075f21fd3d46abef6b6eab72e1640", + "chksum_sha256": "609c701feb4eca12ce7c64d353539e0f966ca529e3e878b338777244c7e31a2e", "format": 1 }, { "name": "plugins/modules/networks_sm_devices_security_centers_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "e5eef605a55dbd8ed5b256f06347385636fcbf3803d8bf62e38ec16f7b3c5156", + "chksum_sha256": "60b80b9de9afaecd31f52d90ddb217284620db7adb7d5f6b1269af23358c5812", "format": 1 }, { @@ -3455,14 +3854,21 @@ "name": "plugins/modules/networks_firmware_upgrades_staged_stages.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "97b6a8858f074691a2713d34d90132a4886be486c44f9da90ac01034242c9dfd", + "chksum_sha256": "f6065aa8e69746a0b90c444520013884c249bb85988afcb7be129a166c692adf", + "format": 1 + }, + { + "name": "plugins/modules/devices_live_tools_throughput_test.py", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "3dfe810a698c866ee14aad49a261f9682abed00ccf34bc894a87557a28363feb", "format": 1 }, { "name": "plugins/modules/organizations_clients_bandwidth_usage_history_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "545948f2619a66dc6419fcbcd2160ed6c328e448e28933fc734cd45a16f21733", + "chksum_sha256": "a15a64ccc348b987f7ef9f81dc81c133f4035376a6f87c64732c12b800204671", "format": 1 }, { @@ -3486,18 +3892,32 @@ "chksum_sha256": "1514726f40ef0604845f011d2d925276bc0f4e6d8e188474b94c7e6415a60067", "format": 1 }, + { + "name": "plugins/modules/devices_live_tools_cable_test.py", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "39a8e99a2a7ec51be413f8277973d04299f58d8efd222df61b241b8a3063746c", + "format": 1 + }, { "name": "plugins/modules/organizations_licenses_overview_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "375ecc6b128d234a077143778b32f914ac75b6530ef034e955dfa8e0407f7998", + "chksum_sha256": "9500fa7c99f9bf926acad172f8631802f1b62c68701dd3d28d5ee14cb53fd708", + "format": 1 + }, + { + "name": "plugins/modules/networks_wireless_ethernet_ports_profiles_info.py", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "00cd9b022d48762e9b80f8945d4227d8cd51509e66d643d483cd9825cd1aa1f6", "format": 1 }, { "name": "plugins/modules/networks_appliance_vpn_bgp_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "e21328c96811b39332c7a258d40c69c76b434b7d7ce35d79cc29f6e8c13d403f", + "chksum_sha256": "c21655dee3e9f8ffa7ab356bf2531050d4212bbf3d2ebd66080afbbeccba79c9", "format": 1 }, { @@ -3511,21 +3931,28 @@ "name": "plugins/modules/networks_bind.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "9fcc457b0ea731c339d622345af9030d30bc5f3e7e2a8232b2afa8a39b5fb381", + "chksum_sha256": "db217505920e8764a6f136db97ea4f23921280066d461598c18b4ade8659d135", + "format": 1 + }, + { + "name": "plugins/modules/networks_wireless_ethernet_ports_profiles_set_default.py", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "4c4df6f02d04d11d2b0ffe0b2ca628965b896bc4480a2cda664ad866eda4388b", "format": 1 }, { "name": "plugins/modules/organizations_licensing_coterm_licenses_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "2de4ba21bbf32aa94fd1ef5357738d00f4943db805201cf44d32a26d3bc540b0", + "chksum_sha256": "361bf5a304c690517eb269c037993ad11f040fa81a79cc20683f88ed249547e8", "format": 1 }, { "name": "plugins/modules/networks_traffic_analysis.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "d1dd8d49b466d529f3e88cee4f897e50ad2383c3efbff847791bf6824744620e", + "chksum_sha256": "dac9d4db2962afdb42e2010436ae9972fe7a30181b551ff23539dae70f91798d", "format": 1 }, { @@ -3539,28 +3966,28 @@ "name": "plugins/modules/networks_switch_routing_multicast_rendezvous_points_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "2a61afecc1a6dea1ebaffc16b9c090cccc902112c73a1528b790ba1bf8991e8b", + "chksum_sha256": "326e893b5afc02ee02e67d82d3908a2a2992552cdf92b70a67c1ea42508dd944", "format": 1 }, { "name": "plugins/modules/devices_appliance_performance_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "660c01a047bc6723121ed254aacaa1e979a9e2d23b205866f6229ab48d1c4c48", + "chksum_sha256": "8ad6a4c6ef81e13e04fe5e151c6f61c4cfb425f1ad33e20b9a0e670fdaa92e1d", "format": 1 }, { "name": "plugins/modules/networks_wireless_ssids_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "755fadd97b24e1f10304a249aee212cf09247ed54ab5f070013d80e27d5e41db", + "chksum_sha256": "84c0a49bd3ac6a31e90467a902f6a4cd04236c36c246614eccdbb31e6f742b30", "format": 1 }, { "name": "plugins/modules/networks_wireless_failed_connections_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "883289ce69bb98f6e8cbfaf57b494ca727d61f77edb6a609ea4ee5d5be621ac8", + "chksum_sha256": "e293d89e440089153e257d5c6a1016aef0870aa868ad389a79fb647d9fceb0ff", "format": 1 }, { @@ -3574,35 +4001,35 @@ "name": "plugins/modules/networks_wireless_ssids.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "d7a406df268cadfc35d4b9ea4d97fc5e01c2c96a41fad83ad69266691335ba04", + "chksum_sha256": "714458405ed8e12bc45014ebd7cbbcd9a9ec1b7d0df08485b2c2376411bf0c6b", "format": 1 }, { "name": "plugins/modules/networks_sensor_alerts_overview_by_metric_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "8a78016e2e3d36d3b9fd33f40cdffad8b87b4f313c706b6a839e9b7fec85e961", + "chksum_sha256": "a9eb579b01e033f7b205b527e0223192f54d67e6e6f35fd834457d5bf4022529", "format": 1 }, { "name": "plugins/modules/organizations_devices_uplinks_loss_and_latency_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "18b4daefb495331d4b50baeaa16d3bb2c8717c93c17f756d728be4f9a5ace92f", + "chksum_sha256": "3dfbbe744cf14a62419331c95267cabd74f52c78bb4b5b1c3d8e552fe3c07f05", "format": 1 }, { "name": "plugins/modules/networks_firmware_upgrades_staged_events_rollbacks.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "615474b77d93c117aadbb69f4e0b1582098ce2e280b3940c0ba4df913962c90f", + "chksum_sha256": "f1da9dcc326317b8a8bc3188964c9b359f7a5624dc191465ff66c3b720764d25", "format": 1 }, { "name": "plugins/modules/networks_settings.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "5505ebd4ea1bda7c29b486608a82e8d8d11528e09893a6e02f4fbb812ef5b63a", + "chksum_sha256": "ba06af16df38a1efae925fdd5e22cd557de1a33a784cc16402e7e08d4662ab69", "format": 1 }, { @@ -3616,28 +4043,28 @@ "name": "plugins/modules/networks_appliance_firewall_cellular_firewall_rules_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "341864a544e92da5b82d72ea2ca932d221efb82c3bb00e8deba8f55ef2b22ff2", + "chksum_sha256": "709c891b9174b6473f12773751a6092a163a22f5ea3f14b4c3a27dd481fa83fc", "format": 1 }, { "name": "plugins/modules/networks_camera_quality_retention_profiles.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "dd774894772c982e80ecad28e555106a425f7175f907d7c0e37b74ccfe4128de", + "chksum_sha256": "89eb50683acae43db6435c8720dbef38524f0f8d759cd302a50ce3f6ef724bc1", "format": 1 }, { "name": "plugins/modules/organizations_early_access_features_opt_ins.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "57d8b5e730d3fb6947980ae75301535d31641597ffcdd6383ea394c14b819276", + "chksum_sha256": "c416ede7f6fbcc31576d7e1f2cd11d4907e924b82c9b973e37625dd3b14b62bc", "format": 1 }, { "name": "plugins/modules/networks_switch_stacks_routing_static_routes_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "a20f07f3ba844d2ec5af68a85698520698ace8264a99db9c6b7b1517e46c0fe5", + "chksum_sha256": "eea5036419e65041c86713ab77e14346dab49f1ca654fa22f3f2be6a142e5d49", "format": 1 }, { @@ -3651,42 +4078,49 @@ "name": "plugins/modules/devices_cellular_gateway_lan.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "95ba149b3f24f5caaa0491587237d4cdaf98ac6deb6a6e8e64834fda1e35f056", + "chksum_sha256": "06ef3c8893d4f1342189bdb7b9f6aacfc000dd9ced92689fd77cd54c6576bd55", "format": 1 }, { "name": "plugins/modules/organizations_alerts_profiles.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "7b1b8b828f1be97a16b29e722a3ff11ff670ebe81c15fa5f0466d84f5081eb9d", + "chksum_sha256": "3ad9e1eefa64eb82d78d28c76ac52bc473eafebaf636b87b7127ce486a64d720", "format": 1 }, { "name": "plugins/modules/networks_group_policies.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "8a802bd3ee92e312c14d9c8eb23a0b63d70c529836d9d61352e48e3941c3dedf", + "chksum_sha256": "8ac9f1c5cfba263076a0ae0a39cf39933e190ab040adcbec1a67a3bf10b92162", "format": 1 }, { "name": "plugins/modules/networks_sm_users_softwares_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "a981d5850d034688011362e58c29627efc0b3bb522704ad38f78206e382b6643", + "chksum_sha256": "8ba4fe1b7e544aa07a5dea7371079737a37cd40a49a5e8fcb3589aa14721d390", "format": 1 }, { "name": "plugins/modules/organizations_camera_custom_analytics_artifacts.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "2f31ed4ac03a70fb7c6baa37a36692dabc2cd3f41f4cd29358103c7612720b85", + "chksum_sha256": "f2aebaf1f5a819ed163f6305cb0f83521a9012026a3d13de7182f35221be51ef", + "format": 1 + }, + { + "name": "plugins/modules/administered_licensing_subscription_subscriptions_info.py", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "cd0aa3fb04e2f5fce7381a527e15b58d705da42ab5b6e554b1f97036526eb7ce", "format": 1 }, { "name": "plugins/modules/devices_switch_routing_static_routes.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "b800b9f10c1ae144afdb51eef92f4313a344d83ec5fc0b674970d16b359ee901", + "chksum_sha256": "d440a306761a3b5508222744c790bb9dbfb718ad2467afb3f06a3c5360573c31", "format": 1 }, { @@ -3700,21 +4134,21 @@ "name": "plugins/modules/organizations_openapi_spec_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "f6bdedfdb362032d7352bf09ecc773490cb66c6b0d7d7686e52a5c0d578f068f", + "chksum_sha256": "c1655098628b4bf35d7f7a59423d360df3550fd1dd797d39abaf4e8b548caab6", "format": 1 }, { "name": "plugins/modules/networks_appliance_traffic_shaping_uplink_bandwidth.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "a72aa1fe2a0d2cff90ae5eb8856521641a7832c677fcf84492b802819c6d7699", + "chksum_sha256": "8575b766cb62f81cf555dbfcda6385a68174aee19d316565b404f4849b1cc19f", "format": 1 }, { "name": "plugins/modules/organizations_early_access_features_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "1db0b91d80918225658932d4baf92fd924571d9fcc06f4775d17fcce66acaab5", + "chksum_sha256": "0c6c7c9b12e5741f9f548fb95d9d14bad7e62bb3167da00aaeb0fa7398dfa756", "format": 1 }, { @@ -3728,49 +4162,49 @@ "name": "plugins/modules/networks_switch_mtu.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "f44626c6600d29b6db583d5bde6e3da95e4b03fd3f24f9b00c710e90fe5c3d5a", + "chksum_sha256": "37a82d27e208b2ef35a5405441977d90a5ae72ed7f659bb010c5f324814a0b4b", "format": 1 }, { "name": "plugins/modules/networks_appliance_firewall_inbound_firewall_rules_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "a1ab2f33a06b43ec4119cf8ecd67c1dfba9366fb1b26a20c5f855e964d0ec590", + "chksum_sha256": "80b6a53439f8952633d68f6afd140546a8af8f4843fa985a4c4e1f1b08577a17", "format": 1 }, { "name": "plugins/modules/organizations_appliance_vpn_third_party_vpnpeers_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "e4b7ecd6c0cd100f5e6c26c573d25579bcfb7eaaf8cd92eeaeb50be9c865d259", + "chksum_sha256": "d2351293e2da3c17c50d51d94dad24c43629db41d79b69a46de325c4e49d0749", "format": 1 }, { "name": "plugins/modules/networks_switch_access_control_lists_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "b32728927090bf1efa352f8d252bb98756b0a286b531caac98b9f3b8516b9f61", + "chksum_sha256": "539ae6c810b5b7d3d99db3c01072c4b999a2376f0f0bd397b5b69ad110cd6585", "format": 1 }, { "name": "plugins/modules/networks_wireless_settings.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "9d5b15fc55e4f6ebf1d5b5dbbf69f083c6a936169dcd3721d52a84ea26608219", + "chksum_sha256": "daa99531f49ed65db1c80b6863016d9c6aa9f7b57c2970181b7b4d7d6cdbdc40", "format": 1 }, { "name": "plugins/modules/organizations_appliance_vpn_vpn_firewall_rules.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "bb4e4e1e6fb7af84425a8ea2616053ae84c75cde980ebdf17a62d452b408926a", + "chksum_sha256": "3521c9392f5b8e141120df4e37f65a27167726822530d8c9bc47b56f4ee11a32", "format": 1 }, { "name": "plugins/modules/networks_switch_settings.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "5ccb1ddfd538519f34098ca35da849c9d625c3d892103bebaa173bda73f6edfa", + "chksum_sha256": "1068f7ebc0381f0a941f5388931575c69c135bab254e7d4478c816c7cd76e299", "format": 1 }, { @@ -3784,7 +4218,7 @@ "name": "plugins/modules/networks_switch_dhcp_server_policy.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "2de12392f5cc7465d662eb7b648bc6e19b3729b32ba7372177bee60111975783", + "chksum_sha256": "b37c48ca51fc9ac0708afc8784c2eac1e8ab58937d7bab0871c80bd997f38c12", "format": 1 }, { @@ -3805,14 +4239,14 @@ "name": "plugins/modules/networks_switch_dhcp_v4_servers_seen_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "2f41db499cbb2d8f595f003201eacc7dbafd0a620938fcadee5839d9fec54303", + "chksum_sha256": "8a54a3f8851f219759dd55b3b74057e0bd765c12dc277b1d6c52d68a2f036837", "format": 1 }, { "name": "plugins/modules/organizations_config_templates_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "f6e5888017a9c645a986628f7f1a6b3ff945c4a7fdb9622532ba7c89a2546ddf", + "chksum_sha256": "9f2ab9db92c9cc8f07e299bc496ebac20f26b9299a96209ec65523aa33d1f477", "format": 1 }, { @@ -3833,56 +4267,63 @@ "name": "plugins/modules/networks_sm_devices_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "94ae7310071d6eb23bb9afa243be30f1afb1333395641dc2a0b06ed0f21e2f2e", + "chksum_sha256": "870e32976e2c102885696b50f57b8d2e73c5d5101887fda44e6ead32122af10c", "format": 1 }, { "name": "plugins/modules/networks_wireless_bluetooth_settings.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "7f7a61433d5f1a99e3e9dcf550720a490d25737664957a2f01b1120b531be9f7", + "chksum_sha256": "7e111eb0aec67fe655f65a2f3d70d5e2ac47859174c141a05f282974debbc066", "format": 1 }, { "name": "plugins/modules/devices_switch_warm_spare_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "aa12c28233f9d550384bb1707927ab5ab8ba84f5c6e1667d2681425ad282b16c", + "chksum_sha256": "6d365c087d200ce1ba4054f7609960463fba0d8ac0771cc0e3c35ac32983e296", "format": 1 }, { "name": "plugins/modules/networks_events_event_types_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "d6dfeae799a44c41e4db798c72892512649496aea92c6ac4c1d4473b2a0b0d2d", + "chksum_sha256": "50b4866c18ec67c8041cc86cdc8963c1cf62c90180365fdbc06dd9b77e84d8c4", "format": 1 }, { "name": "plugins/modules/networks_wireless_billing_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "b3cd0a8d09a348e6454b38a16db70b5baf3698b677a52898add5846ea1c28573", + "chksum_sha256": "7b1efef4c2adcb5dbec224bc7c0e9740ff90e02b5492156a0296ec99669d0049", "format": 1 }, { "name": "plugins/modules/networks_switch_routing_multicast_rendezvous_points.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "946cce1715cca52bdbb7edb9a926701c38cf048c3e15c05465731fcd7a7efb41", + "chksum_sha256": "45cf83c8279294f8932d4cdf2b1339d10f75e999063aebd7dae4ca6bf7baa178", + "format": 1 + }, + { + "name": "plugins/modules/networks_appliance_rf_profiles_info.py", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "e817ff913da88bbdc0c622af20211578a7545cc608457600b52706280e113ae8", "format": 1 }, { "name": "plugins/modules/organizations_saml_roles_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "bb76d341d13d43d0248f80496e793f5e935cb9d7d3c7c7114d4a3370a06cdf97", + "chksum_sha256": "91b1fd6f9c1d186a77861ae770eacd8ee0f7de7b195302f587947f8ae7a6661f", "format": 1 }, { "name": "plugins/modules/networks_appliance_vlans_settings.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "b847f35ec2b6ae47dcc61308642666106a094cebae78cc271eb340d6f7fc3231", + "chksum_sha256": "10371f80191842928c9b367369e7404abafb194b115e6bec00632073d29e550b", "format": 1 }, { @@ -3896,21 +4337,21 @@ "name": "plugins/modules/networks_appliance_vlans_settings_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "d2ea80510ad942ad3ef496567096dff3a3f2ce4fdc2969a1395a08c9c646f469", + "chksum_sha256": "74a29f6b91b2f60d63d1ce5c1801fad46c1306fb26fb97cbcb402a40eafc1c44", "format": 1 }, { "name": "plugins/modules/organizations_devices_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "c449e9d872dd09074ff99f931e400fa8891deb826483c4106953a0dacbb20105", + "chksum_sha256": "213435f8e5a5e5b4f823495b4df7a276fd6a5faa7aa2096233944756ecf1a9fa", "format": 1 }, { "name": "plugins/modules/networks_switch_link_aggregations.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "eb4f36261dba12d8ea2a8a4dce5301d2d815c1b76cd2d9b283b4b254959fa5ee", + "chksum_sha256": "e3d59ce4d4f894c31ad3f73f28f5d0c57f2126014929d04dc69e6594c7a50400", "format": 1 }, { @@ -3924,7 +4365,7 @@ "name": "plugins/modules/networks_appliance_vpn_bgp.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "fdd2f1e20b38593afda79ec186197dc7536905be85a69f955635fcb056c4cfd8", + "chksum_sha256": "5eec6f5864e46533427286cb747d7acf52e48c02769dad8cdfc30443cf4f6dce", "format": 1 }, { @@ -3938,49 +4379,49 @@ "name": "plugins/modules/devices_blink_leds.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "9ef902307643fcd6dead557175949dcf371bfd9660963cd091eeb25c1668a83a", + "chksum_sha256": "56eedd6b9ba24889480061090dbdd5ec7916d03ff862606680ddca4dd905ffd2", "format": 1 }, { "name": "plugins/modules/networks_sensor_alerts_profiles_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "0492b079ea59d6201255241f571e3cded4189027d531f30554646da43c948b1d", + "chksum_sha256": "c0a43e2204a15ac78f97d4cd8e73155c19a237fc984b3d98ef885f5601453908", "format": 1 }, { "name": "plugins/modules/networks_wireless_clients_latency_stats_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "89887f8c959c16ebace0b07a5c0111187a2d3773b2b466837de5e9f6be71b6ee", + "chksum_sha256": "8483ef6700c130313caf5b73bb58f018bcfa178fc8db6d0af039e3d84e5b315b", "format": 1 }, { "name": "plugins/modules/devices_switch_ports_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "23630fad3078fb334a5ee257b9319fc65dd80ee3f1ea3efb05c77d865dccc558", + "chksum_sha256": "2b3d581e96b439c82d09118e278159a2135a18a946b24a254b34042ac4849b80", "format": 1 }, { "name": "plugins/modules/networks_wireless_rf_profiles.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "54b5d61f4c3a6e84ab08726660eb201881666e4f6ef99ca2be627392cd164303", + "chksum_sha256": "f082fe4bc12b67c96ba6e67da13fac8652413dad5fffac7a232f6110dc54e2fd", "format": 1 }, { "name": "plugins/modules/devices_camera_sense.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "b8422cbdaf9d49e7f50870a176928864d78b38dc0a987ab8a570eedb478fd0a2", + "chksum_sha256": "c4b6f938752218111b047692b65744510514b7675e2f83a1f882abfb8ccd040c", "format": 1 }, { "name": "plugins/modules/organizations_inventory_onboarding_cloud_monitoring_networks_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "293c8a4a046429833582a37624bdb9b45ef0830265a621d59622e0d8422dc877", + "chksum_sha256": "481bc0b87c3118fa781ac26caf5b1fa13d9d06b57de044d17b9c5bb57b9721ce", "format": 1 }, { @@ -3990,11 +4431,18 @@ "chksum_sha256": "f3b66656c7baec07b10a4ae98526850ae28950cfc55272747cda6878857aec31", "format": 1 }, + { + "name": "plugins/modules/organizations_camera_permissions_info.py", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "6b682d1645e72d9ea1bcc3193c52af7e85cf1917c49336ff20181d565bcfe7ef", + "format": 1 + }, { "name": "plugins/modules/organizations_switch_ports_by_switch_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "87e8bb538140fa5af88c461f9ade99cc5762834f6f0d4f001c70e9b375023356", + "chksum_sha256": "04e349aa44d9a9deb1cb59543b5dd8ab5688a6ba81745a571c409cd1c7099375", "format": 1 }, { @@ -4008,7 +4456,7 @@ "name": "plugins/modules/networks_snmp.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "4c4e8b2c6480cb7865be1fe2a8356e3ae780c84feef39e85486177cd36465988", + "chksum_sha256": "4d15124f195ee18f5fe076909ca40d4c495816142088c5b3a4084ec6445a5a9a", "format": 1 }, { @@ -4029,7 +4477,7 @@ "name": "plugins/modules/networks_switch_settings_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "20104fc255c7318475f1ea66aaeb2dc1a569a3fccb88e0d8d837c7a22959c9a0", + "chksum_sha256": "0d5da453af0d124378f907d43d10f9a209fbd8fb906c22902122382f271c2239", "format": 1 }, { @@ -4043,7 +4491,7 @@ "name": "plugins/modules/networks_appliance_single_lan_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "74efa315cbecb5cec315d769c7a4ed50a6d4f0f49eac45eec2937787a8fef1a3", + "chksum_sha256": "84aa8f8e6f1c97dac76868bab79b54b92cf60ae0c458c4a1704f4891ed96bfee", "format": 1 }, { @@ -4057,28 +4505,35 @@ "name": "plugins/modules/devices_wireless_bluetooth_settings_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "5d60b9b543ed55838e03a740cdb9646209b338fde7fdea82689be8abf68d0aba", + "chksum_sha256": "ff6c14166303ecde467c93a28b9377842063101938357266b62e9c3f871e8e22", "format": 1 }, { "name": "plugins/modules/organizations_adaptive_policy_settings_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "8c4ee7752da4b6c29b1315e8e98f117b1fb3016c03bc6b66e7bebd9ab309320b", + "chksum_sha256": "19f4443507e1aaa9042e1a0264415b3a6aa7fa5c217c2bad0f50fe036bdc1966", "format": 1 }, { "name": "plugins/modules/networks_wireless_latency_history_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "6557843bac9515c53f3409a9aa2ac1afd2b3b1667a4c9a78086e886c1b622e41", + "chksum_sha256": "8fd3b39a24635059fce2780fa33a5e2d3689b05987f668e86d4ae6f17aa7515e", + "format": 1 + }, + { + "name": "plugins/modules/organizations_wireless_devices_packet_loss_by_device_info.py", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "14d4fc50c16044bea465c10a1fc9f7a535f80a97bcf9ddfcedd5fa5df3e2658b", "format": 1 }, { "name": "plugins/modules/devices_camera_generate_snapshot.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "ee3458fdf2d5bc56491b8d5e27809e5bfc8360bce8363a15dd325b8ebb161b6c", + "chksum_sha256": "c8eb4720ac5b4253336077706b82b331d149aff92c02b47b571a580c7d2684ba", "format": 1 }, { @@ -4099,21 +4554,21 @@ "name": "plugins/modules/organizations_action_batches_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "ac8a51e0035df076cd4178764ea689c485212b4a87fa70182c97e5fb803c8c2b", + "chksum_sha256": "4910c64fe07dc4f20468fc7136c161fa5249fcae4d9a3f84cafbd2f6b9fc377b", "format": 1 }, { "name": "plugins/modules/networks_wireless_rf_profiles_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "d7ae8631ac65f588e348eacd4cf2bd88561453886345307ce31c4ae0461b9dcf", + "chksum_sha256": "99fc47b792a2232b4f934ae4cb075d45ae1a6600db556c0b3f4560a6641e603e", "format": 1 }, { "name": "plugins/modules/networks_sm_devices_device_profiles_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "430094fb68eb8ae41196ac85f964865b7e1a0072214a5e2a8b3e5d2835fc5b8d", + "chksum_sha256": "d306a70b034fc3d93deda8f00b23cb2a0113c5be9b9dd8c0fb35d2e6b69b77ed", "format": 1 }, { @@ -4127,14 +4582,14 @@ "name": "plugins/modules/networks_snmp_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "26fa59e32407ca7f222de0316d70e3632113e89f488078ef0f4d25926e3fe552", + "chksum_sha256": "bdb03e6591c435ed57d185c1b362bf5298331b14ecbfbc3d092f85b7931e2e21", "format": 1 }, { "name": "plugins/modules/networks_appliance_connectivity_monitoring_destinations_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "f81375a37d8b4fe1c9c39d6510186b1ffd1a1a36b3e79ae450ef581f0ac1d538", + "chksum_sha256": "1dcf80863351729d8751568090ca72ffa220808d1263ea87f84e6a9b2a443317", "format": 1 }, { @@ -4148,7 +4603,7 @@ "name": "plugins/modules/networks_switch_routing_ospf_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "63a5ff2998f0d2cf348946685e2fa12e62261a1f6cc270a59576ba1ad0c5eab1", + "chksum_sha256": "eacf7bcecbe82c61c33a140b576f814ce6e8ea85330938d3a4c69d393d5c8f79", "format": 1 }, { @@ -4162,14 +4617,14 @@ "name": "plugins/modules/devices_switch_routing_interfaces_dhcp_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "38378f12279404c3946bfb5cfb1a59f395bf474a4829f8fddf1b8634d4e94f3c", + "chksum_sha256": "fcd699e1e7a2f720b2ca305f68e643a924657bc041ab816909084bad8a28a613", "format": 1 }, { "name": "plugins/modules/networks_sm_devices_move.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "d03654cf28ed7f46a81186b9c382126429bcace62a9e16bd4e561ce7c38d94f0", + "chksum_sha256": "637ab5634854df04a56b2d9304e7f224312f9d36d11a010e884988c726b80918", "format": 1 }, { @@ -4183,7 +4638,7 @@ "name": "plugins/modules/networks_wireless_ssids_bonjour_forwarding_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "7867180b47780a831a326e934a7d3d855b602e091a78e422575cc2c91d1f0eca", + "chksum_sha256": "1cab1978cff41180453056cd1eb3ddaf6f94e4a2bf33a9c0036537c78384b90e", "format": 1 }, { @@ -4197,14 +4652,28 @@ "name": "plugins/modules/networks_switch_routing_multicast_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "ee6b6524474ba8da7ef3a881c2641a531ac2b991f4d4dde730f6cf894636379f", + "chksum_sha256": "cec6d994db8a1818635c980ebcd2557b5ea8cc4bcb9bf069930992a455c6e273", + "format": 1 + }, + { + "name": "plugins/modules/devices_live_tools_cable_test_info.py", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "b8e01d3884bb18a49855eb0c9c73f14997a09244a82a74ea430950af6c673390", + "format": 1 + }, + { + "name": "plugins/modules/organizations_sm_sentry_policies_assignments.py", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "896dc2b817f292d099607892632d2177c67b07bf8dcc3343636cab2872e85c4c", "format": 1 }, { "name": "plugins/modules/networks_wireless_latency_stats_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "b3697d439c81cf564e1c7443688c4d3d7aaefefa5b29678be1ab0d1dd26ef0ea", + "chksum_sha256": "1215db505f60275468bd690cb8c8e8eaebd697e0ec29b9d581526bcb474876cd", "format": 1 }, { @@ -4214,39 +4683,53 @@ "chksum_sha256": "ddd8d144df6514dbcfb7e884aee9677c3c7921fed88d3e8cbf7b6917c695470b", "format": 1 }, + { + "name": "plugins/modules/networks_sm_devices_reboot.py", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "ea0a659b98cab35054afbd056c583c45d1f77eb7dbad680f47ad9d87293096b5", + "format": 1 + }, { "name": "plugins/modules/networks_wireless_ssids_firewall_l3_firewall_rules_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "86d6276968a137897c50efd1017156443a515b64df0174c4b2dd60a8010d2a40", + "chksum_sha256": "d29657f846ed28565ad384f636d1d6ebb5898b483e371f8fff6ba32ae21d135e", "format": 1 }, { "name": "plugins/modules/networks_devices_claim_vmx.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "cc077a5dd84eea2c62023f6b7c74dfc187960d55a120600a4c3b059f793c0d96", + "chksum_sha256": "7bb5b77819151a79a92008a7af2bfeae84b8e79d5cee8a5870a2a73eb22dd255", + "format": 1 + }, + { + "name": "plugins/modules/organizations_wireless_devices_channel_utilization_history_by_device_by_interval_info.py", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "3dad07bbc2498f4070c52de13181c7a81b861f8c20b45cea46321b48020f5b24", "format": 1 }, { "name": "plugins/modules/networks_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "aab12a6ff15c96ad059f371ea6b9b3d0bb96d2b1a361d5518e21c4eeaa84bdc6", + "chksum_sha256": "3e9b580e9d7042f1d388fdd492ef46e65c876c85c71324ad3af4a3f289c492e4", "format": 1 }, { "name": "plugins/modules/networks_appliance_firewall_one_to_many_nat_rules_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "cd2c164f01f039e5092493828345f552c886ea2a79cb82121bc3d6abd453c0ed", + "chksum_sha256": "b36508efee6f7d03414e02ea0c0e1f0f7e0a59049a68217c1470f08b2586b02a", "format": 1 }, { "name": "plugins/modules/networks_appliance_traffic_shaping_uplink_bandwidth_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "23813319a6f137d1efee534c878c7927eb03a0c761ae438f06481b684d7f3ebb", + "chksum_sha256": "2e1e781a89af4e5a0652b5772ee81a9f86a12f9f3302f80c4b82ef4628a04ee7", "format": 1 }, { @@ -4256,25 +4739,32 @@ "chksum_sha256": "86ef4b41902f15008d42b595cbeb5607645b933a8d38118732f7d05df40e6269", "format": 1 }, + { + "name": "plugins/modules/networks_wireless_ethernet_ports_profiles_assign.py", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "4b605946f3f9f886a2db6d4d64e5737ca006d5cfc08ca7edeefb6a6f89c4463b", + "format": 1 + }, { "name": "plugins/modules/organizations_adaptive_policy_groups_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "aee60229119c810a82720ba7ef2c72d4b0de0523a9acc36f0be701e94ba59fdd", + "chksum_sha256": "e2903a2ce50c27ee59f45ae70daeda2158f9fc8192f6c4854b824c69d1d7e43a", "format": 1 }, { "name": "plugins/modules/organizations_firmware_upgrades_by_device_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "1e82c7fae6c2a268ad90512798159aac30e96486d40f76a38997fef7e143a6a3", + "chksum_sha256": "f7b017553d6a6bb9f653ec7124d177da99b3156da92548079e13cad76a29995a", "format": 1 }, { "name": "plugins/modules/networks_wireless_ssids_splash_settings_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "5a1140e12c14ea780d3a07ef68ce61269031203227f2443092c8f6267b63a897", + "chksum_sha256": "d63f8c0b351b6833132c54afee4ae77f329a803a6866a4c078ee7449fe6d60a4", "format": 1 }, { @@ -4302,70 +4792,70 @@ "name": "plugins/modules/devices_lldp_cdp_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "98f4f6ec779c940300043ecb1f637222359207f20c078be857b4fb22f17534e8", + "chksum_sha256": "74ca5e7856aede38a9aea3a3c2af0cbd862a2d8f197dcf8fa01dbe719494dd80", "format": 1 }, { "name": "plugins/modules/networks_switch_stacks_routing_static_routes.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "b2ab9f92c9cf5b89ddb4539f253c2c33c5c1f4b6b0d601e7321d203360772e92", + "chksum_sha256": "e33edffc190e40a58e4a425af2fb94d562be44ce84af11b690bbb419fcaf745f", "format": 1 }, { "name": "plugins/modules/networks_appliance_security_malware.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "10846cefdb3843d456295ffa4949fd0133b4a9039d23094e422b9da37d5110ed", + "chksum_sha256": "17f8995ecd9ca30023673e08f192455fcd8406b62e30849633157aa3b7d3f3db", "format": 1 }, { "name": "plugins/modules/networks_switch_dhcp_server_policy_arp_inspection_warnings_by_device_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "5e44c9d2b84aaa575fef7b3c8975552531210ac324a6e3dd1aa41489b70b0e85", + "chksum_sha256": "3f6cae60e3bd473e8fc99a79198856bba1ce3d29168c2a984a271e3e8b944dbd", "format": 1 }, { "name": "plugins/modules/networks_clients_overview_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "4452586026214676b6c43ab7a7cd217c7f96633f5149cb3c5bd83347b5d26274", + "chksum_sha256": "16025a08c4648a34bd9897793747b4fd3033fdff011b09e1afed8c461bc8555f", "format": 1 }, { "name": "plugins/modules/devices_cellular_gateway_port_forwarding_rules_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "6925ac9f999541153b08993354014823c52370d10371ad44cc2f3cdd234622c9", + "chksum_sha256": "376f466b278b23bf8121f46514966c9bf9938b03c430c994a60a661539571e47", "format": 1 }, { "name": "plugins/modules/networks_switch_dhcp_server_policy_arp_inspection_trusted_servers.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "d551a027c41f86f27cc666a254f7cc8dde81e2a6d1d160fce405314bb608f437", + "chksum_sha256": "6113dcefb731bdc58134a9d3163e9b8278f9c7c0225837be088e61647ad9e173", "format": 1 }, { "name": "plugins/modules/networks_sm_target_groups_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "681175fdce3caa51878a8b8bf5902f006fb1aff2fe8f96d9994f88d3084676fa", + "chksum_sha256": "57fb8d5a92c2aacf97d96d6bc10b567ef98634c5ec3b6b2cb93ca56a7b31af76", "format": 1 }, { "name": "plugins/modules/organizations_adaptive_policy_overview_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "4ddd3e2643154bab72ea6455d2fea5892f3b530ecf4364c963271d29ada146d5", + "chksum_sha256": "40dd304a36a38c0288e089bb7364e869fc1cda2362aca1292efca41544e7ea66", "format": 1 }, { "name": "plugins/modules/organizations_saml_roles.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "017e596d5e2c299edea7569e4b014a8e50c2c340729e13f2890c142617061f1c", + "chksum_sha256": "6f4400141887e5eeeecdc8ce2250113de8d85618557c73c41cc4421b7367ff98", "format": 1 }, { @@ -4375,25 +4865,32 @@ "chksum_sha256": "aa53382d5c0284c73daae62ffa34b45b3ec9faa5c57627136d5db0238cfe2db4", "format": 1 }, + { + "name": "plugins/modules/networks_vlan_profiles_assignments_reassign.py", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "74ada7cdeb62462c32a4f839187e4d2da96cbafb505ecfbc971cb69bf8bd58e8", + "format": 1 + }, { "name": "plugins/modules/networks_sm_devices_lock.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "49748bfba72e76c037d14667b202e78baf4e23a37b863d8e30d30ea32174ff3f", + "chksum_sha256": "e833a24754c18959f1cb95eb8b3a988e554015019633f444788d4112fc968864", "format": 1 }, { "name": "plugins/modules/networks_webhooks_http_servers_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "a66cc99b4ef501c293172312f2ba0dc57bfce2024ec9bff8be314d6a8bc86287", + "chksum_sha256": "2d07726669e12a782b98e8e2d4cabdb20fe340ef95f5512e0c9437530930f1ec", "format": 1 }, { "name": "plugins/modules/networks_sm_profiles_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "751811c0d7b8c037f3c5cc53794c7a0b688fe47543a410f6b27c5bc38d931e08", + "chksum_sha256": "ffb67d3148943a3653c341c1cc5cd249efceb70453f32efcce622e2738d17ff2", "format": 1 }, { @@ -4407,21 +4904,21 @@ "name": "plugins/modules/networks_switch_stacks_remove.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "fe3cb0cebd918d26e93a49a98d580f9cd8402caf3e3381cff69c5032b282774d", + "chksum_sha256": "3f8965074ae7422cfaaee3fc52e68e89d441ffa4d7aa95c0dbabd61251948eee", "format": 1 }, { "name": "plugins/modules/organizations_clients_search_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "c7cb68ccbca67bcb1adb452ae9577abd2fde169cc04990001c2aa376e6a07997", + "chksum_sha256": "a924efb8e72c53a68173732fc168e3e8d0478df3db5b3f27e6e6fe575733afe4", "format": 1 }, { "name": "plugins/modules/networks_appliance_traffic_shaping_custom_performance_classes.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "df36953bfc0d394a36dba7ba99ee01af177aa698347da9af8e8fa73d6c0f4bcd", + "chksum_sha256": "a0e4238c30186d891fcf6f12555de7a445116c2b61a854da6bd02bc7f55678f5", "format": 1 }, { @@ -4435,28 +4932,28 @@ "name": "plugins/modules/networks_wireless_alternate_management_interface_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "936a15f3c4d22a8cb0402b4a07c4bcb7fd27ef15bb027930b10c67ecd98aa38b", + "chksum_sha256": "68b5e1701e3fbad8093b390a644ada854fd29c7db57c284e80191e63f73283b8", "format": 1 }, { "name": "plugins/modules/networks_webhooks_http_servers.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "79e54e69fef60d631ad2fa4a13b384e2ddd1681396a37897a7f9914bb670d184", + "chksum_sha256": "e8c67e04a2be2ca21acb669943fa681a95c85c775e4551067ebb0f3d73c095f0", "format": 1 }, { "name": "plugins/modules/organizations_config_templates_switch_profiles_ports.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "3c9a56e543f5411737509b02afb5dc7644405de800920b4c45e88683cc88c33b", + "chksum_sha256": "4e23f9215bc7507b9b80c18d3ec65c597beeefa4caa65d999e1cf3f01091ddb9", "format": 1 }, { "name": "plugins/modules/devices_camera_video_settings.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "b9830c67e320da7dbdd67c653bf97c8a56fa1910400489cc01f6a0bd07401b67", + "chksum_sha256": "01d3e4a815355ce9f27d49dce73fb39950469bd27e0b850cbd40b0cbea6a3a2b", "format": 1 }, { @@ -4466,11 +4963,18 @@ "chksum_sha256": "730f6963e91ac923a40e1a10f8e8a57d9bf2121fe777021d3dfb13bfd9b5ac02", "format": 1 }, + { + "name": "plugins/modules/organizations_camera_boundaries_areas_by_device_info.py", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "14793761234efc01472d4933073f743928bff12f9e39333bbdf76f854bc703b5", + "format": 1 + }, { "name": "plugins/modules/organizations_early_access_features_opt_ins_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "9bb6e8491e2dcbe1d299c01b731bfb6391286f8fa6d88eb1bf604d8ad1411529", + "chksum_sha256": "8e121e925c9eed38c4350ec641d87963322a3236820f242269b508d3911a6430", "format": 1 }, { @@ -4484,21 +4988,21 @@ "name": "plugins/modules/networks_wireless_mesh_statuses_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "8c5e51ac58d950cde23f81b90b2ba6d862cad86096db9e00330e44122016000c", + "chksum_sha256": "bacbb95a9869d3f0f9df4597e0fc2f1ecb95a707ac37c9386321192d4bc0beff", "format": 1 }, { "name": "plugins/modules/networks_appliance_traffic_shaping_uplink_selection.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "f43c510b853ed5539069c1a0f3711dc28a75f3c98e8d16964d4a75cf95d0b9d7", + "chksum_sha256": "a2b272df4cf020fb08e66c5365da1a7170ca6a3f73d6e3a32b827460f0acecac", "format": 1 }, { "name": "plugins/modules/networks_sm_devices_wipe.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "8fc551e656e4a18d8a6a5a98525d28ef6766eadb3faf7a5b1ac6bad96d61f8b6", + "chksum_sha256": "7595f4f6547c159b831cc548a79951b0ea58e7fbaea052613802c53d60bacd12", "format": 1 }, { @@ -4512,21 +5016,28 @@ "name": "plugins/modules/devices_switch_routing_interfaces.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "98777571178be389bfb3d5315c63e5a041b46ba95d334d2f92ff6265d4ebc8a5", + "chksum_sha256": "3a4916f4922b5d03f9d4350184b43280bff343344eb0b62e1f64586c51176603", "format": 1 }, { "name": "plugins/modules/networks_wireless_ssids_bonjour_forwarding.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "1856a26af8e657a7caced76e85730349783cc987802c3a801f19e8832eaa60ba", + "chksum_sha256": "f1629e842bdd653d3ecf616e393a580fd76319c4a9c47bcc98ed79e30c7ee8ae", + "format": 1 + }, + { + "name": "plugins/modules/organizations_camera_boundaries_lines_by_device_info.py", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "b71b911ac4363a33780dd64a0cad87be6f0ea2074b17ea3fe64a107cdd20b8bd", "format": 1 }, { "name": "plugins/modules/organizations_adaptive_policy_policies_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "4115e20d8f9cd9a9940a0f05157da1822ced3cfcd283ef1a450679176223e9aa", + "chksum_sha256": "7a71b4520b803552613295aefa7a89280258f38ac1c045c3a9c03f02c20115ef", "format": 1 }, { @@ -4540,7 +5051,7 @@ "name": "plugins/modules/networks_split.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "4fcaa28f4b81e9eb7caff90a607f1d9aeec17f817ce8e3af941454f56a5e4676", + "chksum_sha256": "5472f0460469275804fe8b366bdd2000f8f57eeeb8d1eaccb6103d5150756d2d", "format": 1 }, { @@ -4554,28 +5065,28 @@ "name": "plugins/modules/organizations_inventory_onboarding_cloud_monitoring_prepare.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "cfefa4522938d41a07dfa8a8a774b99a9d634037c1bf545ae5d3166c96834344", + "chksum_sha256": "a6d279856c845f0015ea7d3594413924a272d901dc1943646807abe76b147914", "format": 1 }, { "name": "plugins/modules/networks_bluetooth_clients_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "42fd9dbcd146c383b6367d954a6f1c4cf0a3cb0488dd8e5dae320aad86dcd01c", + "chksum_sha256": "f1544b7a78f099c0403f72042a1176d64d195e2b0b53379c4ac11ee42de3639d", "format": 1 }, { "name": "plugins/modules/networks_sm_devices_desktop_logs_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "0287346b3adbf11769971a259fb4fdf2a3c79a4ea35d37980fd06c1db2d69850", + "chksum_sha256": "ef49fd089314a0a785175d6475683daa6a23d29b246bcc446b6ae83b693a6e28", "format": 1 }, { "name": "plugins/modules/networks_wireless_ssids_traffic_shaping_rules_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "5e020bc9ca03c33c28acb2536bc6f267e0d387660693b971386c420b221694d1", + "chksum_sha256": "66e566bc7b1a692e462c3a30ac90d04e2728547505b2de5d4eac28ce140e7b5b", "format": 1 }, { @@ -4589,21 +5100,21 @@ "name": "plugins/modules/networks_wireless_ssids_firewall_l7_firewall_rules_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "380196a73190e001b6482d1bc42ace339bfaa667b1710ac18c30d4435f830efa", + "chksum_sha256": "6f358d330e910d7e5e43a65740faacc81fab3c9bafa37e0a40ae88579bb1d425", "format": 1 }, { "name": "plugins/modules/networks_wireless_clients_connection_stats_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "67776161ff61f4404cc5fa5ae721ba7c521f5332d5ccaccfd27864a8649b21e5", + "chksum_sha256": "d5de135b9eb13c543b34d18ae8a5d9fa0d8645dc3de458c2509b0877cb0dd6a1", "format": 1 }, { "name": "plugins/modules/organizations_summary_top_clients_by_usage_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "edc8ab3705a85acce648c64de4b1c5294fc163264f865e5a24cf56a35ee2d7c3", + "chksum_sha256": "1e52b21b661050f03a93c60dcb93e430021f3c29c2b99d54b2fc891ca50bc60e", "format": 1 }, { @@ -4624,28 +5135,35 @@ "name": "plugins/modules/networks_wireless_channel_utilization_history_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "9b7ed816c142653cef4977c41c27e133e54022119910950755e3871ce46277f6", + "chksum_sha256": "f259a09f68f644f978964b145cc00eae574138810f0b9f67f9501c26f6f06d8d", "format": 1 }, { "name": "plugins/modules/organizations_branding_policies.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "a2f0c6e67f78ee5e35f640ec181f6378aad787cfa91bb3413acbcde42ee5b2f2", + "chksum_sha256": "e9df6bb20a8782fd8fb665ff7752980d2dde0df588e7b1df7c8e58fc964b2579", + "format": 1 + }, + { + "name": "plugins/modules/organizations_wireless_devices_packet_loss_by_client_info.py", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "34f4c55f9ea227ce10718a21efe8249732bbd012789b61de96cbf8a438694ec3", "format": 1 }, { "name": "plugins/modules/networks_clients_policy_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "470ddbdbedf596e494b3491a535daf29538d36d3e158b44a667fd8b4ccb7343b", + "chksum_sha256": "a17bbed12f9f9af892abb451ace258d46a68b997c9cd5ae7dcee328fa9f7e656", "format": 1 }, { "name": "plugins/modules/networks_cellular_gateway_subnet_pool.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "61bf65ab9dba6fbaca67c2fa1e47b3c404b992e24cc2e9a4d2a70d661b46a85d", + "chksum_sha256": "8a0e9706fb011f9277f75e2841f647d5a361070058f12d5295599eaf0581c799", "format": 1 }, { @@ -4659,28 +5177,28 @@ "name": "plugins/modules/organizations_summary_top_devices_by_usage_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "f07a9e7dcd0764c5d99810d4d38ca70ff12b2c96e911127aec176394a6ac03b3", + "chksum_sha256": "5c808fdec2f9e7991fc892aabc9b698d636d60a96c1c11d3a1103131f28a7ab7", "format": 1 }, { "name": "plugins/modules/networks_wireless_ssids_identity_psks_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "f2a25a4bc32413f89c9f311ce672305ea0ec6f46aa0ddb562bb6d9a8d5807253", + "chksum_sha256": "646f5df95c9b8986b3afa65b578f7e6bfc9f4a0e095d669e7dd04a531dfeea88", "format": 1 }, { "name": "plugins/modules/organizations_camera_custom_analytics_artifacts_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "0828135910c287a1e4b27e3aa4a17f0d3b2c0fb20ad752fac1d99ba54c8a0638", + "chksum_sha256": "7fba046945739c9a4ed14beee37ffd03f14cf8b8e5a1d85933048e40ec229035", "format": 1 }, { "name": "plugins/modules/organizations_admins_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "f47ef023ac4f8b540d2f93e375a5007df1cf472a36d526d6c51f43bea7c7d23f", + "chksum_sha256": "e36532e2919a516852c709a7e78347b773e5a3d0d82e92dab1c7fad03f299fef", "format": 1 }, { @@ -4694,21 +5212,21 @@ "name": "plugins/modules/networks_policies_by_client_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "b07ee388ad2788b64f5f2dc073ae42d17fc2992392d2502b95346cb65ced81bf", + "chksum_sha256": "088d69e143ab19cee336d1806a887e086707564b473b56d54b2adba99077a40a", "format": 1 }, { "name": "plugins/modules/networks_sm_devices_device_command_logs_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "4a3d44eae2b64f299e8593980235037908c36f9e83242e84782f8b3f1de60a8d", + "chksum_sha256": "49f611999f1de22e4dea4b16ed3971b6ae104c4003a2fc78ffaa8c09df041d88", "format": 1 }, { "name": "plugins/modules/networks_alerts_settings_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "bd728efd350e2497489c549e1d40ed19bdf1fa1284fb798a972768af51a4734f", + "chksum_sha256": "a4865146a64588dfbe2df2a10b83479b82bf6344104284dc7b0b416132fa63ad", "format": 1 }, { @@ -4722,63 +5240,63 @@ "name": "plugins/modules/devices_wireless_radio_settings_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "cb8b20babbc7b2d9142dec0caa623575584deca67ee0317cff47a5243df1b15f", + "chksum_sha256": "3cc1aabbfb001e011c79185aaa281aecfd303c9b95caac99921f9dc3191ff900", "format": 1 }, { "name": "plugins/modules/networks_appliance_warm_spare_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "49e43aa22b709183026e375cdcd327c0962ad223b5e0e38d33e46f68aa70bbdc", + "chksum_sha256": "452223aa02320dc04fd71bd2a7d9f6c59b4b19e4f5e47c1b5cc008f7b6d0f44f", "format": 1 }, { "name": "plugins/modules/networks_switch_dhcp_server_policy_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "9cf93056ae056637a8ad904abf330b7acac72906b8c608816cd3ac7d4a82a22f", + "chksum_sha256": "c681b3edbebf3b8477b4187346bc063cc1e1eccb4dbeeaac6f10f43dfbe53058", "format": 1 }, { "name": "plugins/modules/networks_wireless_client_count_history_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "636cd3862b2ee877a3d56d3e43a020be5a1056e6798562b84d75a2b41625fc4b", + "chksum_sha256": "bcca66e9ff358948f8320caf2e7eb1e62a65d907f25eac0876637610748befa9", "format": 1 }, { "name": "plugins/modules/organizations_wireless_devices_ethernet_statuses_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "8e4fbe927b0c6ccda76c8a6a0b5fffaaa15fa915197c1f223e2d6b1dfef2bebb", + "chksum_sha256": "8b79c87fd5b80d4dbff09f09f0c6aac309692b19c19299fe4d136ede3aacc342", "format": 1 }, { "name": "plugins/modules/devices_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "5f3ce5d75286e16b0cb6fa79344363f3d44f2a0bad18382a3cef76ade9e6c54a", + "chksum_sha256": "334c7e7fdc880f316a6423a46aeeb7c97276988f7e7f8e199abe7a39fe46f55f", "format": 1 }, { "name": "plugins/modules/devices_appliance_uplinks_settings_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "4dc5e3e4c41b3f897fadec77c96cebb2fc503b66ea496a5166c7cb6a16ece283", + "chksum_sha256": "4323c8e9276b449ec4418df876b4b3a13dc354a67e34814e45ad7b64e2b04726", "format": 1 }, { "name": "plugins/modules/networks_alerts_settings.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "07a2d6b24d2c35866e1326cd3a7e04a7cf068b972b7cd98819bf449cf32c32fb", + "chksum_sha256": "f55dea26b1f2ecebdd613fa1d1e5ec7a5b2934fc8e4c050e0e29fbc04b75dec0", "format": 1 }, { "name": "plugins/modules/networks_sm_trusted_access_configs_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "495fbadee85b4d0d986fab94401de3fb84d756352b12267184fb3ad11a1d4ba2", + "chksum_sha256": "3f4b6d3a47ae8588f20fff2a9a7dab12c2850ed941aa3d8e60dd3ea08a44de60", "format": 1 }, { @@ -4792,112 +5310,126 @@ "name": "plugins/modules/networks_switch_stp.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "5780ee51a6eb36b31bc9b1e83ded4f24e60d4593b55cece1f391a743fb50f0fe", + "chksum_sha256": "1ea4988dfdcb92cba570261b559971fa2894bc1bb57a376834952aa0f083d669", "format": 1 }, { "name": "plugins/modules/organizations_licensing_coterm_licenses_move.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "575035dbb40f7a4e78e1e35eb82af6e072b2d7f58192067b39cd28dfa26da106", + "chksum_sha256": "aecf0d50a5973d1b4a23e398a3be6e99388b4dc23fefcb43d9621bc035120450", "format": 1 }, { "name": "plugins/modules/networks_webhooks_webhook_tests_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "fc6612df2282af8fe477be921526e8176d5d48cdf02043b8cc251e442fd20344", + "chksum_sha256": "8c65003ad9964aba51d5593e005aae7b8d60cb467f297f999d8e1ab35ed9289b", "format": 1 }, { "name": "plugins/modules/networks_firmware_upgrades_staged_stages_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "7baa545e768680a35f8f932f29243d90a6daf1f591bd051b4034d45bf5b02a03", + "chksum_sha256": "de3dfa5e7f96b6ff0733a02f9c830c673085457d2f475beb55f233c460b88afb", "format": 1 }, { "name": "plugins/modules/organizations_login_security_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "cacf70bfdc1f62e92e4d8393d2fca47aacb5e5458fa205a80823357d9fb2ed67", + "chksum_sha256": "45743ad76fcd4b1fd4665e1a6119c392cbe36298240ca400b7477f9aa08b85fb", + "format": 1 + }, + { + "name": "plugins/modules/administered_licensing_subscription_subscriptions_compliance_statuses_info.py", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "8b9b15e216d8d9d796c1bcdadf902dee41523ae74d563053118f6b9bf3cab0cd", "format": 1 }, { "name": "plugins/modules/organizations_summary_top_clients_manufacturers_by_usage_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "abb0197d8dfae662003e24c2fdfdf639f3e2726e781b1caba3ac680a62b14f02", + "chksum_sha256": "a4bd210bba505976dd37fcba59087accbed7714e105603e484a9fffd4c005bb5", "format": 1 }, { "name": "plugins/modules/devices_cellular_gateway_lan_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "350984a9b13325440f31e91efafda21f66b4047f0de970844c0c4e71caa66691", + "chksum_sha256": "14175bbd0dca4f364d2a95d46f044990a7db4586a634b4df15fe2efe5e6afd18", "format": 1 }, { "name": "plugins/modules/networks_sensor_alerts_current_overview_by_metric_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "203a6b56021cd0c10662b59d31bb8384613781d0f1f4bd757d2aeffc1c6660e7", + "chksum_sha256": "69a31868a14f793a75befa3b7c64654e060d4f01568608ab8adcd8f2854b5c89", "format": 1 }, { "name": "plugins/modules/devices_camera_custom_analytics.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "2037c313b06f92a46b67b740ab459e962185859fa489766f06a753fa498b85e2", + "chksum_sha256": "25d00850e59d3f316565c9e8f4e4c1423a723984a15b92f4afbc60c0d65c6041", "format": 1 }, { "name": "plugins/modules/organizations_adaptive_policy_acls_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "95c84605e2a7b19206b64821569e4e10a9bb4d682fdc73e0b6c190686b0fa7a3", + "chksum_sha256": "835feac90ee37a24ee62dfd086173b94b1d86a1fa3a4acff879ef65e15754704", + "format": 1 + }, + { + "name": "plugins/modules/administered_licensing_subscription_subscriptions_bind.py", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "134141674d881af00fc490349ea20e7a31184c598368d6867d6da7cf1931b401", "format": 1 }, { "name": "plugins/modules/networks_appliance_firewall_settings_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "bbab1f08ef27465f2d982439a00cdd228eae958a1386fb15c260fba70b87e775", + "chksum_sha256": "31339aec5e0a77644cc1b13fc4026d014092b97651ad56dd25415811fe4038a0", "format": 1 }, { "name": "plugins/modules/networks_switch_mtu_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "12b6b0afc42ed9cc260039c1c1a5f93e83e7803d25b6574fa046854ee38b0cc9", + "chksum_sha256": "d24cd71b5df8b3963b1e7c1bfb9cbf527ee323cea25aba8657c3785e7b571dac", "format": 1 }, { "name": "plugins/modules/networks_netflow_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "95d1a58f93b47952f3314b2973ff4867a5056f63c339be7ca85c58d348034311", + "chksum_sha256": "5826430d5b0f3bb9caa1bd3800c44701d7937e07f913189f71eb746509d98922", "format": 1 }, { "name": "plugins/modules/organizations_saml_idps.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "96c785a6c6c015a539197c4db9de55c115a91de02fffc923052168aea2e100e0", + "chksum_sha256": "f32ff9dbb000477470516b55e6bc1f450b4085dc447471f9c086d68b33903c7e", "format": 1 }, { "name": "plugins/modules/organizations_config_templates.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "652bfaf6f41532fceaec31025c3056a39119953209302aeca501db0731561f48", + "chksum_sha256": "224cc6bff7bf309348257058a8779a686bd91ada77261f8e50b0abd0643c4fdb", "format": 1 }, { "name": "plugins/modules/networks_wireless_ssids_schedules_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "5ef03ec07400e013311eb0da7d593dad7a267bec5f02747f149a09889f742e09", + "chksum_sha256": "74217d5f666904654d992de9c17b8c8cf4c6975b0fc4cd933aa6e6579780179d", "format": 1 }, { @@ -4918,105 +5450,112 @@ "name": "plugins/modules/networks_switch_port_schedules.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "0d37dae408dc1ccc85964e89d424e16637386c87a3b17524feef1c19c65392ce", + "chksum_sha256": "53c9d55c55e7607b6bde9d98f248f6eb1393e6582d46197a860a81faf7431d66", "format": 1 }, { "name": "plugins/modules/networks_wireless_devices_connection_stats_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "93d84387781f4d12b21612778c4e570abe5dee6303a36e43b1411cd744f7e40b", + "chksum_sha256": "808087abf6c73ad8c7b58986077aac05f7c3da07dde4535029cfa37c68b91018", "format": 1 }, { "name": "plugins/modules/networks_appliance_prefixes_delegated_statics_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "5090de65215835b66210179b1cf552094832bdec7ff222ac40a6867a8ccb4d7d", + "chksum_sha256": "f9462890460a6712ee2e323bc3e365119554ac2b0c81cefb155c3a161da84273", "format": 1 }, { "name": "plugins/modules/organizations_policy_objects_groups.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "49e96eb0efbc3ce4a2eae2adac7d01673626b7a2c9c0b0755fab3c498aa11cf0", + "chksum_sha256": "d1b5256e789f17265810ea32bd4b856963ace83341d08506aaaa4bd5fd991f94", "format": 1 }, { "name": "plugins/modules/organizations_sm_vpp_accounts_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "1ee62f203fab6d26e761379f1a994d3ce60446cd14912004a043de5f65bf3681", + "chksum_sha256": "239685f7ef2caa0549a9320c296a2cff0310b9fb82176cd5f10edd0453e7eab1", "format": 1 }, { "name": "plugins/modules/networks_settings_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "4e995f911b9b20b9abe417f5980f472c8544874e1a95a5bca9579fd7901476a2", + "chksum_sha256": "bed4b4a0cffbf7a0ac047e2ba69536c2a52fca418cc58c95818c4bffdb2bc151", "format": 1 }, { "name": "plugins/modules/networks_appliance_ssids_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "7043a6e3fe2d0f0f8a6fa9f53f6fb0fbae22486f5fcc241ce1527ce0f610765d", + "chksum_sha256": "07c642cbd4dea66e1d7f722e475df7b6a1f044bc87295f5a5d11eef772a32db5", "format": 1 }, { "name": "plugins/modules/networks_switch_qos_rules_order.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "be0563b1a3d09201413b8894ba597bf71781923d49d30fae10c8c0318e9a1b1e", + "chksum_sha256": "0bd0f2f65f22e1a16f87266fc665a50d589522227b13d1220deaa5410c85d201", "format": 1 }, { "name": "plugins/modules/devices_camera_video_settings_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "0e86c3ebb48e126d12e7b6ff3cafa993d8c807ef907a1a4961be05b57c32f715", + "chksum_sha256": "e929514c4f6046f238eccb7850f965b6359f4b38730f2b5f661534f13205fd1a", "format": 1 }, { "name": "plugins/modules/devices_live_tools_ping.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "2045bee53c6acdcaf7723d891d465cb35e946b84bf1423f612e00265d37ca3df", + "chksum_sha256": "15404bacd0aabadad171b09c4bd78fed50f9cb00646ecb4d81a6938788e72400", "format": 1 }, { "name": "plugins/modules/networks_meraki_auth_users.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "8fd117bc475cb2d55951b9c5f6b410e68127a76a36263d837bc6582f30c2fd7b", + "chksum_sha256": "2f26b0bd8b2f08d2b39fcf89a793cd28717dabdaa901fcef0501079a6269ed7d", + "format": 1 + }, + { + "name": "plugins/modules/organizations_camera_roles.py", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "377891dc86f896a73feaf9c05639f5e2c2d1209ed351e4055809fb9d88af807b", "format": 1 }, { "name": "plugins/modules/networks_unbind.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "de17926db0161a0d8c7d8d07df67f425b5ab4b8bc07ba5bfa22f600f8c6b5844", + "chksum_sha256": "3be1c3b55f9e78d9ca88c3f49a6e4481407965fb3f2416806b67727393df90b9", "format": 1 }, { "name": "plugins/modules/organizations_config_templates_switch_profiles_ports_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "6f7757dc739f587b20c2ee53d739df18e8394df2da06ebaf2be34e0f2a725c51", + "chksum_sha256": "b8e5ea805a776fd52aa9b09b59b6be172901838972def856f6e2f17c18eed5ff", "format": 1 }, { "name": "plugins/modules/administered_identities_me_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "6b064b33423a7fbd0fe8a22d0f7de8d581d57e62c12f0c25aa2d9f9a901a7895", + "chksum_sha256": "82bdcb003389a2eb700806ee649d15e6f64218abbe97e9b08fecc85e4ccc5396", "format": 1 }, { "name": "plugins/modules/organizations_appliance_vpn_third_party_vpnpeers.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "6c36e431e5e43635dffdcd536eccfe9b251f2374d39f08a3df340d4097d2d327", + "chksum_sha256": "bc2f3dca565538531e01eedd1658d8038ccf6da7e9ca9b3a429ab6a9f32661ca", "format": 1 }, { @@ -5030,7 +5569,7 @@ "name": "plugins/modules/organizations_summary_top_appliances_by_utilization_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "7ed5a6c77e822f2ba851b97489c90b878180db6a3f3a194dee47a84387b09e9e", + "chksum_sha256": "cc3fb8493a2076d44b6aaed6ccac128cfd083e2b42445d76c7139dc291567bf7", "format": 1 }, { @@ -5058,21 +5597,28 @@ "name": "plugins/modules/networks.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "97622672289623cc260df389f5b68ee0972fc929fa329ceba654af36d72635c3", + "chksum_sha256": "fa9dc3f8789bbc902df25241e24c4a468a8f60bf7ba0e2e0bb7587d00e0dd5fe", "format": 1 }, { "name": "plugins/modules/networks_insight_applications_health_by_time_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "bb08491bc17a5d19f74b8041d510af8c8122ffdff70381b54b2b539f08c25c46", + "chksum_sha256": "72f8552a442400df52e58e1dd9551463c7b4ddf076f2a7bfdfba73e3ef6fc2a6", "format": 1 }, { "name": "plugins/modules/networks_appliance_security_malware_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "75c0fca25ea933a43f2b0f2283feda2566993a2ef2359a5ae22c99ced184a7a9", + "chksum_sha256": "9cdf917e9be2dfc9db0a8776c682bbaffd8071b258ea259eebdbf4de4954ec59", + "format": 1 + }, + { + "name": "plugins/modules/devices_live_tools_throughput_test_info.py", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "b220d780e4e7199ebe118c7240b673e1225b764d8b8d1d4f77a367f7f2b6a98e", "format": 1 }, { @@ -5086,7 +5632,7 @@ "name": "plugins/modules/devices_camera_sense_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "1740cb529969e28725fa2f1f0a7e8e513a60fe42ca6bb45f7d2feeefd343827d", + "chksum_sha256": "246e40597ea41dcf8131e9c0683812b24b11fa63a70524c55bb9231d7b604773", "format": 1 }, { @@ -5100,7 +5646,7 @@ "name": "plugins/modules/networks_switch_stacks_routing_interfaces_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "bf3d8cad99b1c87b340a6c30059ecbf37ae6551dca889009b3da50e0569cd66e", + "chksum_sha256": "65a12c564870d7d595c6bb8579d24adb76caae48d5e105541027160a0f007dcc", "format": 1 }, { @@ -5114,35 +5660,35 @@ "name": "plugins/modules/networks_appliance_traffic_shaping_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "29468156845d58bcc22976d13d527a2802f918b084644c1bca8196c2f7994e89", + "chksum_sha256": "32f96cc3017cc4e5f4cba4c8793d78b0a809d9b4ad8cc5d6b9ddbc1dc4e0fcbf", "format": 1 }, { "name": "plugins/modules/networks_switch_stacks_routing_interfaces.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "cffc90e3bb443d67fb775a7bb38588fd1355a566fde226a87979007e59ef7852", + "chksum_sha256": "80c9c576519766a3598db5c95eb657ba7dd1682fc20d203387e97e494c34937e", "format": 1 }, { "name": "plugins/modules/networks_appliance_ports_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "51cd4f92893b8117096b162cf9a19a9ca182763665a938a30a64e80822b5f04f", + "chksum_sha256": "75b9e41684dd633fded7fe759475980e3777b2bc379d5b9b27630ea2b117ae7d", "format": 1 }, { "name": "plugins/modules/organizations_config_templates_switch_profiles_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "15efa5f83e6597cf1818f2a8448fe6d6a54a4156b2cf47f0ca198a5ef62c2881", + "chksum_sha256": "2405617ec85a6ca92832037a9c3bba2e48930c2a759912f2531a173796535ee6", "format": 1 }, { "name": "plugins/modules/organizations_licenses_assign_seats.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "fa896238aeb11010cc3d2b17363eb030d582c43016b06d39d6e89102bdbc9f5e", + "chksum_sha256": "02e27c187de27da8594e18c39e9f64278fe2733b8a002a0b7d93d267e3466408", "format": 1 }, { @@ -5156,49 +5702,56 @@ "name": "plugins/modules/networks_camera_quality_retention_profiles_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "7ccf75dd55b222f453911cefde1ece1f7d0969c7e9273bca843790999e527c38", + "chksum_sha256": "d618f1519f05e5bb34e8593fa1985537dc914e2600aa5d1a037ac6239878f81b", "format": 1 }, { "name": "plugins/modules/organizations_claim.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "961e35df89916c35d2842eea40ed96eecf1056a2418b3f49364541f5e1ef69fc", + "chksum_sha256": "f2a8a6cbbaabc293323eee8765a32d46596e7df263ad808f5accea3e32323a34", "format": 1 }, { "name": "plugins/modules/networks_switch_stacks_routing_interfaces_dhcp_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "94651618f7aca94b5c77e7023c9e3f0559233dcd8462ce1d6bb6bc9f428d683d", + "chksum_sha256": "05ee26c57d9e6625ddaf4a6d60d8a7b07e6434024f815a2ff84c0ec2f225b46d", "format": 1 }, { "name": "plugins/modules/organizations_sensor_readings_history_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "3922bde87f94848bcf40d2fe226e923416195f13ecbefe6253bbaa74cd152b78", + "chksum_sha256": "61d8c43c50f2ebf905271f3da709f9628211f5fc6f516346f4da8ae28c453fcd", + "format": 1 + }, + { + "name": "plugins/modules/administered_licensing_subscription_subscriptions_claim.py", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "105070107bdb634df983a2c6b6f52da673e4142c024fdc42c1640aa5266659f2", "format": 1 }, { "name": "plugins/modules/networks_appliance_ssids.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "a5e5d8856bdbc4f660782df5db4ae255458a2989a6b33004a62c1503fc7aa21d", + "chksum_sha256": "80dca1690ad2869e0e2062c2636d85277059800335755579fc0cfd215a0d6a6b", "format": 1 }, { "name": "plugins/modules/networks_appliance_traffic_shaping_rules_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "9a4fbcda9ed7ccbd8adbab30ab10b89a02499bce2ff2364decd4e8397ed063e7", + "chksum_sha256": "142d7145e4e9a169a44db8674b283fdaa640e79bd800b05a12062d4c28f571c5", "format": 1 }, { "name": "plugins/modules/networks_wireless_ssids_eap_override_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "14ea69b8d0f79d7082b1221eab3f99f0be7889daa80eebe4c05e81b7b974cbc4", + "chksum_sha256": "9bd8ebfb889fad29461b282b6f6d2fe8de3a524e34dae6a7837498dd02d25ebe", "format": 1 }, { @@ -5208,39 +5761,53 @@ "chksum_sha256": "345791b88df34958621266cb937af20b985ddbdc8bfca2bc7404c416847213e7", "format": 1 }, + { + "name": "plugins/modules/organizations_appliance_traffic_shaping_vpn_exclusions_by_network_info.py", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "dd9e5321f7de648af64a401957ad25aaf6ea2dbd7ee01f77a13538dba95032df", + "format": 1 + }, { "name": "plugins/modules/organizations_uplinks_statuses_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "23e5a27a3764cd7a28fff1c943d9dec9b1b0269d5584d2ccc1325eba615d2f4c", + "chksum_sha256": "8c2a5d4e82fae15634fe560cbb94e6c2712c4746268e8dc03a2d907684c81a12", + "format": 1 + }, + { + "name": "plugins/modules/devices_wireless_alternate_management_interface_ipv6.py", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "967de578dadcedce1d553303cad5f6169ca529f6231f667d5af0a3a9dac6895d", "format": 1 }, { "name": "plugins/modules/networks_appliance_single_lan.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "ce4bf55601b3110749d4b792a0d389d23cc8e13a797ab0e5ca633fae625ae787", + "chksum_sha256": "db3e8a10f9e6e75e2c3bafba23b31b5adf1475d5cb552388d610072f7ed628e7", "format": 1 }, { "name": "plugins/modules/devices_switch_ports_statuses_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "a50f6a57ac1aae5a0b2e8e7f70efb268395de17a72f8a612fa3b0899814fcae9", + "chksum_sha256": "9aee4427bd15bce2cd8be88309bb3964be34803859dcf4b6751619ae175d2849", "format": 1 }, { "name": "plugins/modules/devices_switch_warm_spare.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "6f74d272ffd5fb8fd7aa932782b12154037b6461baad840de6071a9a0d5f948a", + "chksum_sha256": "53bc718beba268ede7d5654084ffcd05bbcc4f521bb163796d755fc4c149f3e0", "format": 1 }, { "name": "plugins/modules/networks_switch_stacks_routing_interfaces_dhcp.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "f5c51852fdd18de8c919f3b6af794413337819b882ac500e2d8fea8a788a8d34", + "chksum_sha256": "fbf3c112f74994b8ac8fe0cf3ca2b83b7f79a46b1e6404f2910064943dae6c06", "format": 1 }, { @@ -5254,28 +5821,28 @@ "name": "plugins/modules/organizations_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "d2f589b106af09a4e95439facba44801d28ca1fc410f5369c4f5c8b11156a299", + "chksum_sha256": "9eb97539ba3e3b448084a6ff808a29fe091dd17fdd3e0a0e0d0f96b942fb522d", "format": 1 }, { "name": "plugins/modules/networks_pii_pii_keys_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "b12b61a58c52953696d7aa6c2be3072b338d63e4cf7863f48b1c18222b4c0dd5", + "chksum_sha256": "a71a003cb7ecc509883290dc0bab4c20de66d710ade1c34e342fb12f667d2d44", "format": 1 }, { "name": "plugins/modules/organizations_adaptive_policy_acls.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "d2377c89cfb3acef29f780594f4fcb045b6133993a741972ca6b5f72cfe50157", + "chksum_sha256": "846df6032216d47ee839f2c71854544f347debecadf8f0c371c9ca7f33bc4f12", "format": 1 }, { "name": "plugins/modules/networks_wireless_ssids_vpn_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "01667df960887549f70a669a268125ab24fa305f6e7bb88ad43daad7faf15444", + "chksum_sha256": "60fe7f725e7c209faa5892b46a532fe8e4a80c09cd4dfe8c8fc056f29b6ef6fe", "format": 1 }, { @@ -5289,14 +5856,14 @@ "name": "plugins/modules/networks_topology_link_layer_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "42d668b3b02282628e8c7b4cca8057026bc33694315e431c7fb331ce54f661bd", + "chksum_sha256": "32c09902b6ec3baa220fe09644d851deacd86939cb1ea2633e2366674b7ed511", "format": 1 }, { "name": "plugins/modules/networks_switch_storm_control.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "0b80877b6fe40fe193df8fac36529159ce4ee65e03209de9ce3b5681ce623b38", + "chksum_sha256": "cbf534d781c9fda390444ea25b0b3ea9b49a91688dd1829ec8faa9280fa2df7a", "format": 1 }, { @@ -5317,21 +5884,21 @@ "name": "plugins/modules/devices_wireless_bluetooth_settings.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "98130360c2d0d5f29cec8fc3e62a7996f58999defe4e3e3b64ab55c841eca997", + "chksum_sha256": "b7ebc44dfd5bc20eea190c6152af333b16e1b98012cd3c1384ca7be8ed2990db", "format": 1 }, { "name": "plugins/modules/networks_sensor_alerts_profiles.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "76e51ed167b7e5c460a6c928a7dca231de81674f5d29d7972b574bbffc87837f", + "chksum_sha256": "913ceae71a244c3e089649f1bb726500e183695b071e54ad7afecfffb05d2851", "format": 1 }, { "name": "plugins/modules/organizations_devices_uplinks_addresses_by_device_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "095b39c947deb7ca0b8be13fc3ad134f52dae0a66f548e27825979624800cc6c", + "chksum_sha256": "566422b1fceb614208dc9e0728359408a6c8af77c55c5f2e06394468341efc4b", "format": 1 }, { @@ -5345,42 +5912,49 @@ "name": "plugins/modules/networks_camera_wireless_profiles_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "bf9945e19c4a2f4e5df492e72b5c9ca3556c83c3ed33f33aabb3d677c2836e95", + "chksum_sha256": "ca28d56f97493f2b17d78dc145651194c136b428f34189112eeec03c40711119", "format": 1 }, { "name": "plugins/modules/networks_clients_policy.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "15819be4a919d838a42da1131fe13af0c4f85e8fa09ebf5728c7ca6ed06bbdd3", + "chksum_sha256": "fa2ebf4c686158d71781335a4e40465618427ea3fb8588876635a5deafa1ca10", + "format": 1 + }, + { + "name": "plugins/modules/devices_appliance_radio_settings_info.py", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "15053e07d1680b26638adce7e90a9e3cf28a0305455c605c0056bdcd60c4254f", "format": 1 }, { "name": "plugins/modules/networks_appliance_security_intrusion_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "35c9c2fbd86b3d5076191701fbde8bcc65ddb11130d8a49aaf62c40b21666cc3", + "chksum_sha256": "3b78e531ebf403ede7965b9d302d621a0a2080f13d44a7a25be37aba2ccaab79", "format": 1 }, { "name": "plugins/modules/networks_floor_plans_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "34138121ef1ceac92a521681d2280d228fe60e2fc119a8f889e3a3bc0d798587", + "chksum_sha256": "e23787f16abf03ecdc848862e32bfe4d4495f33a5c2f75017967e1662596e572", "format": 1 }, { "name": "plugins/modules/organizations_snmp_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "55e35b87564469e4f97b6cc6eacd92b470ee00b5bfa9f4e765bc4856541eb0cf", + "chksum_sha256": "b10e7644caf23607df239db1b18ccb3b1800f311f188f05cd881ddc1689b3f4e", "format": 1 }, { "name": "plugins/modules/organizations_saml_idps_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "6aa6d062f1534d5a3b77a9b493972340918ba42dfc7a59e202c6b91260a1c03c", + "chksum_sha256": "a1c018a21d8365e28670949fe491cf6f817def1237cf354a1cbf7c33ade6329c", "format": 1 }, { @@ -5390,11 +5964,18 @@ "chksum_sha256": "c1fdbf3250aaa3a438a972551ac121cd977f8c42850208dc2026595c1e07efbc", "format": 1 }, + { + "name": "plugins/modules/devices_live_tools_arp_table.py", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "198239dac290c2b9b955239047ff3719ed582498d19144c7efcef166d1a8e229", + "format": 1 + }, { "name": "plugins/modules/organizations_api_requests_overview_response_codes_by_interval_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "fd612c215b87d71f898828e4667f3e59f03330af839bfb7281020dca14ff6e65", + "chksum_sha256": "6a945e1bccfb84276528514b9d2ef947498ee004c87a06994ab25efe0ea0f206", "format": 1 }, { @@ -5408,28 +5989,35 @@ "name": "plugins/modules/networks_camera_wireless_profiles.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "82fb4705248c5bb3fd7839e992808bcb6e32af432e87e8859ad3fcf6ddbbce06", + "chksum_sha256": "95c491c6bd8f22b2147983832bfeeb1f00b9bd7d4290beeceb273bfd84365e24", "format": 1 }, { "name": "plugins/modules/networks_sm_users_device_profiles_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "9b15fdfb0b4f3991e2bb3a40cb43e4d4b5f9ce1b279916c1e008abf727487c3a", + "chksum_sha256": "76386fc2fd2f09f1ec558d5389697da77b0a2613a986b5f4d9d178d202edc996", "format": 1 }, { "name": "plugins/modules/networks_appliance_firewall_firewalled_services.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "8f114910154797922f433576b2ce93d68815e6ef2dc2907d9a0f180e7c6f00f0", + "chksum_sha256": "ab9a4150682f3efdac21618756a35833e1dcfac3928dcb9ac6f7ad282e9d2c03", + "format": 1 + }, + { + "name": "plugins/modules/networks_vlan_profiles.py", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "c3cf7d794ed002505151f58d22c3e35d622de6736a2af090d8f42b068b14d54d", "format": 1 }, { "name": "plugins/modules/organizations.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "a092a85cdfc9527cde53179cb9f31b11b044a6afc98fc182fbcab75784dad7c6", + "chksum_sha256": "396910abbd856966ea57db60cc589f80efe689b50cb6d5160a909ed57bdc9f4f", "format": 1 }, { @@ -5443,21 +6031,21 @@ "name": "plugins/modules/networks_appliance_firewall_inbound_firewall_rules.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "b13c5cce1ef98d2e25a53e784c0ee66ac1fa2c4f394f2f3f5334bc6ccbf65266", + "chksum_sha256": "8ebdc98091ae5876883b711480893486bf3e909db58e6d1ef7b013a08da12910", "format": 1 }, { "name": "plugins/modules/devices_cellular_sims_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "248f292c530fb41de71d55ae1f4260b0e7e08bf68835e7de73e49bf5c364af65", + "chksum_sha256": "d0f270add5a7745b6265906ad121211adf50316b9500b53d1d0ec4154b38175a", "format": 1 }, { "name": "plugins/modules/networks_sensor_mqtt_brokers.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "6b4d3bb8cf89580125db674f77ed6026516404edb868143925f223d954255f99", + "chksum_sha256": "fd274a15d2211910b8efd7fa051d21e043830667812628fe6a04e8cc0cc1b11d", "format": 1 }, { @@ -5471,7 +6059,7 @@ "name": "plugins/modules/networks_appliance_content_filtering_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "11e580c4ec52ad685ceb4b0838752d678fb357fc109d7f9d307a09f06526b883", + "chksum_sha256": "8fd159c157a7f2396a65e4daf3747e1475fb074daa95b4a295346d69b22736b7", "format": 1 }, { @@ -5485,14 +6073,14 @@ "name": "plugins/modules/organizations_inventory_claim.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "d200bf4ff0347004402dcd68a094b891aa5555c6c79887bd9523c8994f980404", + "chksum_sha256": "64f560dcc67a46ab8c2a5f1729a5fa7fa1457170cc226ae2cceefe92a1389cec", "format": 1 }, { "name": "plugins/modules/devices_sensor_relationships_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "00705b45ca934c8dba75d8a038eb561d74378862d9a47bda44212a4ca06e0f23", + "chksum_sha256": "22f3043c29589d4fb570f0a4153883f1609c807540b877d3e90c3a4531474b42", "format": 1 }, { @@ -5506,21 +6094,21 @@ "name": "plugins/modules/networks_wireless_usage_history_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "5862604c9eb82cda6d303bb56c8d7abb348a50e582c4eb7812f6725603eee9ab", + "chksum_sha256": "6025943090b3d33bbdd3ec376deb1f62e6bcaf6cd96c50ecab46d23971aeeba4", "format": 1 }, { "name": "plugins/modules/networks_cellular_gateway_uplink_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "33da979ee7d1e8f3a7eea6ed046f64deac4d88c1a805ba1672b85be2800426b3", + "chksum_sha256": "09abbc31f0e6f6a2db875568c7f9d393a22a2e43184d33ed3163bd496ceaacac", "format": 1 }, { "name": "plugins/modules/networks_appliance_firewall_port_forwarding_rules_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "9d1fcec4d881272e40c665be310b63b3c779247a2fd2742d8fe4972df11ffb38", + "chksum_sha256": "8563d2718bbd236f9c24b9e42c52be85fb56f3f101a0186db39354a33c7c9883", "format": 1 }, { @@ -5534,7 +6122,7 @@ "name": "plugins/modules/networks_meraki_auth_users_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "6a018eecf216a0c156625f7171412050e2a71db2021fcc273eae5181aa5760b2", + "chksum_sha256": "2448825e0c4b5648ff7c3df4797732d8dc32eed0a8362d9438b44b9aa3bbc04c", "format": 1 }, { @@ -5548,63 +6136,63 @@ "name": "plugins/modules/networks_switch_stp_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "21015e581a2e7f08cea18aec492d3fed60d77effda018067911c69d6411c4004", + "chksum_sha256": "780c38bf2d8534501d4e5f4f31e0c9dc3a70cee9ba70d8a82c332efef75a6002", "format": 1 }, { "name": "plugins/modules/networks_switch_access_policies.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "fffc1d3d2b168f765c89b550cba241d000acc7f558a98a9add038ea1f8604e19", + "chksum_sha256": "8da855c2cc9fe7ee18d3b4a4c5682e907c062d8e86002a85e7bd20e37eb27213", "format": 1 }, { "name": "plugins/modules/networks_switch_stacks.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "2fdcad8f53f7842aad16541fa40bf9cbf94e17e6edabfb8cb9ef05dffabd6cc7", + "chksum_sha256": "eb9b64de59a7fdb6234ba55b96e6cd151bfd1d716dbabb97cb35f7356ff707c0", "format": 1 }, { "name": "plugins/modules/networks_mqtt_brokers.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "ff54fceeea4118c304ae385b211e81c5a0109e04026328815885cdd48a6264e7", + "chksum_sha256": "6fe88b51ecfd71e124208c50c01a54f95f1ea0a2d8e7cc4c5933204eadf8e136", "format": 1 }, { "name": "plugins/modules/devices_camera_quality_and_retention.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "14a0063c5c4eb8a04b290927eec97f70225c564df1fd4cbd6a31f9d55c52111b", + "chksum_sha256": "927e09d476993c0ffec31b9a651088d200cf78a4950240501c0b7b4bb7821d32", "format": 1 }, { "name": "plugins/modules/networks_appliance_firewall_one_to_one_nat_rules_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "72562b2d476968ee9452f7ee2a3c618b7e9f8f6b135a70591251a1323ed8b2dc", + "chksum_sha256": "2308bf8ac252df15dfe870bf49a38e5a30b92123bbe9b48561d158687ded8756", "format": 1 }, { "name": "plugins/modules/devices_management_interface_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "87fc37142e44edc1ec368fbfb8f187d1ed23657ca9a43cfdbb9aac3a1bd63ae9", + "chksum_sha256": "de0e958e8cdf2420c4d1c23f57f75d3819401fd9c16a050e043e575599fe2bb0", "format": 1 }, { "name": "plugins/modules/devices_live_tools_ping_device_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "536938d372f8e4218cd58e4084291d63b52f0d077f0a3b3578035750916df35e", + "chksum_sha256": "5cdb0143203410754598a375a57061b12805e05123634a607a55412b0bf7bd85", "format": 1 }, { "name": "plugins/modules/networks_webhooks_payload_templates.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "2f45ec96095fd04b9f89568b8492c31932072e87dde05601a0ede18d04ea075a", + "chksum_sha256": "3f7195e850e3b55f8e586195261d8519db49b10f66d993ed65eeeef279a346da", "format": 1 }, { @@ -5618,7 +6206,7 @@ "name": "plugins/modules/networks_sm_devices_certs_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "3fc5ede16e7088a1741b4921895c51ca284012995b8553abbeac081e2cd0a5e9", + "chksum_sha256": "28d1e0aa8b9bf8fa677efea37975a0e6f317c71cad51c8a39681cee75825d3f8", "format": 1 }, { @@ -5632,63 +6220,70 @@ "name": "plugins/modules/networks_sm_target_groups.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "0b65fd9bd8736317788ccf4cebf97cfe0cea6801e34787190c491b796e5d18c0", + "chksum_sha256": "9fe732d09aeff67b18a38c9f66720c887cf07013be8d661d2350c0a9e05e9722", "format": 1 }, { "name": "plugins/modules/organizations_insight_monitored_media_servers_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "6ccd2dfd1a3af5da931a2c63824e8c64a57cd21c0f7dc4f9ea058c174febd471", + "chksum_sha256": "49089ae525dee50332562762f2988dcd81f5e61aee33f7b7400a7898d4ab725f", "format": 1 }, { "name": "plugins/modules/organizations_login_security.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "8bb31c1edcce4e485ca3e21abc381110f2413ca03a6ef22542613c87d234f40e", + "chksum_sha256": "1740f0a2ea5e22dc69905c42a3e784d4f038d95e78e48ca0054da32952c90b56", "format": 1 }, { "name": "plugins/modules/networks_group_policies_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "be8f42494a88c3d46c31a46611fc51e705cfc44ed7d1752071594555b8de1abe", + "chksum_sha256": "e83306285b6c231afd6731205f93af595d3b348edaae746b4be5b981a31b34c3", "format": 1 }, { "name": "plugins/modules/networks_wireless_bluetooth_settings_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "7ba64cfa15e134b1f0aaacf6a36472da7698ed7bdaaf16ffda185c3a27d46027", + "chksum_sha256": "0813b762763f88d050ddce766305f8205e80337b23330202a8920b29a4bb9830", "format": 1 }, { "name": "plugins/modules/networks_sm_user_access_devices_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "b532f4847e315d8775d079de9c780dfb7caca3a496282d4e5191bec137bb017e", + "chksum_sha256": "3d474c0b1aaadf604803ddde1f87cfb1f89106439c25c845ef6fcb737be5a575", "format": 1 }, { "name": "plugins/modules/networks_appliance_ports.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "82c044254b4c4863a9c90594cf8006ac9e7d3e8725c05f507b29ef5c8b7bf975", + "chksum_sha256": "4c461dbb4fd311ae2805bdfbfd34bba87aaef516d1f8744e92c50c01defdcff6", + "format": 1 + }, + { + "name": "plugins/modules/organizations_sm_sentry_policies_assignments_by_network_info.py", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "37c2918bc44903e54a7585200c7293c719c77f1591b504ac41e7bc3820ff5f4f", "format": 1 }, { "name": "plugins/modules/networks_switch_routing_multicast.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "51424794208e8307daf2e94ec72e60830c223e108bd5748d57f2951a8f14edd6", + "chksum_sha256": "d61f3ddd08a76f50abab4a1cb934cf6b1444ff2fce15a14800050fd34877ff16", "format": 1 }, { "name": "plugins/modules/networks_floor_plans.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "899df20c04f9364a065c038721bc73bacc8ad0e5bc88cb2fcd4db50dd4b943fb", + "chksum_sha256": "4180aeb60ccd216bde4f67204e8d587b612ec1b0b4cc5fa6dfba4651ee3cf505", "format": 1 }, { @@ -5702,28 +6297,35 @@ "name": "plugins/modules/devices_wireless_latency_stats_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "25dfd2b4731e259005bfa381eb8aa1aabe13bd0a0912e7f9e9d80b9d1ed456ea", + "chksum_sha256": "68cace03da14e83c75d223c13813b7ec4c4abca95ee1a386204a8d00e790c51a", "format": 1 }, { "name": "plugins/modules/networks_switch_port_schedules_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "5bddb4bfac9b4752f679bc311e74f7829af693735524f2411d1e96617a328f5f", + "chksum_sha256": "b23575c5ab4167d4d8143270e41f95ea343a2d41661f530ba1df9da4b5809564", "format": 1 }, { "name": "plugins/modules/networks_switch_access_policies_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "0b3468245b9128a8a8094399d654bf1787cf759862b21235ba3b94a6c73bcfb2", + "chksum_sha256": "4b73980aeccd94ff5c75ae52a5d3a8ce1df8c178c168cd54e89aeefa965ac07c", "format": 1 }, { "name": "plugins/modules/organizations_licenses.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "34d2d9b82a75904b7aefe6c406880397fbae9d940a892f3d9be2cd527eb05933", + "chksum_sha256": "9ca8f5b8d16d98e18881d0a8f42133c6022eb82b8da2f40af53175945dcfbc6e", + "format": 1 + }, + { + "name": "plugins/modules/organizations_camera_roles_info.py", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "0cf695a9f8d76ffe1f060f1f9649d4c658145c3f51862563c04bf63ad19f211e", "format": 1 }, { @@ -5737,35 +6339,35 @@ "name": "plugins/modules/organizations_summary_top_ssids_by_usage_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "63dc94ef3fd832d106b5078990aa41d1565ba7bd7503d2500258d24181f4dd46", + "chksum_sha256": "635186dc03dcc0447a5041adba63053197fdd8d4a8928d1db8c9a189b44607f9", "format": 1 }, { "name": "plugins/modules/networks_sm_devices_checkin.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "ec2d1c628d8b67566dcf26b153519eaf6531f7ebca06f6c5b6df50ac07bfd4b9", + "chksum_sha256": "13750dfa10ab16895e74db63c7840321556d9a80001395c922453888c000aca3", "format": 1 }, { "name": "plugins/modules/networks_wireless_ssids_splash_settings.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "33ef0404152cfdad515c1e8a65b1fdac44a68f1dfb3570e4f2228e7b7159e9d8", + "chksum_sha256": "7adf2bd20d9ec6195d7bc94f2aa02e312481ab3b9792e7804631241eb7d3d496", "format": 1 }, { "name": "plugins/modules/organizations_networks_combine.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "8cc5cb6a436eb67941c46d9fa5df6372ecdd10c4417ffbc8b7a0471b46296ceb", + "chksum_sha256": "f5ca3187ba014ef4687b0f212894970a0a86b0e908adca68a587685486fc3c96", "format": 1 }, { "name": "plugins/modules/networks_firmware_upgrades_rollbacks.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "4a550e6abc098897d7200ee4f57d8c2720ac336a3742dcf74026283fdfdea9ef", + "chksum_sha256": "0c8266fddbf6003b9db265bfc99e4ba532534f14f0be3f52b404de8690a01dc9", "format": 1 }, { @@ -5779,91 +6381,133 @@ "name": "plugins/modules/networks_switch_dhcp_server_policy_arp_inspection_trusted_servers_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "14b960a68aa9eef5fcea207bca140321c417657b38e920a998a5c93cdc128fd1", + "chksum_sha256": "cb35d4db944ff9f4339a93b3cd214cced006fa9908c047dbdf81e8f2342a8189", + "format": 1 + }, + { + "name": "plugins/modules/organizations_appliance_uplinks_statuses_overview_info.py", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "2b21ba0e01305b475556b7f6c3635fae0c71984a754357a38eb9f75c7adee395", + "format": 1 + }, + { + "name": "plugins/modules/organizations_sm_admins_roles_info.py", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "cc08fa3539f847c0b55497a26d196e3e519bbf370de5f41e8de86ddbde7eb39d", + "format": 1 + }, + { + "name": "plugins/modules/networks_wireless_ethernet_ports_profiles.py", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "43a77fe915ebb73b4cc2ecdb978bf274caf6430e853a911b59e122fc289178da", "format": 1 }, { "name": "plugins/modules/networks_appliance_firewall_l7_firewall_rules_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "df11cb034689b0768266880acf527ad75123d6f5302a6e380c5ccbae9ed6b0a0", + "chksum_sha256": "3e3a7fe5aa9229acd3db6d37c5ed06f3903c3c438861bf9d1eb54fc7d496b208", "format": 1 }, { "name": "plugins/modules/devices_switch_ports_cycle.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "1a7e719b6a0dd04d4e2783c588c2ae9f0128af3252d0faf2becda3d71c094113", + "chksum_sha256": "239db3ae5d16bbfabe90d02f98ed118bf8234da086ce1c7d162c52c8ea7c4a1e", "format": 1 }, { "name": "plugins/modules/networks_firmware_upgrades_staged_groups_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "61529b98cfbb8f39e51faca00dd3ae54be4f340949658f9d783ac87efd9e5598", + "chksum_sha256": "4c0b48b086697e6b35062e07e12cabec6e6491c73df36b76c49fa1d2889ad5e8", "format": 1 }, { "name": "plugins/modules/devices_wireless_radio_settings.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "963eafc4881b9a281e9440bd15648ea33e291c4814986bc5cc466d26c12240a7", + "chksum_sha256": "5004bb971521fd16b09579d601016c48844125f3eb3d796da4aa8ddafa901230", "format": 1 }, { "name": "plugins/modules/organizations_devices_power_modules_statuses_by_device_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "f5a8d98879497ba2e170d07bff42f01eb18695663c4f03740222e7879ef96ee8", + "chksum_sha256": "1ad460c8a40aa67a90fe43e7d1fc46af98ce12d3fa1456d5310056390b4426f9", + "format": 1 + }, + { + "name": "plugins/modules/organizations_camera_detections_history_by_boundary_by_interval_info.py", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "ada9e36c0233051d92c83fdb656fd971a45df362da0fb5c4c34ae93e1f0e4c2a", "format": 1 }, { "name": "plugins/modules/organizations_admins.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "44ff42ca9871ba0eca0d0d2dfa1d24fd1afadefa4f913eaa99057472416b3653", + "chksum_sha256": "8eda0bddeff2b97522e85b18336fdb766409cf552593250ea56da7a0ab81db25", "format": 1 }, { "name": "plugins/modules/networks_firmware_upgrades.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "224f29f05fe56fbf481265024e6bd233316bcf00524211abbc651000509778b7", + "chksum_sha256": "4abe6665758650fc4cad20835caf8c57a008902baaa1e33d912c7e1b72819e10", "format": 1 }, { "name": "plugins/modules/devices_management_interface.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "2ff9d3d92588c64f5acbcd4e9f3b17044f266d60dfba61f6f4ea8e4700475fa2", + "chksum_sha256": "d5f3430cfbc95ea11f84694ecc5c62be5599640ed7a886f03c06b5e12cc49463", "format": 1 }, { "name": "plugins/modules/networks_webhooks_payload_templates_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "ae28dd6b544128b3ac7b2d9b380ec553a117aa8e19356a72b9e0e16a35519ad0", + "chksum_sha256": "3090c460a8849b3a50db7d884570ddd001dea900fc718bc7b7be7380c179677e", "format": 1 }, { "name": "plugins/modules/networks_sm_devices_modify_tags.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "4dd01dfb8ba6434505940d5e1ea897fbeb0b30866798a4ac34eb34bca78b7cba", + "chksum_sha256": "7cff3f276d1438ee32eca4c29d118a25cb40dd547f3a8bf8bd47d17350b36d72", + "format": 1 + }, + { + "name": "plugins/modules/networks_vlan_profiles_assignments_by_device_info.py", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "e8b7fb2624ac69e2ff2eb8da4a8e964dbd5a2816a3344859510d91b01058dc1e", "format": 1 }, { "name": "plugins/modules/networks_health_alerts_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "97673dd12f1bd1ab3b771437ca2092392d37618a1d436f032dd93503c4c9efe3", + "chksum_sha256": "640a47c57400cd94fb232fbabdd4aec34f6e03b4775a43e3d1e17eb7cb6b150e", "format": 1 }, { "name": "plugins/modules/networks_wireless_ssids_firewall_l7_firewall_rules.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "40219cb1e87018913fc7de01b6f509088a1c4b71f72c71f011fc7d5165661d8e", + "chksum_sha256": "94cd4dab5bdef89485aadcd32d3f984f6ba3965ccb3f55aa8f576f1acee8d04f", + "format": 1 + }, + { + "name": "plugins/modules/networks_sm_devices_uninstall_apps.py", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "5665160983b6d8d0453eccb4bc63aaa340a16673534971bfe662fefb32d8dd7a", "format": 1 }, { @@ -5877,28 +6521,28 @@ "name": "plugins/modules/networks_sensor_relationships_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "6e3bfdceb51d9fe195378043e257771d15a6da2aef90991a871c01705bbb7dfe", + "chksum_sha256": "beeb81e82633577df04a765f5c8fece25921fd902141a7769b2c6283b8fba1de", "format": 1 }, { "name": "plugins/modules/networks_sm_bypass_activation_lock_attempts_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "b9d1297fb54f58c10b0296bea82994a84895f31b5de46a829a221519b5bd5228", + "chksum_sha256": "ef3aec73c06ada1e93c6149567ed59b52ffad0acf7f195da456aa86ae63cdc88", "format": 1 }, { "name": "plugins/modules/devices_live_tools_ping_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "6b23ba02911fa649067bd3da1c593c28ed21340444bca0db4ef650157ee7430a", + "chksum_sha256": "ba2fa1ca8de82f57b4998a0b4827e6011ef7b67ccdf19e33180ad887384acd43", "format": 1 }, { "name": "plugins/modules/networks_firmware_upgrades_staged_events_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "d33dc0e78d70e263324b41a5e6e9f6976ecb1615e0c2c2ca18e0d54fc60f8637", + "chksum_sha256": "b367965aa4928f89638bfd0f029db9173ea3f8568173deb1af6d8b4cd695c0d1", "format": 1 }, { @@ -5912,7 +6556,7 @@ "name": "plugins/modules/organizations_adaptive_policy_groups.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "30ef413f2648c1bc27c72e070c9a4fdf04617189a25b714aa9a220c448ba9d7e", + "chksum_sha256": "8350dcd369dcd773ed23a266b8b9827cd2e37e9af6b35eb759a1b7ce95914bb4", "format": 1 }, { @@ -5926,35 +6570,35 @@ "name": "plugins/modules/networks_wireless_billing.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "44d90276b1c173453a3c7e61c08eaf882af031cc93df4399240cbbd78c76458c", + "chksum_sha256": "aa7dfff2af46eb086f24145ba37de3f4f81a6cabaf05fa85ebf2805529a934ad", "format": 1 }, { "name": "plugins/modules/networks_sm_devices_fields.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "780554e40bb9cf23e5acc5c01cab428a8df0e0ef68ebb7449352af86808022eb", + "chksum_sha256": "84c285a2e933f73428cada2f2266ea3af52386e6feb7aa0f594261f8bc08925a", "format": 1 }, { "name": "plugins/modules/networks_firmware_upgrades_staged_events_defer.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "9cdfe2e2fe40b0ddc1ffc42b587ce19329f323a524a8cf574226d0be9a710463", + "chksum_sha256": "2719b1871f735804817502373809027149c9071170b8c77ad12cff725304ebeb", "format": 1 }, { "name": "plugins/modules/devices_camera_wireless_profiles_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "4ba91479861271dc6c717edba053797932a1091b345b9d19f5ce01aa7540258b", + "chksum_sha256": "c50ccc0b145b31f5bdd8d6bfb4baebd38205f8449995f06a62e700c203f5181e", "format": 1 }, { "name": "plugins/modules/organizations_summary_top_devices_models_by_usage_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "1e3934c4498f2d2f7e3485b7312d22a94483f33823a9f4960d02e6beb8a3fb34", + "chksum_sha256": "b8ac329fb9b35c492791623f805a9c55d04cbf07f2518d670951dc641aef20c9", "format": 1 }, { @@ -5968,98 +6612,112 @@ "name": "plugins/modules/organizations_appliance_security_intrusion_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "de9384435bc38d35b9e72b8eb6cc237c24659cb002901c253ee2fc42113d6bdf", + "chksum_sha256": "2358fc76caeb42c63baca2a4738d20d42d09070fd9d51e7562db022878dcac06", "format": 1 }, { "name": "plugins/modules/networks_firmware_upgrades_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "16783220aa59c74e0fbf3d69f89e2310d048222bab436e845216e413aec32500", + "chksum_sha256": "bb7b3dde22389ece9e1466a5a15700ca1e1dcfb1edf81a5311bcd09b15e965e7", "format": 1 }, { "name": "plugins/modules/devices_wireless_connection_stats_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "313841ad709a50bf16fe29b23c1483ce0a6fede86345bab6afd941698bbc2f44", + "chksum_sha256": "d6032d52c0415c9cf951a0b0118cffd89a081ec3e5bd1ea70685a01961aa0d17", + "format": 1 + }, + { + "name": "plugins/modules/devices_live_tools_wake_on_lan_info.py", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "276e3dc4200949fdaa46e83424b16e6d3b653c3ca9195d3e65bd8550c9acb977", "format": 1 }, { "name": "plugins/modules/organizations_action_batches.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "9b257caa0baed1b5b66bbc0b762d69c3f8428a8524c61147a56867597c416c7f", + "chksum_sha256": "1fed1789a0743b5b2dce98d23a9d2e5af683a708bedd3e8852731e915df10e58", "format": 1 }, { "name": "plugins/modules/networks_sensor_mqtt_brokers_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "5404acd29944dae88b51965d57fa23e0161f0b7e9f39cacebfca6d2544fbe13b", + "chksum_sha256": "5ceb4c437ae1400cbb575f2efa54d3f670a18548ed34e7cb5359f388526f0b8a", "format": 1 }, { "name": "plugins/modules/organizations_inventory_release.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "4b4801da8ebe1ba784efd1a6f482be63fcf55775f6115bf60227de9ae64b0301", + "chksum_sha256": "996779339c4b998b60d2425001f07218f4770c8bf3257e8b99f0ec8c3e867d92", "format": 1 }, { "name": "plugins/modules/organizations_cellular_gateway_uplink_statuses_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "04eb110335491bc21d8a1a1bf9311a22312c8174da753364ef157e8314d4b1a7", + "chksum_sha256": "4f0ce1272d44dbd612f5f3b6d6b6c03897df304d93334b0fd6a06c51f922fd12", "format": 1 }, { "name": "plugins/modules/networks_pii_sm_devices_for_key_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "817d069ea86f758113126cb08e486c21a26f7c68ddd2d6f107fb5792d21213ef", + "chksum_sha256": "46caa80fe43734cc55dc45030cc6bc8e67927ccf50c2b9b88878749503af8cf7", + "format": 1 + }, + { + "name": "plugins/modules/networks_appliance_rf_profiles.py", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "e782c70e550cd192b0199eb6a5fd127d69c7da7508abf0ec7d57988615844bf1", "format": 1 }, { "name": "plugins/modules/organizations_inventory_devices_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "645f6e7b61e9b8ef86f26cbf9c1e91cc2c8019b5a397bda8d12a92c8564d6940", + "chksum_sha256": "b5079e793415f40d8e0f9b10ae5464676668e355700ba2054040b107fcf9685b", "format": 1 }, { "name": "plugins/modules/networks_clients_provision.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "48d370481809ff8258e8e033382253171a8aa9f90b15d917a5598253f17bb591", + "chksum_sha256": "07c9bee641024fadcc775c1bb9978bdfb8219683c544cb4191fc111107f8fbdd", "format": 1 }, { "name": "plugins/modules/devices_switch_routing_interfaces_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "e15bbe3401ff4d72b6892a51efee4239e9b9dc66f689db7ffbf1852e74bd322d", + "chksum_sha256": "d75a829380e3f371f80c39c4c4a83a275b83d9a708aa46a399f0ec7f2d1398f6", "format": 1 }, { "name": "plugins/modules/organizations_snmp.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "158105f9310311e26aa7f8ebd2f06466b6446ae80ed8d912f1625dbff1753fab", + "chksum_sha256": "642113ab58f105c98200a645d8f04fd8e3bad47c9da8a62d7f8bcb5b19dc0a0a", "format": 1 }, { "name": "plugins/modules/devices_appliance_vmx_authentication_token.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "2cac946fb65babee47478f3626f1c5ca74cda18d6d926b9a4da01018bd2a59e8", + "chksum_sha256": "d00b138480ad8392fb5429d94d1d264ba07187ace1c6588748a33e42c06b7759", "format": 1 }, { "name": "plugins/modules/networks_switch_access_control_lists.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "6558841604fb0958f4f2057ced0608f84464c384fb8b64d06a9e80b4e45608b5", + "chksum_sha256": "1c5fac01f4651403823319163e5ce750b4b35f45a0bc1d339ea21777377ddcb3", "format": 1 }, { @@ -6073,42 +6731,49 @@ "name": "plugins/modules/networks_pii_sm_owners_for_key_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "898359948fd849d4b388a11c1678466f44722c27eab7dbe1a74ad76f57f12da7", + "chksum_sha256": "efb843d5902ca3554d47275531f33ac1e43b94dbdaf325e36481c310cfbb865e", "format": 1 }, { "name": "plugins/modules/networks_firmware_upgrades_staged_events.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "3db0ae3618567bb63fca45d5fe3d4476ba546f9740a1ed2b2023cfb49689d058", + "chksum_sha256": "a2c3efb885a0d7c6515c9f1efe15c2eb66129d0c60f37ddd6ddbda6b26592100", "format": 1 }, { "name": "plugins/modules/networks_wireless_ssids_identity_psks.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "67feac0799d7c27b527230e0cea5fe0c1f2892aef0f762fd58d1eea1271160ac", + "chksum_sha256": "768192fea6c1b72a2504a95b035c053556e0705c8a513276de9e16de8bbed15a", "format": 1 }, { "name": "plugins/modules/networks_switch_dscp_to_cos_mappings_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "04e26bc9e6152ffc3d56b55cb17c65d15c128d36c919ba18dc7be1bfd27fe4d6", + "chksum_sha256": "0833b88f5083c731648498f8bc6a077abbe89eec122454c60b782a3b596ad0c9", "format": 1 }, { "name": "plugins/modules/networks_devices_claim.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "2040d0caad9dceafbb7d3df8f3e15baac286fd0aec054f0ecbe15e9109732321", + "chksum_sha256": "ef3ebf24406fe573a33c2a2775130e5ce5a3641af198b4d572d39d6ac37f6772", + "format": 1 + }, + { + "name": "plugins/modules/organizations_devices_availabilities_change_history_info.py", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "1c48bd116e6471f9358b768b3347a410a468367277448a56f6fdf6818772ea67", "format": 1 }, { "name": "plugins/modules/networks_switch_link_aggregations_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "de6143688d2ad3f230fc33eda591e82fe0f3adf8936bb4a756b3c27006f37223", + "chksum_sha256": "9442121efff4ae2cc30457848f3b4fdde7bab4fef27bc47942ee1cff8def209b", "format": 1 }, { @@ -6122,14 +6787,21 @@ "name": "plugins/modules/organizations_policy_objects_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "647dd5e555536b962e015753d494046fc671b30e81056b63ac600d68ad051c04", + "chksum_sha256": "0af599f6efd13aa58884e30e8dc2649c66befc1d234d716440363c5fbf93ee69", + "format": 1 + }, + { + "name": "plugins/modules/organizations_webhooks_callbacks_statuses_info.py", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "9ee835cda5753aad7e122c50047014942c9bc3f2b7662acec9bb88cf94cb5f09", "format": 1 }, { "name": "plugins/modules/organizations_policy_objects.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "011bf864532c358dc65072e5f62f4b75556f6affb79cf2ee74b0912e8dd046e7", + "chksum_sha256": "e8befa218614bd335df83761432382a13685bf369c276ef837c97cbc58cf0773", "format": 1 }, { @@ -6143,21 +6815,21 @@ "name": "plugins/modules/networks_events_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "97da99fb268666a45335331b1ab2666e371f7ee22c620eee62cb24f6b472dceb", + "chksum_sha256": "6f6e5168cd00b0e7332af70036cb829a484b08677c7f34cad676a6314d7070d0", "format": 1 }, { "name": "plugins/modules/networks_sm_users_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "a5a0166b067f62cae2b405bea36e44ed90f27b2d45618c48cda738a151d76a56", + "chksum_sha256": "6b6fb76a8d753b7691019e1242140dae5252192aaf41ce87df432e89f3871081", "format": 1 }, { "name": "plugins/modules/organizations_devices_statuses_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "5886b1be1f71c1839afdbbd4d5de4946da63c149e1199f6a68ad6512f61510a8", + "chksum_sha256": "efc58937ab5b63bd0a6a7a944a39d9ebb24e0feb41e0516056b163925080f738", "format": 1 }, { @@ -6171,63 +6843,84 @@ "name": "plugins/modules/networks_wireless_signal_quality_history_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "f62df5c3b8dcf3bdf92b5e7972961088b74cbccb28dec4fd40620974076c55c3", + "chksum_sha256": "576c271c3bb4f5466cc16ec4060ab6a008bd93a5364417068ab9185bdeb40dec", "format": 1 }, { "name": "plugins/modules/devices.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "ca1cf5ba5f312a2c9a8aa7af49e1dea28676febd9f9336c9417850be3f6e3496", + "chksum_sha256": "38a6c0e728f388963c8481ea5e12bd40bdea3692ece33b310925bb99349ac6b9", "format": 1 }, { "name": "plugins/modules/devices_switch_routing_interfaces_dhcp.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "6638bf22a6f7dd6e0a492625d43e9f16d912af5437175a5eccab2a866b67bdeb", + "chksum_sha256": "c4627a110eb6fb1fc7f9d4b01324b81d7ffa08ffd3fa201a2b7df59932fd79af", "format": 1 }, { "name": "plugins/modules/devices_camera_quality_and_retention_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "ee701e5de2b7e101d3f34942fc9bf4a29f6efd38fdbb4761c670654a5026d1fb", + "chksum_sha256": "bd3c482593ec55c85e4449d7d8ca7e1deadd9ea8ddea6a86a9a9fd25fbc70d18", "format": 1 }, { "name": "plugins/modules/organizations_policy_objects_groups_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "0f9eaeab0278a7195da936d234ddd964a14017e631a24da73ecd5a38a4a477a4", + "chksum_sha256": "c5faffd239c2104b386c96fd1dd747202f6bd525dd1c37cb9c97ed62cb8f4371", + "format": 1 + }, + { + "name": "plugins/modules/organizations_wireless_devices_channel_utilization_by_device_info.py", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "80527b1e380603bce62738d73f06eb09ff816ed4ebaa03785e41d588f05d4a48", "format": 1 }, { "name": "plugins/modules/networks_firmware_upgrades_staged_groups.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "da5c41de3f1342da617a28ecd4e094a5176ac103582e4d2deee8feef5c9009e1", + "chksum_sha256": "040c78668b28a01e972aaa1d57de1ce7760658d9573710b67c21a5019729fc7d", + "format": 1 + }, + { + "name": "plugins/modules/devices_live_tools_wake_on_lan.py", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "814ba53945f15a547a29f4ee05c0e14422cb4d817d67682a9ac6353f269d353e", "format": 1 }, { "name": "plugins/modules/organizations_inventory_onboarding_cloud_monitoring_imports_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "45d7102023596d97c168016073fb53b625cc997251f14aedc730db280a372b68", + "chksum_sha256": "e1e5a1e51a073e259b7170208f1d5ae79fcf9acd3d0f69b80225b848382d1cc7", + "format": 1 + }, + { + "name": "plugins/modules/networks_vlan_profiles_info.py", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "e0656dfaa14b4ee5df74be73c5a7e4a85d485108018dad78aa2099327f55144d", "format": 1 }, { "name": "plugins/modules/networks_wireless_ssids_device_type_group_policies_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "3f9b6288b1839553613469ad6a7c3b8bf095c51de279f0a051f76f21e7393009", + "chksum_sha256": "5ca0847bdcf1e4806ea7aa05d8c18acfdf318f31c6d87906df23e1a9a0ca1904", "format": 1 }, { "name": "plugins/modules/networks_traffic_analysis_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "8a67a170aac02cd4d3e5c40dd9cb5968d53dbb4d0c2618963a06687fb5c2f54e", + "chksum_sha256": "a246a840a0c398b7c6ac828c1bb27beedd1047d947f224901d9be4e9918cdd7b", "format": 1 }, { @@ -6241,182 +6934,245 @@ "name": "plugins/modules/networks_wireless_ssids_hotspot20_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "cc825fc113e0bd774b40a32affbe16094a8f3b7fb544bd2b66844b60029c9f99", + "chksum_sha256": "a09176608f2d5c06928dca76b183b4ed06f2f1b24462fb2dc270de15c9464eca", "format": 1 }, { "name": "plugins/modules/networks_appliance_security_intrusion.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "d85600f2ca06bd8484b086962947afedf0f87b6b7877f87490b50f351294f656", + "chksum_sha256": "3cbe6856cb38de39132b1df2866d0249467dd8f38c34068e62291ea32aa8bb4f", "format": 1 }, { "name": "plugins/modules/organizations_branding_policies_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "2baae211ca1fec55ec7339fd269b62e9b575115c390014a4e7001de32af86ca0", + "chksum_sha256": "a021d8c1e8223470822dbf5f301be4dc85e6453b1296fa3a6f5335564efd47a2", "format": 1 }, { "name": "plugins/modules/networks_cellular_gateway_dhcp_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "d1245fac6dc0814b709687f0ccf4e5f79ef0a4d8d734ac7f26d6e22cd7da8ba1", + "chksum_sha256": "6f69e575d6ebf03f729bfcc25a0056e0e1bfb81e262d009538c9689faeb73ce5", "format": 1 }, { "name": "plugins/modules/networks_pii_requests_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "e1a3712d761aeafddc07efe365bce1cf2e96f1cba27798f9b197d8d64879f469", + "chksum_sha256": "4a8dcbc3053a4e0d3d4f633d8486980aed417da797b6349226ac6c01608e322f", "format": 1 }, { "name": "plugins/modules/networks_switch_qos_rules_order_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "950fb368632dae6d28cb563cbbe16637ab29b1a7cb545c98ac51d7d020e86af2", + "chksum_sha256": "c29399575386fffba855d2de489f5620616b30cc2eabea6dc27a2d3008d10833", + "format": 1 + }, + { + "name": "plugins/modules/networks_sm_devices_install_apps.py", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "81597c6830356fada3054d551dff43ef1be8da04dea0366df33822c67f00a9e0", "format": 1 }, { "name": "plugins/modules/networks_appliance_vpn_site_to_site_vpn.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "91882fc7c89240c5de0b904bf465e0faf0d5b9fedca9a008ec78fe692893a78a", + "chksum_sha256": "4c22bb1233ccc98d276aa748eabe05fcd0fc3289b937b3100bebad7a63c72dc6", "format": 1 }, { "name": "plugins/modules/organizations_insight_applications_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "e362f8cd4efd599ef9152ac1dd4d05ce4390007003c9f5b3be9bc857e5459f7b", + "chksum_sha256": "6fca47ee77e8b54022648e0f98037c61759f89a88eaf7487eb8b5b4cb2bd4b4b", + "format": 1 + }, + { + "name": "plugins/modules/devices_appliance_radio_settings.py", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "f123c2658e619b94b26cc185f97df1912bc835de596f5edfd2c5a778b581031e", + "format": 1 + }, + { + "name": "plugins/modules/administered_licensing_subscription_subscriptions_claim_key_validate.py", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "7745937c08df7049c6aaa49b58a0821a8b66b64a0e49418a23efad19455f8155", "format": 1 }, { "name": "plugins/modules/networks_cellular_gateway_connectivity_monitoring_destinations_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "7c53f704d7de0d71ad9c67fb55219aadcf55cafa43e7ad2665509d32909524a6", + "chksum_sha256": "03745349388f756fb3f35db78ada46c244634becc82edb332ecfb4c4eaeca885", "format": 1 }, { "name": "plugins/modules/organizations_insight_monitored_media_servers.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "82b99cb733f0668e50c684209d92006323f64c6632188225f7b0aaabf2b53f26", + "chksum_sha256": "9dffb92e7a1bfb50313ac722c6ed3d41972d46909aa600ee8e0a659f40483472", "format": 1 }, { "name": "plugins/modules/devices_camera_custom_analytics_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "a047db46f71b609056c409ca3b6995ab85bfce652db656d3a78f010c5e128bcc", + "chksum_sha256": "efa3aaacefb575f025a3939a9f718947df6e9e99d99919edc4a6b8a8999de330", "format": 1 }, { "name": "plugins/modules/networks_appliance_firewall_l3_firewall_rules_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "77a011e5db0e991e9ffba39e13b8300b30a898a7e6d52dbab49697ab1e984b9e", + "chksum_sha256": "183835761a813eac17655d792371a95dc1e7ad1f5ecac108b44c5e89a601ea11", + "format": 1 + }, + { + "name": "plugins/modules/organizations_summary_top_networks_by_status_info.py", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "c3e5932826321db4d8ab2a3c03e9cc9a3442a896501c154b14db31cbad4b3d8c", "format": 1 }, { "name": "plugins/modules/organizations_clients_overview_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "acfb0ab72145201f2f41cfae6faa8308987846bba83d2f1e93f8ab6273f664eb", + "chksum_sha256": "6e9f3ebde3dfa37084c4be1ef3ff675b37ae210f6c951e19a8c9aa0b2c27ae7c", "format": 1 }, { "name": "plugins/modules/networks_appliance_firewall_firewalled_services_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "7360b8dde41408673bda6246fa2abf266bc56bd96920faa20d3194fc14db2033", + "chksum_sha256": "24121c0e04cf780b1249d96acb7da73958db7f766e8e608733c3496054c8f86d", + "format": 1 + }, + { + "name": "plugins/modules/networks_sm_devices_shutdown.py", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "3032c249e5a5d14da1adade739cc2aed13485dbee959ce1497056b731eca8b1f", + "format": 1 + }, + { + "name": "plugins/modules/organizations_wireless_devices_channel_utilization_by_network_info.py", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "6adc91643f839ba62f1f9dc514f2a7dcabe98d0a0bcef6a6c66f974eee39c495", "format": 1 }, { "name": "plugins/modules/devices_sensor_relationships.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "752c8eacf10957da5e834192433e25ffea9b036620c45c9736fb2e0200418368", + "chksum_sha256": "1d818aa08d96fc11d5b982f886f7d43a6527adcd75dab7bb89b5cb8c53f20742", + "format": 1 + }, + { + "name": "plugins/modules/organizations_sm_admins_roles.py", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "2e22e763e8cbf0137898739c0107cfb70024a41a53287194187d119f54fbbe6d", "format": 1 }, { "name": "plugins/modules/organizations_appliance_vpn_vpn_firewall_rules_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "ec6e07678781178da8c3adcab4376f1da5e95dfcc81c0f540da3903c0115bf48", + "chksum_sha256": "7785d449681bcced79de511e4c2ceb07696db1bb1a100ba4b284b95845f7591e", "format": 1 }, { "name": "plugins/modules/devices_switch_routing_static_routes_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "ad5fe129e02e3f3fc52529ea021abd3034a072fa7ad512b1bdfafad262866c88", + "chksum_sha256": "1ec8b1d327d13b891f46f14107efebeb9458e0f62405e090fe01069136d83517", "format": 1 }, { "name": "plugins/modules/organizations_inventory_onboarding_cloud_monitoring_imports.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "15ea7238f375b4328b75ffc8970b1e9ec5f10d2b692958a1ceccc7fa10d8f015", + "chksum_sha256": "3da09866fe5e3a7a184075141172cc0ccb4f869088e4a8dc090a572474c18865", "format": 1 }, { "name": "plugins/modules/organizations_firmware_upgrades_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "eddf56ee33c700f885981fc32e36ebf832164a37649fcf4339daa33a32e00685", + "chksum_sha256": "e22b5ac77b711b3b71ed4610d2234daf6d4fd2d57ee9c4ae7d8cbcefc4ea7b70", "format": 1 }, { "name": "plugins/modules/networks_sm_devices_unenroll.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "3a0f267dcd38f0d241fb9cc5761b2b7514c65eb5d330285c6f5386274530691a", + "chksum_sha256": "6da1b62f06e356ba1ef904beb4f479769a0b6e8f99bf649a0169a9f951532e4a", "format": 1 }, { "name": "plugins/modules/networks_wireless_settings_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "a55e0de93cff909b32f0d2398f866c187a744076160f64059c3b50742a6adde3", + "chksum_sha256": "3cfc73e417561e00d96e81bf78dc25ab66fbe0baec9843e2d43a3dcf52880e5f", + "format": 1 + }, + { + "name": "plugins/modules/organizations_devices_boots_history_info.py", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "447b9674f6b05d458526355f256a59e985c58ada2b7f208f4730b31599030b24", "format": 1 }, { "name": "plugins/modules/networks_sm_devices_performance_history_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "f906d2b6f38c3d808675bd9e85f0da4910ab2496397f3c035c2c114335fbac51", + "chksum_sha256": "5e6d926722465dd6abac1d2cc21478ec49e8e53819ae725cdeb2960053656214", "format": 1 }, { "name": "plugins/modules/networks_alerts_history_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "71ae6240abd5acdd953b1576aebbff42ea3c25c6a0f54537250188b8510b0125", + "chksum_sha256": "774cd0811b0e370f4e52435d64977842ba261b5a122c2bb2b0e8e780ee4542cd", + "format": 1 + }, + { + "name": "plugins/modules/organizations_appliance_uplinks_usage_by_network_info.py", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "f497177acabed7583022805ca2959b1924fd706d39e61681aa96a4ba43a68e1e", "format": 1 }, { "name": "plugins/modules/networks_wireless_ssids_traffic_shaping_rules.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "63bea9bd6416b3ad1607de1f137bdd5befc6be4e7940d9dcfe44a87cef2bc1cc", + "chksum_sha256": "47ba82d790aea43e7aefde38af711fdf5870460b3b097a6968e7f1f34e77c35d", "format": 1 }, { "name": "plugins/modules/organizations_api_requests_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "f11cab0cd2c66afd3712f8308dfac644ba7832d920d695c0a46320b3a80414dd", + "chksum_sha256": "467f12ec61ae15277244ab058bc237b8ede2bbbc9f77d6e047aa1c5c31b4444a", "format": 1 }, { "name": "plugins/modules/networks_appliance_vlans_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "15f18f9667e879d8d2ad4f1b544f76b13bbdef53509acb2f32021ef7c6d65c17", + "chksum_sha256": "75192e944db45ba42596aaf0d915c606a2c1c1a8b9099a5976b6916ad8f5bfe5", "format": 1 }, { @@ -6437,7 +7193,14 @@ "name": "plugins/modules/networks_appliance_prefixes_delegated_statics.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "fe325a87de497d8bdd59ec8c56214fb1e19d432732081342e25cb243dfe2385c", + "chksum_sha256": "e3463f0d31fa32d5d6cea87cf36c507cabbfc8cb7f398590d35e21032ed887d5", + "format": 1 + }, + { + "name": "plugins/modules/organizations_wireless_devices_channel_utilization_history_by_network_by_interval_info.py", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "57dc58557af3a462983c137ced638bde4e8acc3e8de9190a0e7ef7390edc8a25", "format": 1 }, { @@ -6451,28 +7214,49 @@ "name": "plugins/modules/organizations_clone.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "f7cfb36b507c938466d275dcaf946560250fa2b8723b3a1b58f3822e65cb800e", + "chksum_sha256": "91eeea9eda6a632864e1b7a407b1552466568ddbc5a65c072f270ad076bba052", "format": 1 }, { "name": "plugins/modules/devices_camera_video_link_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "dbeb7c2e68c830427412d62b9e9f32ac3ef922401a601d941c8a3432852f6f3e", + "chksum_sha256": "09d776c686f3d071ce68fac45efd5aa6e9bc543d37b703582d78ce6f60579b53", + "format": 1 + }, + { + "name": "plugins/modules/devices_live_tools_arp_table_info.py", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "182bb9cfacc809728b8fe0b8bf0c5238181d6a05433a64725e6c3baeadf7417b", + "format": 1 + }, + { + "name": "plugins/modules/administered_licensing_subscription_entitlements_info.py", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "b15eaeb68a68c5bbe705447ea6bf9a7c3f17b122844e48a2c6150df31e4496a7", + "format": 1 + }, + { + "name": "plugins/modules/organizations_wireless_devices_packet_loss_by_network_info.py", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "40f8a34eb529cb996e620dc82cf8ff782b7ea154a42746a7ee3b95e5719abd58", "format": 1 }, { "name": "plugins/modules/networks_appliance_vpn_site_to_site_vpn_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "407e1e1d38217dfeea66ca8bef64d1b4a3458cccce51d47559d6ae7375759a48", + "chksum_sha256": "e3ab5ba7f7131ff3416fdddbd09517cf65a686a76a7e05574d9fc45c232cfe33", "format": 1 }, { "name": "plugins/modules/networks_wireless_ssids_firewall_l3_firewall_rules.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "199581d1dac419fa4d01f24248b85b77455abf596f8cba5bf3c921b9cdb8422f", + "chksum_sha256": "2b09fe836ed03e3a1cc92c7e143cb7ea650399c4137c55206b576ca55a5fadb0", "format": 1 }, { @@ -8047,14 +8831,14 @@ "name": "changelogs/changelog.yaml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "992bbdddaec70a154eb09d649be360f10f23855871b73e27593b113317aa56c8", + "chksum_sha256": "0edb9769be2615fbd836b0e2163b3f1ac4a6a5a5c1d26e21d073a68e3a3121cb", "format": 1 }, { "name": "README.md", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "dab7eb97211ed7b3620fc89a9a52e8a5b6f910ebf5d9cee8684d8a6b3aebfcd0", + "chksum_sha256": "1783cef0d9bf0bc424d1cb9bf05cc3e6ead14b99c48a5cde79efdf46c11546e3", "format": 1 }, { @@ -8126,20 +8910,6 @@ "chksum_type": "sha256", "chksum_sha256": "41eb770f555c1ae50051e7fd5d13cb7546eb134c1d95f6b7572c2ad397dca546", "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": "d1be9315fe97520591ad6aca56c5b6ee625d3d2c84633de40f0f0afcc13a12a1", - "format": 1 } ], "format": 1 diff --git a/ansible_collections/cisco/meraki/MANIFEST.json b/ansible_collections/cisco/meraki/MANIFEST.json index 5b4fc1a92..6f671e250 100644 --- a/ansible_collections/cisco/meraki/MANIFEST.json +++ b/ansible_collections/cisco/meraki/MANIFEST.json @@ -2,7 +2,7 @@ "collection_info": { "namespace": "cisco", "name": "meraki", - "version": "2.17.2", + "version": "2.18.0", "authors": [ "Francisco Mu\u00f1oz ", "Bryan Vargas ", @@ -22,7 +22,7 @@ "license": [], "license_file": "LICENSE", "dependencies": { - "ansible.utils": ">=2.0.0,<4.0" + "ansible.utils": ">=2.0.0,<5.0" }, "repository": "https://github.com/meraki/dashboard-api-ansible", "documentation": "https://meraki.github.io/dashboard-api-ansible/", @@ -33,7 +33,7 @@ "name": "FILES.json", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "25a0e6b84e05b702fda09387109297a3491dd507f35fb966796b7f612b4a76af", + "chksum_sha256": "4c5636d16b861bfa135c614ab136a32cfe5ca9b0d639f5743d9136b2c3454ca8", "format": 1 }, "format": 1 diff --git a/ansible_collections/cisco/meraki/README.md b/ansible_collections/cisco/meraki/README.md index 56534396d..f7dc05f6a 100644 --- a/ansible_collections/cisco/meraki/README.md +++ b/ansible_collections/cisco/meraki/README.md @@ -1,117 +1,81 @@ -# Ansible Collection - cisco.meraki +# Ansible Modules for Meraki -## Ansible Modules for Meraki +The Meraki-Ansible project provides an Ansible collection for managing and automating your Cisco Meraki environment. It consists of a set of modules and roles for performing tasks related to Meraki. -The meraki-ansible project provides an Ansible collection for managing and automating your Cisco Meraki environment. It consists of a set of modules and roles for performing tasks related to Meraki. +# Quick Start Guide -This collection has been tested and supports Cisco Meraki v1.33.0 - -*Note: This collection is not compatible with versions of Ansible before v2.14.* - -Other versions of this collection have support for previous Cisco Meraki versions. The recommended versions are listed below on the [Compatibility matrix](https://github.com/meraki/dashboard-api-ansible#compatibility-matrix). - -## Compatibility matrix - -| Cisco Meraki version | Ansible "cisco.meraki" version | Python "DashboardAPI" version | -|--------------------------|------------------------------|-------------------------------| -| 1.33.0 | 2.17.0 |1.33.0 | - -*Notes*: - - -1. The "Python 'meraki' SDK version" column has the minimum recommended version used when testing the Ansible collection. This means you could use later versions of the Python "meraki" than those listed. -2. The "Cisco Meraki version" column has the value of the `meraki_version` you should use for the Ansible collection. - -## Installing according to Compatibility Matrix - -For example, for Cisco Meraki 1.33.0, it is recommended to use Ansible "cisco.meraki" v1.0.0 and Python "meraki DashboardAPI" v1.33.0. - -To get the Python Meraki SDK v1.33.0 in a fresh development environment: -``` -pip install meraki -``` - -To get the Ansible collection v1.0.0 in a fresh development environment: -``` -ansible-galaxy collection install cisco.meraki -f -``` - -## Requirements -- Ansible >= 2.9 -- [Python Meraki SDK](https://github.com/meraki/dashboard-api-python) v1.33.0 or newer -- Python >= 3.6, as the Meraki SDK doesn't support Python version 2.x - -## Install -Ansible must be installed ([Install guide](https://docs.ansible.com/ansible/latest/installation_guide/intro_installation.html)) +## Installation +1. Ansible must be installed ([Install guide](https://docs.ansible.com/ansible/latest/installation_guide/intro_installation.html)) ``` pip install ansible ``` -Python Meraki SDK must be installed +2. Python Meraki SDK must be installed ``` pip install meraki ``` -Install the collection ([Galaxy link](https://galaxy.ansible.com/cisco/meraki)) +3. Install the collection ([Galaxy link](https://galaxy.ansible.com/cisco/meraki)) ``` ansible-galaxy collection install cisco.meraki -f ``` -## Use -First, your Meraki API key needs to be available for the playbook to use. You can leverage environment variables `export MERAKI_DASHBOARD_API_KEY=093b24e85df15a3e66f1fc359f4c48493eaa1b73`, or create a `credentials.yml` ([example](https://github.com/meraki/dashboard-api-ansible/blob/main/playbooks/credentials.yml) file. +## Initial Configuration + +1. First, your Meraki API key needs to be available for the playbook to use. You can leverage environment variables `export MERAKI_DASHBOARD_API_KEY=6bec40cf957de430a6f1f2baa056b99a4fac9ea0`, or create a `credentials.yml` ([example](https://github.com/meraki/dashboard-api-ansible/blob/main/playbooks/credentials.yml) file. **Note:** Storing your API key in an unencrypted text file is not recommended for security reasons. -``` ---- -meraki_api_key: "ABC" -meraki_base_url: "https://api.meraki.com/api/v1" -meraki_single_request_timeout: "" -meraki_certificate_path: "" -meraki_requests_proxy: True -meraki_wait_on_rate_limit: 60 -meraki_nginx_429_retry_wait_time: 60 -meraki_action_batch_retry_wait_time: 60 -meraki_retry_4xx_error: False -meraki_retry_4xx_error_wait_time: 60 -meraki_maximum_retries: 2 -meraki_output_log: True -meraki_log_file_prefix: "meraki_api_" -meraki_log_path: "" -meraki_print_console: True -meraki_suppress_logging: False -meraki_simulate: False -meraki_be_geo_id: "" -meraki_caller: "" -meraki_use_iterator_for_get_pages: False -meraki_inherit_logging_config: False -``` - -Create a `hosts` ([example](https://github.com/meraki/dashboard-api-ansible/blob/main/playbooks/hosts)) file that uses `[meraki_servers]` with your Cisco Meraki Settings: +2. Create a `hosts` ([example](https://github.com/meraki/dashboard-api-ansible/blob/main/playbooks/hosts)) file that uses `[meraki_servers]` with your Cisco Meraki Settings: ``` [meraki_servers] meraki_server ``` - -Then, create a playbook `myplaybook.yml` ([example](https://github.com/meraki/dashboard-api-ansible/blob/main/playbooks/who_am_i.yml)) referencing the variables in your credentials.yml file and specifying the full namespace path to the module, plugin and/or role: +3. Running your first "Hello, world" in Ansible +Create a playbook `who_am_i.yml` ([example](https://github.com/meraki/dashboard-api-ansible/blob/main/playbooks/who_am_i.yml)): ``` --- -- hosts: localhost +- hosts: meraki_servers gather_facts: false tasks: - - name: Get all administered _identities _me + - name: Get my administered identities cisco.meraki.administered_identities_me_info: - meraki_suppress_logging: true register: result + - name: Show result + ansible.builtin.debug: + msg: "{{ result }}" ``` +This is a simple playbook that will (1) get the information about the Meraki admin user the API key belongs to and (2) print the information on the screen. Execute the playbook: ``` -ansible-playbook -i hosts myplaybook.yml +ansible-playbook -i hosts who_am_i.yml ``` -In the `playbooks` [directory](https://github.com/meraki/dashboard-api-ansible/blob/main/playbooks/) you can find more examples and use cases. +4. Congratulations! You have just run your first Ansible playbook! -### See Also: +- - - +# Detailed Information -* [Ansible Using collections](https://docs.ansible.com/ansible/latest/user_guide/collections_using.html) for more details. +This collection has been tested and supports Cisco Meraki Dashboard API v1.33.0 + +*Note: This collection is not compatible with versions of Ansible before v2.14.* + +Other versions of this collection have support for previous Cisco Meraki versions. The recommended versions are listed below on the [Compatibility matrix](https://github.com/meraki/dashboard-api-ansible#compatibility-matrix). + +## Compatibility matrix + +| Cisco Meraki version | Ansible "cisco.meraki" version | Python "DashboardAPI" version | +|--------------------------|------------------------------|-------------------------------| +| 1.33.0 | 2.17.0 |1.33.0 | +| 1.44.1 | 2.18.0 |1.44.1 | + +*Notes*: + +1. The "Python `meraki` SDK version" column has the minimum recommended version used when testing the Ansible collection. This means you could use later versions of the Python "meraki" than those listed. +2. The "Cisco Meraki version" column has the value of the `meraki_version` you should use for the Ansible collection. + +## Requirements +- Ansible >= 2.9 +- [Python Meraki SDK](https://github.com/meraki/dashboard-api-python) v1.33.0 or newer +- Python >= 3.6, as the Meraki SDK doesn't support Python version 2.x ## Attention macOS users @@ -128,6 +92,12 @@ If that's the case try setting this environment variable: export OBJC_DISABLE_INITIALIZE_FORK_SAFETY=YES ``` +## Additional Resources +1. [Meraki's Ansible Collection Documentation](https://docs.ansible.com/ansible/latest/collections/cisco/meraki/index.html) +2. [Meraki Dashboard API Documentation](https://meraki.io/api) +3. [DevNet Learning Lab](https://developer.cisco.com/learning/labs/meraki-dashboard-ansible/introduction/) +4. [DevNet Sandbox](https://devnetsandbox.cisco.com/RM/Diagram/Index/a9487767-deef-4855-b3e3-880e7f39eadc?diagramType=Topology) + ## Contributing to this collection Ongoing development efforts and contributions to this collection are tracked as issues in this repository. diff --git a/ansible_collections/cisco/meraki/changelogs/changelog.yaml b/ansible_collections/cisco/meraki/changelogs/changelog.yaml index 53b0eabca..9909009fc 100644 --- a/ansible_collections/cisco/meraki/changelogs/changelog.yaml +++ b/ansible_collections/cisco/meraki/changelogs/changelog.yaml @@ -1003,4 +1003,64 @@ releases: changes: bugfixes: - Adding `smartquotes = False` to `conf.py` and romoving `'` from rst files. - release_date: '2023-12-19' \ No newline at end of file + release_date: '2023-12-19' + 2.18.0: + changes: + minor_changes: + - Ansible collection now support v1.44.1 of Dashboard Api. + - administered_licensing_subscription_entitlements_info - new plugin. + - administered_licensing_subscription_subscriptions_bind - new plugin. + - administered_licensing_subscription_subscriptions_claim_key_validate - new plugin. + - administered_licensing_subscription_subscriptions_claim - new plugin. + - administered_licensing_subscription_subscriptions_compliance_statuses_info - new plugin. + - administered_licensing_subscription_subscriptions_info - new plugin. + - devices_appliance_radio_settings_info - new plugin. + - devices_appliance_radio_settings - new plugin. + - devices_live_tools_arp_table_info - new plugin. + - devices_live_tools_arp_table - new plugin. + - devices_live_tools_cable_test_info - new plugin. + - devices_live_tools_cable_test - new plugin. + - devices_live_tools_throughput_test_info - new plugin. + - devices_live_tools_throughput_test - new plugin. + - devices_live_tools_wake_on_lan_info - new plugin. + - devices_live_tools_wake_on_lan - new plugin. + - devices_wireless_alternate_management_interface_ipv6 - new plugin. + - networks_appliance_rf_profiles_info - new plugin. + - networks_appliance_rf_profiles - new plugin. + - networks_appliance_traffic_shaping_vpn_exclusions - new plugin. + - networks_sm_devices_install_apps - new plugin. + - networks_sm_devices_reboot - new plugin. + - networks_sm_devices_shutdown - new plugin. + - networks_sm_devices_uninstall_apps - new plugin. + - networks_vlan_profiles_assignments_by_device_info - new plugin. + - networks_vlan_profiles_assignments_reassign - new plugin. + - networks_vlan_profiles_info - new plugin. + - networks_vlan_profiles - new plugin. + - networks_wireless_ethernet_ports_profiles_assign - new plugin. + - networks_wireless_ethernet_ports_profiles_info - new plugin. + - networks_wireless_ethernet_ports_profiles_set_default - new plugin. + - networks_wireless_ethernet_ports_profiles - new plugin. + - organizations_appliance_traffic_shaping_vpn_exclusions_by_network_info - new plugin. + - organizations_appliance_uplinks_statuses_overview_info - new plugin. + - organizations_appliance_uplinks_usage_by_network_info - new plugin. + - organizations_camera_boundaries_areas_by_device_info - new plugin. + - organizations_camera_boundaries_lines_by_device_info - new plugin. + - organizations_camera_detections_history_by_boundary_by_interval_info - new plugin. + - organizations_camera_permissions_info - new plugin. + - organizations_camera_roles_info - new plugin. + - organizations_camera_roles - new plugin. + - organizations_devices_availabilities_change_history_info - new plugin. + - organizations_devices_boots_history_info - new plugin. + - organizations_sm_admins_roles_info - new plugin. + - organizations_sm_admins_roles - new plugin. + - organizations_sm_sentry_policies_assignments_by_network_info - new plugin. + - organizations_sm_sentry_policies_assignments - new plugin. + - organizations_summary_top_networks_by_status_info - new plugin. + - organizations_webhooks_callbacks_statuses_info - new plugin. + - organizations_wireless_devices_channel_utilization_by_device_info - new plugin. + - organizations_wireless_devices_channel_utilization_by_network_info - new plugin. + - organizations_wireless_devices_channel_utilization_history_by_device_by_interval_info - new plugin. + - organizations_wireless_devices_channel_utilization_history_by_network_by_interval_info - new plugin. + - organizations_wireless_devices_packet_loss_by_client_info - new plugin. + - organizations_wireless_devices_packet_loss_by_device_info - new plugin. + - organizations_wireless_devices_packet_loss_by_network_info - new plugin. \ No newline at end of file diff --git a/ansible_collections/cisco/meraki/plugins/action/administered_licensing_subscription_entitlements_info.py b/ansible_collections/cisco/meraki/plugins/action/administered_licensing_subscription_entitlements_info.py new file mode 100644 index 000000000..b5af8055e --- /dev/null +++ b/ansible_collections/cisco/meraki/plugins/action/administered_licensing_subscription_entitlements_info.py @@ -0,0 +1,90 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +# Copyright (c) 2021, Cisco Systems +# 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 +from ansible.plugins.action import ActionBase +try: + from ansible_collections.ansible.utils.plugins.module_utils.common.argspec_validate import ( + AnsibleArgSpecValidator, + ) +except ImportError: + ANSIBLE_UTILS_IS_INSTALLED = False +else: + ANSIBLE_UTILS_IS_INSTALLED = True +from ansible.errors import AnsibleActionFail +from ansible_collections.cisco.meraki.plugins.plugin_utils.meraki import ( + MERAKI, + meraki_argument_spec, +) + +# Get common arguments specification +argument_spec = meraki_argument_spec() +# Add arguments specific for this module +argument_spec.update(dict( + skus=dict(type="list"), +)) + +required_if = [] +required_one_of = [] +mutually_exclusive = [] +required_together = [] + + +class ActionModule(ActionBase): + def __init__(self, *args, **kwargs): + if not ANSIBLE_UTILS_IS_INSTALLED: + raise AnsibleActionFail( + "ansible.utils is not installed. Execute 'ansible-galaxy collection install ansible.utils'") + super(ActionModule, self).__init__(*args, **kwargs) + self._supports_async = False + self._supports_check_mode = True + self._result = None + + # Checks the supplied parameters against the argument spec for this module + def _check_argspec(self): + aav = AnsibleArgSpecValidator( + data=self._task.args, + schema=dict(argument_spec=argument_spec), + schema_format="argspec", + schema_conditionals=dict( + required_if=required_if, + required_one_of=required_one_of, + mutually_exclusive=mutually_exclusive, + required_together=required_together, + ), + name=self._task.action, + ) + valid, errors, self._task.args = aav.validate() + if not valid: + raise AnsibleActionFail(errors) + + def get_all(self, params): + new_object = {} + if params.get("skus") is not None: + new_object["skus"] = params.get( + "skus") + + return new_object + + def run(self, tmp=None, task_vars=None): + self._task.diff = False + self._result = super(ActionModule, self).run(tmp, task_vars) + self._result["changed"] = False + self._check_argspec() + + self._result.update(dict(meraki_response={})) + + meraki = MERAKI(params=self._task.args) + + response = meraki.exec_meraki( + family="licensing", + function='getAdministeredLicensingSubscriptionEntitlements', + params=self.get_all(self._task.args), + ) + self._result.update(dict(meraki_response=response)) + self._result.update(meraki.exit_json()) + return self._result diff --git a/ansible_collections/cisco/meraki/plugins/action/administered_licensing_subscription_subscriptions_bind.py b/ansible_collections/cisco/meraki/plugins/action/administered_licensing_subscription_subscriptions_bind.py new file mode 100644 index 000000000..e3cc7eba1 --- /dev/null +++ b/ansible_collections/cisco/meraki/plugins/action/administered_licensing_subscription_subscriptions_bind.py @@ -0,0 +1,91 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +# Copyright (c) 2021, Cisco Systems +# 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 +from ansible.plugins.action import ActionBase +try: + from ansible_collections.ansible.utils.plugins.module_utils.common.argspec_validate import ( + AnsibleArgSpecValidator, + ) +except ImportError: + ANSIBLE_UTILS_IS_INSTALLED = False +else: + ANSIBLE_UTILS_IS_INSTALLED = True +from ansible.errors import AnsibleActionFail +from ansible_collections.cisco.meraki.plugins.plugin_utils.meraki import ( + MERAKI, + meraki_argument_spec, +) + +# Get common arguements specification +argument_spec = meraki_argument_spec() +# Add arguments specific for this module +argument_spec.update(dict( + networkIds=dict(type="list"), + subscriptionId=dict(type="str"), + validate=dict(type="bool"), +)) + +required_if = [] +required_one_of = [] +mutually_exclusive = [] +required_together = [] + + +class ActionModule(ActionBase): + def __init__(self, *args, **kwargs): + if not ANSIBLE_UTILS_IS_INSTALLED: + raise AnsibleActionFail( + "ansible.utils is not installed. Execute 'ansible-galaxy collection install ansible.utils'") + super(ActionModule, self).__init__(*args, **kwargs) + self._supports_async = False + self._supports_check_mode = False + self._result = None + + # Checks the supplied parameters against the argument spec for this module + def _check_argspec(self): + aav = AnsibleArgSpecValidator( + data=self._task.args, + schema=dict(argument_spec=argument_spec), + schema_format="argspec", + schema_conditionals=dict( + required_if=required_if, + required_one_of=required_one_of, + mutually_exclusive=mutually_exclusive, + required_together=required_together, + ), + name=self._task.action, + ) + valid, errors, self._task.args = aav.validate() + if not valid: + raise AnsibleActionFail(errors) + + def get_object(self, params): + new_object = dict( + networkIds=params.get("networkIds"), + subscription_id=params.get("subscriptionId"), + validate=params.get("validate"), + ) + return new_object + + def run(self, tmp=None, task_vars=None): + self._task.diff = False + self._result = super(ActionModule, self).run(tmp, task_vars) + self._result["changed"] = False + self._check_argspec() + + meraki = MERAKI(params=self._task.args) + + response = meraki.exec_meraki( + family="licensing", + function='bindAdministeredLicensingSubscriptionSubscription', + op_modifies=True, + params=self.get_object(self._task.args), + ) + self._result.update(dict(meraki_response=response)) + self._result.update(meraki.exit_json()) + return self._result diff --git a/ansible_collections/cisco/meraki/plugins/action/administered_licensing_subscription_subscriptions_claim.py b/ansible_collections/cisco/meraki/plugins/action/administered_licensing_subscription_subscriptions_claim.py new file mode 100644 index 000000000..cf02a8ac6 --- /dev/null +++ b/ansible_collections/cisco/meraki/plugins/action/administered_licensing_subscription_subscriptions_claim.py @@ -0,0 +1,95 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +# Copyright (c) 2021, Cisco Systems +# 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 +from ansible.plugins.action import ActionBase +try: + from ansible_collections.ansible.utils.plugins.module_utils.common.argspec_validate import ( + AnsibleArgSpecValidator, + ) +except ImportError: + ANSIBLE_UTILS_IS_INSTALLED = False +else: + ANSIBLE_UTILS_IS_INSTALLED = True +from ansible.errors import AnsibleActionFail +from ansible_collections.cisco.meraki.plugins.plugin_utils.meraki import ( + MERAKI, + meraki_argument_spec, +) + +# Get common arguements specification +argument_spec = meraki_argument_spec() +# Add arguments specific for this module +argument_spec.update(dict( + claimKey=dict(type="str"), + description=dict(type="str"), + name=dict(type="str"), + organizationId=dict(type="str"), + validate=dict(type="bool"), +)) + +required_if = [] +required_one_of = [] +mutually_exclusive = [] +required_together = [] + + +class ActionModule(ActionBase): + def __init__(self, *args, **kwargs): + if not ANSIBLE_UTILS_IS_INSTALLED: + raise AnsibleActionFail( + "ansible.utils is not installed. Execute 'ansible-galaxy collection install ansible.utils'") + super(ActionModule, self).__init__(*args, **kwargs) + self._supports_async = False + self._supports_check_mode = False + self._result = None + + # Checks the supplied parameters against the argument spec for this module + def _check_argspec(self): + aav = AnsibleArgSpecValidator( + data=self._task.args, + schema=dict(argument_spec=argument_spec), + schema_format="argspec", + schema_conditionals=dict( + required_if=required_if, + required_one_of=required_one_of, + mutually_exclusive=mutually_exclusive, + required_together=required_together, + ), + name=self._task.action, + ) + valid, errors, self._task.args = aav.validate() + if not valid: + raise AnsibleActionFail(errors) + + def get_object(self, params): + new_object = dict( + claimKey=params.get("claimKey"), + description=params.get("description"), + name=params.get("name"), + organizationId=params.get("organizationId"), + validate=params.get("validate"), + ) + return new_object + + def run(self, tmp=None, task_vars=None): + self._task.diff = False + self._result = super(ActionModule, self).run(tmp, task_vars) + self._result["changed"] = False + self._check_argspec() + + meraki = MERAKI(params=self._task.args) + + response = meraki.exec_meraki( + family="licensing", + function='claimAdministeredLicensingSubscriptionSubscriptions', + op_modifies=True, + params=self.get_object(self._task.args), + ) + self._result.update(dict(meraki_response=response)) + self._result.update(meraki.exit_json()) + return self._result diff --git a/ansible_collections/cisco/meraki/plugins/action/administered_licensing_subscription_subscriptions_claim_key_validate.py b/ansible_collections/cisco/meraki/plugins/action/administered_licensing_subscription_subscriptions_claim_key_validate.py new file mode 100644 index 000000000..9113049d7 --- /dev/null +++ b/ansible_collections/cisco/meraki/plugins/action/administered_licensing_subscription_subscriptions_claim_key_validate.py @@ -0,0 +1,87 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +# Copyright (c) 2021, Cisco Systems +# 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 +from ansible.plugins.action import ActionBase +try: + from ansible_collections.ansible.utils.plugins.module_utils.common.argspec_validate import ( + AnsibleArgSpecValidator, + ) +except ImportError: + ANSIBLE_UTILS_IS_INSTALLED = False +else: + ANSIBLE_UTILS_IS_INSTALLED = True +from ansible.errors import AnsibleActionFail +from ansible_collections.cisco.meraki.plugins.plugin_utils.meraki import ( + MERAKI, + meraki_argument_spec, +) + +# Get common arguements specification +argument_spec = meraki_argument_spec() +# Add arguments specific for this module +argument_spec.update(dict( + claimKey=dict(type="str"), +)) + +required_if = [] +required_one_of = [] +mutually_exclusive = [] +required_together = [] + + +class ActionModule(ActionBase): + def __init__(self, *args, **kwargs): + if not ANSIBLE_UTILS_IS_INSTALLED: + raise AnsibleActionFail( + "ansible.utils is not installed. Execute 'ansible-galaxy collection install ansible.utils'") + super(ActionModule, self).__init__(*args, **kwargs) + self._supports_async = False + self._supports_check_mode = False + self._result = None + + # Checks the supplied parameters against the argument spec for this module + def _check_argspec(self): + aav = AnsibleArgSpecValidator( + data=self._task.args, + schema=dict(argument_spec=argument_spec), + schema_format="argspec", + schema_conditionals=dict( + required_if=required_if, + required_one_of=required_one_of, + mutually_exclusive=mutually_exclusive, + required_together=required_together, + ), + name=self._task.action, + ) + valid, errors, self._task.args = aav.validate() + if not valid: + raise AnsibleActionFail(errors) + + def get_object(self, params): + new_object = dict( + claimKey=params.get("claimKey"), + ) + return new_object + + def run(self, tmp=None, task_vars=None): + self._task.diff = False + self._result = super(ActionModule, self).run(tmp, task_vars) + self._result["changed"] = False + self._check_argspec() + + meraki = MERAKI(params=self._task.args) + + response = meraki.exec_meraki( + family="licensing", + function='validateAdministeredLicensingSubscriptionSubscriptionsClaimKey', + op_modifies=True, + params=self.get_object(self._task.args), + ) + self._result.update(dict(meraki_response=response)) + self._result.update(meraki.exit_json()) + return self._result diff --git a/ansible_collections/cisco/meraki/plugins/action/administered_licensing_subscription_subscriptions_compliance_statuses_info.py b/ansible_collections/cisco/meraki/plugins/action/administered_licensing_subscription_subscriptions_compliance_statuses_info.py new file mode 100644 index 000000000..ec2d035ab --- /dev/null +++ b/ansible_collections/cisco/meraki/plugins/action/administered_licensing_subscription_subscriptions_compliance_statuses_info.py @@ -0,0 +1,94 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +# Copyright (c) 2021, Cisco Systems +# 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 +from ansible.plugins.action import ActionBase +try: + from ansible_collections.ansible.utils.plugins.module_utils.common.argspec_validate import ( + AnsibleArgSpecValidator, + ) +except ImportError: + ANSIBLE_UTILS_IS_INSTALLED = False +else: + ANSIBLE_UTILS_IS_INSTALLED = True +from ansible.errors import AnsibleActionFail +from ansible_collections.cisco.meraki.plugins.plugin_utils.meraki import ( + MERAKI, + meraki_argument_spec, +) + +# Get common arguments specification +argument_spec = meraki_argument_spec() +# Add arguments specific for this module +argument_spec.update(dict( + organizationIds=dict(type="list"), + subscriptionIds=dict(type="list"), +)) + +required_if = [] +required_one_of = [] +mutually_exclusive = [] +required_together = [] + + +class ActionModule(ActionBase): + def __init__(self, *args, **kwargs): + if not ANSIBLE_UTILS_IS_INSTALLED: + raise AnsibleActionFail( + "ansible.utils is not installed. Execute 'ansible-galaxy collection install ansible.utils'") + super(ActionModule, self).__init__(*args, **kwargs) + self._supports_async = False + self._supports_check_mode = True + self._result = None + + # Checks the supplied parameters against the argument spec for this module + def _check_argspec(self): + aav = AnsibleArgSpecValidator( + data=self._task.args, + schema=dict(argument_spec=argument_spec), + schema_format="argspec", + schema_conditionals=dict( + required_if=required_if, + required_one_of=required_one_of, + mutually_exclusive=mutually_exclusive, + required_together=required_together, + ), + name=self._task.action, + ) + valid, errors, self._task.args = aav.validate() + if not valid: + raise AnsibleActionFail(errors) + + def get_all(self, params): + new_object = {} + if params.get("organizationIds") is not None: + new_object["organizationIds"] = params.get( + "organizationIds") + if params.get("subscriptionIds") is not None: + new_object["subscriptionIds"] = params.get( + "subscriptionIds") + + return new_object + + def run(self, tmp=None, task_vars=None): + self._task.diff = False + self._result = super(ActionModule, self).run(tmp, task_vars) + self._result["changed"] = False + self._check_argspec() + + self._result.update(dict(meraki_response={})) + + meraki = MERAKI(params=self._task.args) + + response = meraki.exec_meraki( + family="licensing", + function='getAdministeredLicensingSubscriptionSubscriptionsComplianceStatuses', + params=self.get_all(self._task.args), + ) + self._result.update(dict(meraki_response=response)) + self._result.update(meraki.exit_json()) + return self._result diff --git a/ansible_collections/cisco/meraki/plugins/action/administered_licensing_subscription_subscriptions_info.py b/ansible_collections/cisco/meraki/plugins/action/administered_licensing_subscription_subscriptions_info.py new file mode 100644 index 000000000..8be76a060 --- /dev/null +++ b/ansible_collections/cisco/meraki/plugins/action/administered_licensing_subscription_subscriptions_info.py @@ -0,0 +1,128 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +# Copyright (c) 2021, Cisco Systems +# 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 +from ansible.plugins.action import ActionBase +try: + from ansible_collections.ansible.utils.plugins.module_utils.common.argspec_validate import ( + AnsibleArgSpecValidator, + ) +except ImportError: + ANSIBLE_UTILS_IS_INSTALLED = False +else: + ANSIBLE_UTILS_IS_INSTALLED = True +from ansible.errors import AnsibleActionFail +from ansible_collections.cisco.meraki.plugins.plugin_utils.meraki import ( + MERAKI, + meraki_argument_spec, +) + +# Get common arguments specification +argument_spec = meraki_argument_spec() +# Add arguments specific for this module +argument_spec.update(dict( + perPage=dict(type="int"), + total_pages=dict(type="int"), + direction=dict(type="str"), + startingAfter=dict(type="str"), + endingBefore=dict(type="str"), + subscriptionIds=dict(type="list"), + organizationIds=dict(type="list"), + statuses=dict(type="list"), + productTypes=dict(type="list"), + startDate=dict(type="str"), + endDate=dict(type="str"), +)) + +required_if = [] +required_one_of = [] +mutually_exclusive = [] +required_together = [] + + +class ActionModule(ActionBase): + def __init__(self, *args, **kwargs): + if not ANSIBLE_UTILS_IS_INSTALLED: + raise AnsibleActionFail( + "ansible.utils is not installed. Execute 'ansible-galaxy collection install ansible.utils'") + super(ActionModule, self).__init__(*args, **kwargs) + self._supports_async = False + self._supports_check_mode = True + self._result = None + + # Checks the supplied parameters against the argument spec for this module + def _check_argspec(self): + aav = AnsibleArgSpecValidator( + data=self._task.args, + schema=dict(argument_spec=argument_spec), + schema_format="argspec", + schema_conditionals=dict( + required_if=required_if, + required_one_of=required_one_of, + mutually_exclusive=mutually_exclusive, + required_together=required_together, + ), + name=self._task.action, + ) + valid, errors, self._task.args = aav.validate() + if not valid: + raise AnsibleActionFail(errors) + + def get_all(self, params): + new_object = {} + if params.get("perPage") is not None: + new_object["perPage"] = params.get( + "perPage") + new_object['total_pages'] = params.get( + "total_pages") or 1 + new_object['direction'] = params.get( + "direction") or "next" + if params.get("startingAfter") is not None: + new_object["startingAfter"] = params.get( + "startingAfter") + if params.get("endingBefore") is not None: + new_object["endingBefore"] = params.get( + "endingBefore") + if params.get("subscriptionIds") is not None: + new_object["subscriptionIds"] = params.get( + "subscriptionIds") + if params.get("organizationIds") is not None: + new_object["organizationIds"] = params.get( + "organizationIds") + if params.get("statuses") is not None: + new_object["statuses"] = params.get( + "statuses") + if params.get("productTypes") is not None: + new_object["productTypes"] = params.get( + "productTypes") + if params.get("startDate") is not None: + new_object["startDate"] = params.get( + "startDate") + if params.get("endDate") is not None: + new_object["endDate"] = params.get( + "endDate") + + return new_object + + def run(self, tmp=None, task_vars=None): + self._task.diff = False + self._result = super(ActionModule, self).run(tmp, task_vars) + self._result["changed"] = False + self._check_argspec() + + self._result.update(dict(meraki_response={})) + + meraki = MERAKI(params=self._task.args) + + response = meraki.exec_meraki( + family="licensing", + function='getAdministeredLicensingSubscriptionSubscriptions', + params=self.get_all(self._task.args), + ) + self._result.update(dict(meraki_response=response)) + self._result.update(meraki.exit_json()) + return self._result diff --git a/ansible_collections/cisco/meraki/plugins/action/devices.py b/ansible_collections/cisco/meraki/plugins/action/devices.py index df0edfd10..49d41b1a7 100644 --- a/ansible_collections/cisco/meraki/plugins/action/devices.py +++ b/ansible_collections/cisco/meraki/plugins/action/devices.py @@ -32,16 +32,15 @@ argument_spec = meraki_argument_spec() # Add arguments specific for this module argument_spec.update(dict( state=dict(type="str", default="present", choices=["present"]), - name=dict(type="str"), - tags=dict(type="list"), + address=dict(type="str"), + floorPlanId=dict(type="str"), lat=dict(type="float"), lng=dict(type="float"), - address=dict(type="str"), - notes=dict(type="str"), moveMapMarker=dict(type="bool"), + name=dict(type="str"), + notes=dict(type="str"), switchProfileId=dict(type="str"), - floorPlanId=dict(type="str"), - mac=dict(type="str"), + tags=dict(type="list"), serial=dict(type="str"), organizationId=dict(type="str"), )) @@ -58,16 +57,15 @@ class Devices(object): def __init__(self, params, meraki): self.meraki = meraki self.new_object = dict( - name=params.get("name"), - tags=params.get("tags"), + address=params.get("address"), + floorPlanId=params.get("floorPlanId"), lat=params.get("lat"), lng=params.get("lng"), - address=params.get("address"), - notes=params.get("notes"), moveMapMarker=params.get("moveMapMarker"), + name=params.get("name"), + notes=params.get("notes"), switchProfileId=params.get("switchProfileId"), - floorPlanId=params.get("floorPlanId"), - mac=params.get("mac"), + tags=params.get("tags"), serial=params.get("serial"), organization_id=params.get("organizationId"), ) @@ -130,36 +128,32 @@ class Devices(object): def update_by_id_params(self): new_object_params = {} - if self.new_object.get('name') is not None or self.new_object.get('name') is not None: - new_object_params['name'] = self.new_object.get('name') or \ - self.new_object.get('name') - if self.new_object.get('tags') is not None or self.new_object.get('tags') is not None: - new_object_params['tags'] = self.new_object.get('tags') or \ - self.new_object.get('tags') + if self.new_object.get('address') is not None or self.new_object.get('address') is not None: + new_object_params['address'] = self.new_object.get('address') or \ + self.new_object.get('address') + if self.new_object.get('floorPlanId') is not None or self.new_object.get('floor_plan_id') is not None: + new_object_params['floorPlanId'] = self.new_object.get('floorPlanId') or \ + self.new_object.get('floor_plan_id') if self.new_object.get('lat') is not None or self.new_object.get('lat') is not None: new_object_params['lat'] = self.new_object.get('lat') or \ self.new_object.get('lat') if self.new_object.get('lng') is not None or self.new_object.get('lng') is not None: new_object_params['lng'] = self.new_object.get('lng') or \ self.new_object.get('lng') - if self.new_object.get('address') is not None or self.new_object.get('address') is not None: - new_object_params['address'] = self.new_object.get('address') or \ - self.new_object.get('address') + if self.new_object.get('moveMapMarker') is not None or self.new_object.get('move_map_marker') is not None: + new_object_params['moveMapMarker'] = self.new_object.get('moveMapMarker') + if self.new_object.get('name') is not None or self.new_object.get('name') is not None: + new_object_params['name'] = self.new_object.get('name') or \ + self.new_object.get('name') if self.new_object.get('notes') is not None or self.new_object.get('notes') is not None: new_object_params['notes'] = self.new_object.get('notes') or \ self.new_object.get('notes') - if self.new_object.get('moveMapMarker') is not None or self.new_object.get('move_map_marker') is not None: - new_object_params['moveMapMarker'] = self.new_object.get( - 'moveMapMarker') if self.new_object.get('switchProfileId') is not None or self.new_object.get('switch_profile_id') is not None: new_object_params['switchProfileId'] = self.new_object.get('switchProfileId') or \ self.new_object.get('switch_profile_id') - if self.new_object.get('floorPlanId') is not None or self.new_object.get('floor_plan_id') is not None: - new_object_params['floorPlanId'] = self.new_object.get('floorPlanId') or \ - self.new_object.get('floor_plan_id') - if self.new_object.get('mac') is not None or self.new_object.get('mac') is not None: - new_object_params['mac'] = self.new_object.get('mac') or \ - self.new_object.get('mac') + if self.new_object.get('tags') is not None or self.new_object.get('tags') is not None: + new_object_params['tags'] = self.new_object.get('tags') or \ + self.new_object.get('tags') if self.new_object.get('serial') is not None or self.new_object.get('serial') is not None: new_object_params['serial'] = self.new_object.get('serial') or \ self.new_object.get('serial') @@ -238,16 +232,15 @@ class Devices(object): requested_obj = self.new_object obj_params = [ - ("name", "name"), - ("tags", "tags"), + ("address", "address"), + ("floorPlanId", "floorPlanId"), ("lat", "lat"), ("lng", "lng"), - ("address", "address"), - ("notes", "notes"), ("moveMapMarker", "moveMapMarker"), + ("name", "name"), + ("notes", "notes"), ("switchProfileId", "switchProfileId"), - ("floorPlanId", "floorPlanId"), - ("mac", "mac"), + ("tags", "tags"), ("serial", "serial"), ("organizationId", "organizationId"), ] diff --git a/ansible_collections/cisco/meraki/plugins/action/devices_appliance_radio_settings.py b/ansible_collections/cisco/meraki/plugins/action/devices_appliance_radio_settings.py new file mode 100644 index 000000000..783ba4821 --- /dev/null +++ b/ansible_collections/cisco/meraki/plugins/action/devices_appliance_radio_settings.py @@ -0,0 +1,211 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +# Copyright (c) 2021, Cisco Systems +# 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 +from ansible.plugins.action import ActionBase +try: + from ansible_collections.ansible.utils.plugins.module_utils.common.argspec_validate import ( + AnsibleArgSpecValidator, + ) +except ImportError: + ANSIBLE_UTILS_IS_INSTALLED = False +else: + ANSIBLE_UTILS_IS_INSTALLED = True +from ansible.errors import AnsibleActionFail +from ansible_collections.cisco.meraki.plugins.plugin_utils.meraki import ( + MERAKI, + meraki_argument_spec, + meraki_compare_equality, + get_dict_result, +) +from ansible_collections.cisco.meraki.plugins.plugin_utils.exceptions import ( + InconsistentParameters, +) + +# Get common arguments specification +argument_spec = meraki_argument_spec() +# Add arguments specific for this module +argument_spec.update(dict( + state=dict(type="str", default="present", choices=["present"]), + fiveGhzSettings=dict(type="dict"), + rfProfileId=dict(type="str"), + twoFourGhzSettings=dict(type="dict"), + serial=dict(type="str"), +)) + +required_if = [ + ("state", "present", ["serial"], True), +] +required_one_of = [] +mutually_exclusive = [] +required_together = [] + + +class DevicesApplianceRadioSettings(object): + def __init__(self, params, meraki): + self.meraki = meraki + self.new_object = dict( + fiveGhzSettings=params.get("fiveGhzSettings"), + rfProfileId=params.get("rfProfileId"), + twoFourGhzSettings=params.get("twoFourGhzSettings"), + serial=params.get("serial"), + ) + + def get_all_params(self, name=None, id=None): + new_object_params = {} + if self.new_object.get('serial') is not None or self.new_object.get('serial') is not None: + new_object_params['serial'] = self.new_object.get('serial') + return new_object_params + + def update_all_params(self): + new_object_params = {} + if self.new_object.get('fiveGhzSettings') is not None or self.new_object.get('five_ghz_settings') is not None: + new_object_params['fiveGhzSettings'] = self.new_object.get('fiveGhzSettings') or \ + self.new_object.get('five_ghz_settings') + if self.new_object.get('rfProfileId') is not None or self.new_object.get('rf_profile_id') is not None: + new_object_params['rfProfileId'] = self.new_object.get('rfProfileId') or \ + self.new_object.get('rf_profile_id') + if self.new_object.get('twoFourGhzSettings') is not None or self.new_object.get('two_four_ghz_settings') is not None: + new_object_params['twoFourGhzSettings'] = self.new_object.get('twoFourGhzSettings') or \ + self.new_object.get('two_four_ghz_settings') + if self.new_object.get('serial') is not None or self.new_object.get('serial') is not None: + new_object_params['serial'] = self.new_object.get('serial') or \ + self.new_object.get('serial') + return new_object_params + + def get_object_by_name(self, name): + result = None + # NOTE: Does not have a get by name method, using get all + try: + items = self.meraki.exec_meraki( + family="appliance", + function="getDeviceApplianceRadioSettings", + params=self.get_all_params(name=name), + ) + if isinstance(items, dict): + if 'response' in items: + items = items.get('response') + result = get_dict_result(items, 'name', name) + if result is None: + result = items + except Exception as e: + print("Error: ", e) + result = None + return result + + def get_object_by_id(self, id): + result = None + # NOTE: Does not have a get by id method or it is in another action + return result + + def exists(self): + prev_obj = None + id_exists = False + name_exists = False + o_id = self.new_object.get("serial") + name = self.new_object.get("name") + if o_id: + prev_obj = self.get_object_by_name(o_id) + id_exists = prev_obj is not None and isinstance(prev_obj, dict) + if not id_exists and name: + prev_obj = self.get_object_by_name(name) + name_exists = prev_obj is not None and isinstance(prev_obj, dict) + if name_exists: + _id = prev_obj.get("id") + if id_exists and name_exists and o_id != _id: + raise InconsistentParameters( + "The 'id' and 'name' params don't refer to the same object") + if _id: + self.new_object.update(dict(id=_id)) + it_exists = prev_obj is not None and isinstance(prev_obj, dict) + return (it_exists, prev_obj) + + def requires_update(self, current_obj): + requested_obj = self.new_object + + obj_params = [ + ("fiveGhzSettings", "fiveGhzSettings"), + ("rfProfileId", "rfProfileId"), + ("twoFourGhzSettings", "twoFourGhzSettings"), + ("serial", "serial"), + ] + # Method 1. Params present in request (Ansible) obj are the same as the current (ISE) params + # If any does not have eq params, it requires update + return any(not meraki_compare_equality(current_obj.get(meraki_param), + requested_obj.get(ansible_param)) + for (meraki_param, ansible_param) in obj_params) + + def update(self): + id = self.new_object.get("id") + name = self.new_object.get("name") + result = None + result = self.meraki.exec_meraki( + family="appliance", + function="updateDeviceApplianceRadioSettings", + params=self.update_all_params(), + op_modifies=True, + ) + return result + + +class ActionModule(ActionBase): + def __init__(self, *args, **kwargs): + if not ANSIBLE_UTILS_IS_INSTALLED: + raise AnsibleActionFail( + "ansible.utils is not installed. Execute 'ansible-galaxy collection install ansible.utils'") + super(ActionModule, self).__init__(*args, **kwargs) + self._supports_async = False + self._supports_check_mode = False + self._result = None + + # Checks the supplied parameters against the argument spec for this module + def _check_argspec(self): + aav = AnsibleArgSpecValidator( + data=self._task.args, + schema=dict(argument_spec=argument_spec), + schema_format="argspec", + schema_conditionals=dict( + required_if=required_if, + required_one_of=required_one_of, + mutually_exclusive=mutually_exclusive, + required_together=required_together, + ), + name=self._task.action, + ) + valid, errors, self._task.args = aav.validate() + if not valid: + raise AnsibleActionFail(errors) + + def run(self, tmp=None, task_vars=None): + self._task.diff = False + self._result = super(ActionModule, self).run(tmp, task_vars) + self._result["changed"] = False + self._check_argspec() + + meraki = MERAKI(self._task.args) + obj = DevicesApplianceRadioSettings(self._task.args, meraki) + + state = self._task.args.get("state") + + response = None + if state == "present": + (obj_exists, prev_obj) = obj.exists() + if obj_exists: + if obj.requires_update(prev_obj): + response = obj.update() + meraki.object_updated() + else: + response = prev_obj + meraki.object_already_present() + else: + meraki.fail_json( + "Object does not exists, plugin only has update") + + self._result.update(dict(meraki_response=response)) + self._result.update(meraki.exit_json()) + return self._result diff --git a/ansible_collections/cisco/meraki/plugins/action/devices_appliance_radio_settings_info.py b/ansible_collections/cisco/meraki/plugins/action/devices_appliance_radio_settings_info.py new file mode 100644 index 000000000..2ac8e4768 --- /dev/null +++ b/ansible_collections/cisco/meraki/plugins/action/devices_appliance_radio_settings_info.py @@ -0,0 +1,90 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +# Copyright (c) 2021, Cisco Systems +# 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 +from ansible.plugins.action import ActionBase +try: + from ansible_collections.ansible.utils.plugins.module_utils.common.argspec_validate import ( + AnsibleArgSpecValidator, + ) +except ImportError: + ANSIBLE_UTILS_IS_INSTALLED = False +else: + ANSIBLE_UTILS_IS_INSTALLED = True +from ansible.errors import AnsibleActionFail +from ansible_collections.cisco.meraki.plugins.plugin_utils.meraki import ( + MERAKI, + meraki_argument_spec, +) + +# Get common arguments specification +argument_spec = meraki_argument_spec() +# Add arguments specific for this module +argument_spec.update(dict( + serial=dict(type="str"), +)) + +required_if = [] +required_one_of = [] +mutually_exclusive = [] +required_together = [] + + +class ActionModule(ActionBase): + def __init__(self, *args, **kwargs): + if not ANSIBLE_UTILS_IS_INSTALLED: + raise AnsibleActionFail( + "ansible.utils is not installed. Execute 'ansible-galaxy collection install ansible.utils'") + super(ActionModule, self).__init__(*args, **kwargs) + self._supports_async = False + self._supports_check_mode = True + self._result = None + + # Checks the supplied parameters against the argument spec for this module + def _check_argspec(self): + aav = AnsibleArgSpecValidator( + data=self._task.args, + schema=dict(argument_spec=argument_spec), + schema_format="argspec", + schema_conditionals=dict( + required_if=required_if, + required_one_of=required_one_of, + mutually_exclusive=mutually_exclusive, + required_together=required_together, + ), + name=self._task.action, + ) + valid, errors, self._task.args = aav.validate() + if not valid: + raise AnsibleActionFail(errors) + + def get_all(self, params): + new_object = {} + if params.get("serial") is not None: + new_object["serial"] = params.get( + "serial") + + return new_object + + def run(self, tmp=None, task_vars=None): + self._task.diff = False + self._result = super(ActionModule, self).run(tmp, task_vars) + self._result["changed"] = False + self._check_argspec() + + self._result.update(dict(meraki_response={})) + + meraki = MERAKI(params=self._task.args) + + response = meraki.exec_meraki( + family="appliance", + function='getDeviceApplianceRadioSettings', + params=self.get_all(self._task.args), + ) + self._result.update(dict(meraki_response=response)) + self._result.update(meraki.exit_json()) + return self._result diff --git a/ansible_collections/cisco/meraki/plugins/action/devices_blink_leds.py b/ansible_collections/cisco/meraki/plugins/action/devices_blink_leds.py index d6e157172..010922bcd 100644 --- a/ansible_collections/cisco/meraki/plugins/action/devices_blink_leds.py +++ b/ansible_collections/cisco/meraki/plugins/action/devices_blink_leds.py @@ -26,8 +26,8 @@ argument_spec = meraki_argument_spec() # Add arguments specific for this module argument_spec.update(dict( duration=dict(type="int"), - period=dict(type="int"), duty=dict(type="int"), + period=dict(type="int"), serial=dict(type="str"), )) @@ -68,8 +68,8 @@ class ActionModule(ActionBase): def get_object(self, params): new_object = dict( duration=params.get("duration"), - period=params.get("period"), duty=params.get("duty"), + period=params.get("period"), serial=params.get("serial"), ) return new_object diff --git a/ansible_collections/cisco/meraki/plugins/action/devices_camera_custom_analytics.py b/ansible_collections/cisco/meraki/plugins/action/devices_camera_custom_analytics.py index 92f3aa3ae..7493fe9b4 100644 --- a/ansible_collections/cisco/meraki/plugins/action/devices_camera_custom_analytics.py +++ b/ansible_collections/cisco/meraki/plugins/action/devices_camera_custom_analytics.py @@ -32,8 +32,8 @@ argument_spec = meraki_argument_spec() # Add arguments specific for this module argument_spec.update(dict( state=dict(type="str", default="present", choices=["present"]), - enabled=dict(type="bool"), artifactId=dict(type="str"), + enabled=dict(type="bool"), parameters=dict(type="list"), serial=dict(type="str"), )) @@ -50,8 +50,8 @@ class DevicesCameraCustomAnalytics(object): def __init__(self, params, meraki): self.meraki = meraki self.new_object = dict( - enabled=params.get("enabled"), artifactId=params.get("artifactId"), + enabled=params.get("enabled"), parameters=params.get("parameters"), serial=params.get("serial"), ) @@ -64,11 +64,11 @@ class DevicesCameraCustomAnalytics(object): def update_all_params(self): new_object_params = {} - if self.new_object.get('enabled') is not None or self.new_object.get('enabled') is not None: - new_object_params['enabled'] = self.new_object.get('enabled') if self.new_object.get('artifactId') is not None or self.new_object.get('artifact_id') is not None: new_object_params['artifactId'] = self.new_object.get('artifactId') or \ self.new_object.get('artifact_id') + if self.new_object.get('enabled') is not None or self.new_object.get('enabled') is not None: + new_object_params['enabled'] = self.new_object.get('enabled') if self.new_object.get('parameters') is not None or self.new_object.get('parameters') is not None: new_object_params['parameters'] = self.new_object.get('parameters') or \ self.new_object.get('parameters') @@ -128,8 +128,8 @@ class DevicesCameraCustomAnalytics(object): requested_obj = self.new_object obj_params = [ - ("enabled", "enabled"), ("artifactId", "artifactId"), + ("enabled", "enabled"), ("parameters", "parameters"), ("serial", "serial"), ] diff --git a/ansible_collections/cisco/meraki/plugins/action/devices_camera_generate_snapshot.py b/ansible_collections/cisco/meraki/plugins/action/devices_camera_generate_snapshot.py index 8b7e68487..25f923011 100644 --- a/ansible_collections/cisco/meraki/plugins/action/devices_camera_generate_snapshot.py +++ b/ansible_collections/cisco/meraki/plugins/action/devices_camera_generate_snapshot.py @@ -25,8 +25,8 @@ from ansible_collections.cisco.meraki.plugins.plugin_utils.meraki import ( argument_spec = meraki_argument_spec() # Add arguments specific for this module argument_spec.update(dict( - timestamp=dict(type="str"), fullframe=dict(type="bool"), + timestamp=dict(type="str"), serial=dict(type="str"), )) @@ -66,8 +66,8 @@ class ActionModule(ActionBase): def get_object(self, params): new_object = dict( - timestamp=params.get("timestamp"), fullframe=params.get("fullframe"), + timestamp=params.get("timestamp"), serial=params.get("serial"), ) return new_object diff --git a/ansible_collections/cisco/meraki/plugins/action/devices_camera_quality_and_retention.py b/ansible_collections/cisco/meraki/plugins/action/devices_camera_quality_and_retention.py index b7781783a..7b5056cf0 100644 --- a/ansible_collections/cisco/meraki/plugins/action/devices_camera_quality_and_retention.py +++ b/ansible_collections/cisco/meraki/plugins/action/devices_camera_quality_and_retention.py @@ -32,13 +32,13 @@ argument_spec = meraki_argument_spec() # Add arguments specific for this module argument_spec.update(dict( state=dict(type="str", default="present", choices=["present"]), - profileId=dict(type="str"), - motionBasedRetentionEnabled=dict(type="bool"), audioRecordingEnabled=dict(type="bool"), - restrictedBandwidthModeEnabled=dict(type="bool"), + motionBasedRetentionEnabled=dict(type="bool"), + motionDetectorVersion=dict(type="int"), + profileId=dict(type="str"), quality=dict(type="str"), resolution=dict(type="str"), - motionDetectorVersion=dict(type="int"), + restrictedBandwidthModeEnabled=dict(type="bool"), serial=dict(type="str"), )) @@ -54,13 +54,13 @@ class DevicesCameraQualityAndRetention(object): def __init__(self, params, meraki): self.meraki = meraki self.new_object = dict( - profileId=params.get("profileId"), - motionBasedRetentionEnabled=params.get("motionBasedRetentionEnabled"), audioRecordingEnabled=params.get("audioRecordingEnabled"), - restrictedBandwidthModeEnabled=params.get("restrictedBandwidthModeEnabled"), + motionBasedRetentionEnabled=params.get("motionBasedRetentionEnabled"), + motionDetectorVersion=params.get("motionDetectorVersion"), + profileId=params.get("profileId"), quality=params.get("quality"), resolution=params.get("resolution"), - motionDetectorVersion=params.get("motionDetectorVersion"), + restrictedBandwidthModeEnabled=params.get("restrictedBandwidthModeEnabled"), serial=params.get("serial"), ) @@ -72,24 +72,24 @@ class DevicesCameraQualityAndRetention(object): def update_all_params(self): new_object_params = {} + if self.new_object.get('audioRecordingEnabled') is not None or self.new_object.get('audio_recording_enabled') is not None: + new_object_params['audioRecordingEnabled'] = self.new_object.get('audioRecordingEnabled') + if self.new_object.get('motionBasedRetentionEnabled') is not None or self.new_object.get('motion_based_retention_enabled') is not None: + new_object_params['motionBasedRetentionEnabled'] = self.new_object.get('motionBasedRetentionEnabled') + if self.new_object.get('motionDetectorVersion') is not None or self.new_object.get('motion_detector_version') is not None: + new_object_params['motionDetectorVersion'] = self.new_object.get('motionDetectorVersion') or \ + self.new_object.get('motion_detector_version') if self.new_object.get('profileId') is not None or self.new_object.get('profile_id') is not None: new_object_params['profileId'] = self.new_object.get('profileId') or \ self.new_object.get('profile_id') - if self.new_object.get('motionBasedRetentionEnabled') is not None or self.new_object.get('motion_based_retention_enabled') is not None: - new_object_params['motionBasedRetentionEnabled'] = self.new_object.get('motionBasedRetentionEnabled') - if self.new_object.get('audioRecordingEnabled') is not None or self.new_object.get('audio_recording_enabled') is not None: - new_object_params['audioRecordingEnabled'] = self.new_object.get('audioRecordingEnabled') - if self.new_object.get('restrictedBandwidthModeEnabled') is not None or self.new_object.get('restricted_bandwidth_mode_enabled') is not None: - new_object_params['restrictedBandwidthModeEnabled'] = self.new_object.get('restrictedBandwidthModeEnabled') if self.new_object.get('quality') is not None or self.new_object.get('quality') is not None: new_object_params['quality'] = self.new_object.get('quality') or \ self.new_object.get('quality') if self.new_object.get('resolution') is not None or self.new_object.get('resolution') is not None: new_object_params['resolution'] = self.new_object.get('resolution') or \ self.new_object.get('resolution') - if self.new_object.get('motionDetectorVersion') is not None or self.new_object.get('motion_detector_version') is not None: - new_object_params['motionDetectorVersion'] = self.new_object.get('motionDetectorVersion') or \ - self.new_object.get('motion_detector_version') + if self.new_object.get('restrictedBandwidthModeEnabled') is not None or self.new_object.get('restricted_bandwidth_mode_enabled') is not None: + new_object_params['restrictedBandwidthModeEnabled'] = self.new_object.get('restrictedBandwidthModeEnabled') if self.new_object.get('serial') is not None or self.new_object.get('serial') is not None: new_object_params['serial'] = self.new_object.get('serial') or \ self.new_object.get('serial') @@ -146,13 +146,13 @@ class DevicesCameraQualityAndRetention(object): requested_obj = self.new_object obj_params = [ - ("profileId", "profileId"), - ("motionBasedRetentionEnabled", "motionBasedRetentionEnabled"), ("audioRecordingEnabled", "audioRecordingEnabled"), - ("restrictedBandwidthModeEnabled", "restrictedBandwidthModeEnabled"), + ("motionBasedRetentionEnabled", "motionBasedRetentionEnabled"), + ("motionDetectorVersion", "motionDetectorVersion"), + ("profileId", "profileId"), ("quality", "quality"), ("resolution", "resolution"), - ("motionDetectorVersion", "motionDetectorVersion"), + ("restrictedBandwidthModeEnabled", "restrictedBandwidthModeEnabled"), ("serial", "serial"), ] # Method 1. Params present in request (Ansible) obj are the same as the current (ISE) params diff --git a/ansible_collections/cisco/meraki/plugins/action/devices_camera_sense.py b/ansible_collections/cisco/meraki/plugins/action/devices_camera_sense.py index 3cc8dca92..c95304f52 100644 --- a/ansible_collections/cisco/meraki/plugins/action/devices_camera_sense.py +++ b/ansible_collections/cisco/meraki/plugins/action/devices_camera_sense.py @@ -32,10 +32,10 @@ argument_spec = meraki_argument_spec() # Add arguments specific for this module argument_spec.update(dict( state=dict(type="str", default="present", choices=["present"]), - senseEnabled=dict(type="bool"), - mqttBrokerId=dict(type="str"), audioDetection=dict(type="dict"), detectionModelId=dict(type="str"), + mqttBrokerId=dict(type="str"), + senseEnabled=dict(type="bool"), serial=dict(type="str"), )) @@ -51,10 +51,10 @@ class DevicesCameraSense(object): def __init__(self, params, meraki): self.meraki = meraki self.new_object = dict( - senseEnabled=params.get("senseEnabled"), - mqttBrokerId=params.get("mqttBrokerId"), audioDetection=params.get("audioDetection"), detectionModelId=params.get("detectionModelId"), + mqttBrokerId=params.get("mqttBrokerId"), + senseEnabled=params.get("senseEnabled"), serial=params.get("serial"), ) @@ -66,17 +66,17 @@ class DevicesCameraSense(object): def update_all_params(self): new_object_params = {} - if self.new_object.get('senseEnabled') is not None or self.new_object.get('sense_enabled') is not None: - new_object_params['senseEnabled'] = self.new_object.get('senseEnabled') - if self.new_object.get('mqttBrokerId') is not None or self.new_object.get('mqtt_broker_id') is not None: - new_object_params['mqttBrokerId'] = self.new_object.get('mqttBrokerId') or \ - self.new_object.get('mqtt_broker_id') if self.new_object.get('audioDetection') is not None or self.new_object.get('audio_detection') is not None: new_object_params['audioDetection'] = self.new_object.get('audioDetection') or \ self.new_object.get('audio_detection') if self.new_object.get('detectionModelId') is not None or self.new_object.get('detection_model_id') is not None: new_object_params['detectionModelId'] = self.new_object.get('detectionModelId') or \ self.new_object.get('detection_model_id') + if self.new_object.get('mqttBrokerId') is not None or self.new_object.get('mqtt_broker_id') is not None: + new_object_params['mqttBrokerId'] = self.new_object.get('mqttBrokerId') or \ + self.new_object.get('mqtt_broker_id') + if self.new_object.get('senseEnabled') is not None or self.new_object.get('sense_enabled') is not None: + new_object_params['senseEnabled'] = self.new_object.get('senseEnabled') if self.new_object.get('serial') is not None or self.new_object.get('serial') is not None: new_object_params['serial'] = self.new_object.get('serial') or \ self.new_object.get('serial') @@ -133,10 +133,10 @@ class DevicesCameraSense(object): requested_obj = self.new_object obj_params = [ - ("senseEnabled", "senseEnabled"), - ("mqttBrokerId", "mqttBrokerId"), ("audioDetection", "audioDetection"), ("detectionModelId", "detectionModelId"), + ("mqttBrokerId", "mqttBrokerId"), + ("senseEnabled", "senseEnabled"), ("serial", "serial"), ] # Method 1. Params present in request (Ansible) obj are the same as the current (ISE) params diff --git a/ansible_collections/cisco/meraki/plugins/action/devices_camera_wireless_profiles.py b/ansible_collections/cisco/meraki/plugins/action/devices_camera_wireless_profiles.py index 8153293df..f891d8c5b 100644 --- a/ansible_collections/cisco/meraki/plugins/action/devices_camera_wireless_profiles.py +++ b/ansible_collections/cisco/meraki/plugins/action/devices_camera_wireless_profiles.py @@ -78,8 +78,8 @@ class DevicesCameraWirelessProfiles(object): params=self.get_all_params(name=name), ) if isinstance(items, dict): - if 'response' in items: - items = items.get('response') + if 'ids' in items: + items = items.get('ids') result = get_dict_result(items, 'name', name) if result is None: result = items diff --git a/ansible_collections/cisco/meraki/plugins/action/devices_cellular_gateway_lan.py b/ansible_collections/cisco/meraki/plugins/action/devices_cellular_gateway_lan.py index ddb0b4d97..048e8a28b 100644 --- a/ansible_collections/cisco/meraki/plugins/action/devices_cellular_gateway_lan.py +++ b/ansible_collections/cisco/meraki/plugins/action/devices_cellular_gateway_lan.py @@ -32,8 +32,8 @@ argument_spec = meraki_argument_spec() # Add arguments specific for this module argument_spec.update(dict( state=dict(type="str", default="present", choices=["present"]), - reservedIpRanges=dict(type="list"), fixedIpAssignments=dict(type="list"), + reservedIpRanges=dict(type="list"), serial=dict(type="str"), )) @@ -49,8 +49,8 @@ class DevicesCellularGatewayLan(object): def __init__(self, params, meraki): self.meraki = meraki self.new_object = dict( - reservedIpRanges=params.get("reservedIpRanges"), fixedIpAssignments=params.get("fixedIpAssignments"), + reservedIpRanges=params.get("reservedIpRanges"), serial=params.get("serial"), ) @@ -62,12 +62,12 @@ class DevicesCellularGatewayLan(object): def update_all_params(self): new_object_params = {} - if self.new_object.get('reservedIpRanges') is not None or self.new_object.get('reserved_ip_ranges') is not None: - new_object_params['reservedIpRanges'] = self.new_object.get('reservedIpRanges') or \ - self.new_object.get('reserved_ip_ranges') if self.new_object.get('fixedIpAssignments') is not None or self.new_object.get('fixed_ip_assignments') is not None: new_object_params['fixedIpAssignments'] = self.new_object.get('fixedIpAssignments') or \ self.new_object.get('fixed_ip_assignments') + if self.new_object.get('reservedIpRanges') is not None or self.new_object.get('reserved_ip_ranges') is not None: + new_object_params['reservedIpRanges'] = self.new_object.get('reservedIpRanges') or \ + self.new_object.get('reserved_ip_ranges') if self.new_object.get('serial') is not None or self.new_object.get('serial') is not None: new_object_params['serial'] = self.new_object.get('serial') or \ self.new_object.get('serial') @@ -124,8 +124,8 @@ class DevicesCellularGatewayLan(object): requested_obj = self.new_object obj_params = [ - ("reservedIpRanges", "reservedIpRanges"), ("fixedIpAssignments", "fixedIpAssignments"), + ("reservedIpRanges", "reservedIpRanges"), ("serial", "serial"), ] # Method 1. Params present in request (Ansible) obj are the same as the current (ISE) params diff --git a/ansible_collections/cisco/meraki/plugins/action/devices_cellular_gateway_port_forwarding_rules.py b/ansible_collections/cisco/meraki/plugins/action/devices_cellular_gateway_port_forwarding_rules.py index 59a6ddf66..cb8693d61 100644 --- a/ansible_collections/cisco/meraki/plugins/action/devices_cellular_gateway_port_forwarding_rules.py +++ b/ansible_collections/cisco/meraki/plugins/action/devices_cellular_gateway_port_forwarding_rules.py @@ -78,8 +78,8 @@ class DevicesCellularGatewayPortForwardingRules(object): params=self.get_all_params(name=name), ) if isinstance(items, dict): - if 'response' in items: - items = items.get('response') + if 'rules' in items: + items = items.get('rules') result = get_dict_result(items, 'name', name) if result is None: result = items diff --git a/ansible_collections/cisco/meraki/plugins/action/devices_cellular_sims.py b/ansible_collections/cisco/meraki/plugins/action/devices_cellular_sims.py index 93e187918..d00c47622 100644 --- a/ansible_collections/cisco/meraki/plugins/action/devices_cellular_sims.py +++ b/ansible_collections/cisco/meraki/plugins/action/devices_cellular_sims.py @@ -32,8 +32,8 @@ argument_spec = meraki_argument_spec() # Add arguments specific for this module argument_spec.update(dict( state=dict(type="str", default="present", choices=["present"]), - sims=dict(type="list"), simFailover=dict(type="dict"), + sims=dict(type="list"), serial=dict(type="str"), )) @@ -49,8 +49,8 @@ class DevicesCellularSims(object): def __init__(self, params, meraki): self.meraki = meraki self.new_object = dict( - sims=params.get("sims"), simFailover=params.get("simFailover"), + sims=params.get("sims"), serial=params.get("serial"), ) @@ -62,12 +62,12 @@ class DevicesCellularSims(object): def update_all_params(self): new_object_params = {} - if self.new_object.get('sims') is not None or self.new_object.get('sims') is not None: - new_object_params['sims'] = self.new_object.get('sims') or \ - self.new_object.get('sims') if self.new_object.get('simFailover') is not None or self.new_object.get('sim_failover') is not None: new_object_params['simFailover'] = self.new_object.get('simFailover') or \ self.new_object.get('sim_failover') + if self.new_object.get('sims') is not None or self.new_object.get('sims') is not None: + new_object_params['sims'] = self.new_object.get('sims') or \ + self.new_object.get('sims') if self.new_object.get('serial') is not None or self.new_object.get('serial') is not None: new_object_params['serial'] = self.new_object.get('serial') or \ self.new_object.get('serial') @@ -83,8 +83,8 @@ class DevicesCellularSims(object): params=self.get_all_params(name=name), ) if isinstance(items, dict): - if 'response' in items: - items = items.get('response') + if 'sims' in items: + items = items.get('sims') result = get_dict_result(items, 'name', name) if result is None: result = items @@ -124,8 +124,8 @@ class DevicesCellularSims(object): requested_obj = self.new_object obj_params = [ - ("sims", "sims"), ("simFailover", "simFailover"), + ("sims", "sims"), ("serial", "serial"), ] # Method 1. Params present in request (Ansible) obj are the same as the current (ISE) params diff --git a/ansible_collections/cisco/meraki/plugins/action/devices_live_tools_arp_table.py b/ansible_collections/cisco/meraki/plugins/action/devices_live_tools_arp_table.py new file mode 100644 index 000000000..3c80f50c5 --- /dev/null +++ b/ansible_collections/cisco/meraki/plugins/action/devices_live_tools_arp_table.py @@ -0,0 +1,174 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +# Copyright (c) 2021, Cisco Systems +# 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 +from ansible.plugins.action import ActionBase +try: + from ansible_collections.ansible.utils.plugins.module_utils.common.argspec_validate import ( + AnsibleArgSpecValidator, + ) +except ImportError: + ANSIBLE_UTILS_IS_INSTALLED = False +else: + ANSIBLE_UTILS_IS_INSTALLED = True +from ansible.errors import AnsibleActionFail +from ansible_collections.cisco.meraki.plugins.plugin_utils.meraki import ( + MERAKI, + meraki_argument_spec, + meraki_compare_equality, +) +from ansible_collections.cisco.meraki.plugins.plugin_utils.exceptions import ( + InconsistentParameters, +) + +# Get common arguments specification +argument_spec = meraki_argument_spec() +# Add arguments specific for this module +argument_spec.update(dict( + state=dict(type="str", default="present", choices=["present"]), + callback=dict(type="dict"), + serial=dict(type="str"), +)) + +required_if = [ + ("state", "present", ["serial"], True), +] +required_one_of = [] +mutually_exclusive = [] +required_together = [] + + +class DevicesLiveToolsArpTable(object): + def __init__(self, params, meraki): + self.meraki = meraki + self.new_object = dict( + callback=params.get("callback"), + serial=params.get("serial"), + ) + + def create_params(self): + new_object_params = {} + if self.new_object.get('callback') is not None or self.new_object.get('callback') is not None: + new_object_params['callback'] = self.new_object.get('callback') or \ + self.new_object.get('callback') + if self.new_object.get('serial') is not None or self.new_object.get('serial') is not None: + new_object_params['serial'] = self.new_object.get('serial') or \ + self.new_object.get('serial') + return new_object_params + + def get_object_by_name(self, name): + result = None + # NOTE: Does not have a get by name and get all + return result + + def get_object_by_id(self, id): + result = None + # NOTE: Does not have a get by id method or it is in another action + return result + + def exists(self): + prev_obj = None + id_exists = False + name_exists = False + o_id = self.new_object.get("serial") + name = self.new_object.get("name") + if o_id: + prev_obj = self.get_object_by_name(o_id) + id_exists = prev_obj is not None and isinstance(prev_obj, dict) + if not id_exists and name: + prev_obj = self.get_object_by_name(name) + name_exists = prev_obj is not None and isinstance(prev_obj, dict) + if name_exists: + _id = prev_obj.get("id") + if id_exists and name_exists and o_id != _id: + raise InconsistentParameters( + "The 'id' and 'name' params don't refer to the same object") + if _id: + self.new_object.update(dict(id=_id)) + it_exists = prev_obj is not None and isinstance(prev_obj, dict) + return (it_exists, prev_obj) + + def requires_update(self, current_obj): + requested_obj = self.new_object + + obj_params = [ + ("callback", "callback"), + ("serial", "serial"), + ] + # Method 1. Params present in request (Ansible) obj are the same as the current (ISE) params + # If any does not have eq params, it requires update + return any(not meraki_compare_equality(current_obj.get(meraki_param), + requested_obj.get(ansible_param)) + for (meraki_param, ansible_param) in obj_params) + + def create(self): + result = self.meraki.exec_meraki( + family="devices", + function="createDeviceLiveToolsArpTable", + params=self.create_params(), + op_modifies=True, + ) + return result + + +class ActionModule(ActionBase): + def __init__(self, *args, **kwargs): + if not ANSIBLE_UTILS_IS_INSTALLED: + raise AnsibleActionFail( + "ansible.utils is not installed. Execute 'ansible-galaxy collection install ansible.utils'") + super(ActionModule, self).__init__(*args, **kwargs) + self._supports_async = False + self._supports_check_mode = False + self._result = None + + # Checks the supplied parameters against the argument spec for this module + def _check_argspec(self): + aav = AnsibleArgSpecValidator( + data=self._task.args, + schema=dict(argument_spec=argument_spec), + schema_format="argspec", + schema_conditionals=dict( + required_if=required_if, + required_one_of=required_one_of, + mutually_exclusive=mutually_exclusive, + required_together=required_together, + ), + name=self._task.action, + ) + valid, errors, self._task.args = aav.validate() + if not valid: + raise AnsibleActionFail(errors) + + def run(self, tmp=None, task_vars=None): + self._task.diff = False + self._result = super(ActionModule, self).run(tmp, task_vars) + self._result["changed"] = False + self._check_argspec() + + meraki = MERAKI(self._task.args) + obj = DevicesLiveToolsArpTable(self._task.args, meraki) + + state = self._task.args.get("state") + + response = None + if state == "present": + (obj_exists, prev_obj) = obj.exists() + if obj_exists: + if obj.requires_update(prev_obj): + response = prev_obj + meraki.object_present_and_different() + else: + response = prev_obj + meraki.object_already_present() + else: + response = obj.create() + meraki.object_created() + + self._result.update(dict(meraki_response=response)) + self._result.update(meraki.exit_json()) + return self._result diff --git a/ansible_collections/cisco/meraki/plugins/action/devices_live_tools_arp_table_info.py b/ansible_collections/cisco/meraki/plugins/action/devices_live_tools_arp_table_info.py new file mode 100644 index 000000000..8e972db51 --- /dev/null +++ b/ansible_collections/cisco/meraki/plugins/action/devices_live_tools_arp_table_info.py @@ -0,0 +1,79 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +# Copyright (c) 2021, Cisco Systems +# 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 +from ansible.plugins.action import ActionBase +try: + from ansible_collections.ansible.utils.plugins.module_utils.common.argspec_validate import ( + AnsibleArgSpecValidator, + ) +except ImportError: + ANSIBLE_UTILS_IS_INSTALLED = False +else: + ANSIBLE_UTILS_IS_INSTALLED = True +from ansible.errors import AnsibleActionFail +from ansible_collections.cisco.meraki.plugins.plugin_utils.meraki import ( + MERAKI, + meraki_argument_spec, +) + +# Get common arguments specification +argument_spec = meraki_argument_spec() +# Add arguments specific for this module +argument_spec.update(dict( +)) + +required_if = [] +required_one_of = [] +mutually_exclusive = [] +required_together = [] + + +class ActionModule(ActionBase): + def __init__(self, *args, **kwargs): + if not ANSIBLE_UTILS_IS_INSTALLED: + raise AnsibleActionFail( + "ansible.utils is not installed. Execute 'ansible-galaxy collection install ansible.utils'") + super(ActionModule, self).__init__(*args, **kwargs) + self._supports_async = False + self._supports_check_mode = True + self._result = None + + # Checks the supplied parameters against the argument spec for this module + def _check_argspec(self): + aav = AnsibleArgSpecValidator( + data=self._task.args, + schema=dict(argument_spec=argument_spec), + schema_format="argspec", + schema_conditionals=dict( + required_if=required_if, + required_one_of=required_one_of, + mutually_exclusive=mutually_exclusive, + required_together=required_together, + ), + name=self._task.action, + ) + valid, errors, self._task.args = aav.validate() + if not valid: + raise AnsibleActionFail(errors) + + def run(self, tmp=None, task_vars=None): + self._task.diff = False + self._result = super(ActionModule, self).run(tmp, task_vars) + self._result["changed"] = False + self._check_argspec() + + self._result.update(dict(meraki_response={})) + + meraki = MERAKI(params=self._task.args) + + # NOTE: Does not have a get all method or it is in another action + response = None + meraki.object_modify_result(changed=False, result="Module does not have get all, check arguments of module") + self._result.update(dict(meraki_response=response)) + self._result.update(meraki.exit_json()) + return self._result diff --git a/ansible_collections/cisco/meraki/plugins/action/devices_live_tools_cable_test.py b/ansible_collections/cisco/meraki/plugins/action/devices_live_tools_cable_test.py new file mode 100644 index 000000000..ec58e54fc --- /dev/null +++ b/ansible_collections/cisco/meraki/plugins/action/devices_live_tools_cable_test.py @@ -0,0 +1,180 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +# Copyright (c) 2021, Cisco Systems +# 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 +from ansible.plugins.action import ActionBase +try: + from ansible_collections.ansible.utils.plugins.module_utils.common.argspec_validate import ( + AnsibleArgSpecValidator, + ) +except ImportError: + ANSIBLE_UTILS_IS_INSTALLED = False +else: + ANSIBLE_UTILS_IS_INSTALLED = True +from ansible.errors import AnsibleActionFail +from ansible_collections.cisco.meraki.plugins.plugin_utils.meraki import ( + MERAKI, + meraki_argument_spec, + meraki_compare_equality, +) +from ansible_collections.cisco.meraki.plugins.plugin_utils.exceptions import ( + InconsistentParameters, +) + +# Get common arguments specification +argument_spec = meraki_argument_spec() +# Add arguments specific for this module +argument_spec.update(dict( + state=dict(type="str", default="present", choices=["present"]), + callback=dict(type="dict"), + ports=dict(type="list"), + serial=dict(type="str"), +)) + +required_if = [ + ("state", "present", ["serial"], True), +] +required_one_of = [] +mutually_exclusive = [] +required_together = [] + + +class DevicesLiveToolsCableTest(object): + def __init__(self, params, meraki): + self.meraki = meraki + self.new_object = dict( + callback=params.get("callback"), + ports=params.get("ports"), + serial=params.get("serial"), + ) + + def create_params(self): + new_object_params = {} + if self.new_object.get('callback') is not None or self.new_object.get('callback') is not None: + new_object_params['callback'] = self.new_object.get('callback') or \ + self.new_object.get('callback') + if self.new_object.get('ports') is not None or self.new_object.get('ports') is not None: + new_object_params['ports'] = self.new_object.get('ports') or \ + self.new_object.get('ports') + if self.new_object.get('serial') is not None or self.new_object.get('serial') is not None: + new_object_params['serial'] = self.new_object.get('serial') or \ + self.new_object.get('serial') + return new_object_params + + def get_object_by_name(self, name): + result = None + # NOTE: Does not have a get by name and get all + return result + + def get_object_by_id(self, id): + result = None + # NOTE: Does not have a get by id method or it is in another action + return result + + def exists(self): + prev_obj = None + id_exists = False + name_exists = False + o_id = self.new_object.get("serial") + name = self.new_object.get("name") + if o_id: + prev_obj = self.get_object_by_name(o_id) + id_exists = prev_obj is not None and isinstance(prev_obj, dict) + if not id_exists and name: + prev_obj = self.get_object_by_name(name) + name_exists = prev_obj is not None and isinstance(prev_obj, dict) + if name_exists: + _id = prev_obj.get("id") + if id_exists and name_exists and o_id != _id: + raise InconsistentParameters( + "The 'id' and 'name' params don't refer to the same object") + if _id: + self.new_object.update(dict(id=_id)) + it_exists = prev_obj is not None and isinstance(prev_obj, dict) + return (it_exists, prev_obj) + + def requires_update(self, current_obj): + requested_obj = self.new_object + + obj_params = [ + ("callback", "callback"), + ("ports", "ports"), + ("serial", "serial"), + ] + # Method 1. Params present in request (Ansible) obj are the same as the current (ISE) params + # If any does not have eq params, it requires update + return any(not meraki_compare_equality(current_obj.get(meraki_param), + requested_obj.get(ansible_param)) + for (meraki_param, ansible_param) in obj_params) + + def create(self): + result = self.meraki.exec_meraki( + family="devices", + function="createDeviceLiveToolsCableTest", + params=self.create_params(), + op_modifies=True, + ) + return result + + +class ActionModule(ActionBase): + def __init__(self, *args, **kwargs): + if not ANSIBLE_UTILS_IS_INSTALLED: + raise AnsibleActionFail( + "ansible.utils is not installed. Execute 'ansible-galaxy collection install ansible.utils'") + super(ActionModule, self).__init__(*args, **kwargs) + self._supports_async = False + self._supports_check_mode = False + self._result = None + + # Checks the supplied parameters against the argument spec for this module + def _check_argspec(self): + aav = AnsibleArgSpecValidator( + data=self._task.args, + schema=dict(argument_spec=argument_spec), + schema_format="argspec", + schema_conditionals=dict( + required_if=required_if, + required_one_of=required_one_of, + mutually_exclusive=mutually_exclusive, + required_together=required_together, + ), + name=self._task.action, + ) + valid, errors, self._task.args = aav.validate() + if not valid: + raise AnsibleActionFail(errors) + + def run(self, tmp=None, task_vars=None): + self._task.diff = False + self._result = super(ActionModule, self).run(tmp, task_vars) + self._result["changed"] = False + self._check_argspec() + + meraki = MERAKI(self._task.args) + obj = DevicesLiveToolsCableTest(self._task.args, meraki) + + state = self._task.args.get("state") + + response = None + if state == "present": + (obj_exists, prev_obj) = obj.exists() + if obj_exists: + if obj.requires_update(prev_obj): + response = prev_obj + meraki.object_present_and_different() + else: + response = prev_obj + meraki.object_already_present() + else: + response = obj.create() + meraki.object_created() + + self._result.update(dict(meraki_response=response)) + self._result.update(meraki.exit_json()) + return self._result diff --git a/ansible_collections/cisco/meraki/plugins/action/devices_live_tools_cable_test_info.py b/ansible_collections/cisco/meraki/plugins/action/devices_live_tools_cable_test_info.py new file mode 100644 index 000000000..8e972db51 --- /dev/null +++ b/ansible_collections/cisco/meraki/plugins/action/devices_live_tools_cable_test_info.py @@ -0,0 +1,79 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +# Copyright (c) 2021, Cisco Systems +# 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 +from ansible.plugins.action import ActionBase +try: + from ansible_collections.ansible.utils.plugins.module_utils.common.argspec_validate import ( + AnsibleArgSpecValidator, + ) +except ImportError: + ANSIBLE_UTILS_IS_INSTALLED = False +else: + ANSIBLE_UTILS_IS_INSTALLED = True +from ansible.errors import AnsibleActionFail +from ansible_collections.cisco.meraki.plugins.plugin_utils.meraki import ( + MERAKI, + meraki_argument_spec, +) + +# Get common arguments specification +argument_spec = meraki_argument_spec() +# Add arguments specific for this module +argument_spec.update(dict( +)) + +required_if = [] +required_one_of = [] +mutually_exclusive = [] +required_together = [] + + +class ActionModule(ActionBase): + def __init__(self, *args, **kwargs): + if not ANSIBLE_UTILS_IS_INSTALLED: + raise AnsibleActionFail( + "ansible.utils is not installed. Execute 'ansible-galaxy collection install ansible.utils'") + super(ActionModule, self).__init__(*args, **kwargs) + self._supports_async = False + self._supports_check_mode = True + self._result = None + + # Checks the supplied parameters against the argument spec for this module + def _check_argspec(self): + aav = AnsibleArgSpecValidator( + data=self._task.args, + schema=dict(argument_spec=argument_spec), + schema_format="argspec", + schema_conditionals=dict( + required_if=required_if, + required_one_of=required_one_of, + mutually_exclusive=mutually_exclusive, + required_together=required_together, + ), + name=self._task.action, + ) + valid, errors, self._task.args = aav.validate() + if not valid: + raise AnsibleActionFail(errors) + + def run(self, tmp=None, task_vars=None): + self._task.diff = False + self._result = super(ActionModule, self).run(tmp, task_vars) + self._result["changed"] = False + self._check_argspec() + + self._result.update(dict(meraki_response={})) + + meraki = MERAKI(params=self._task.args) + + # NOTE: Does not have a get all method or it is in another action + response = None + meraki.object_modify_result(changed=False, result="Module does not have get all, check arguments of module") + self._result.update(dict(meraki_response=response)) + self._result.update(meraki.exit_json()) + return self._result diff --git a/ansible_collections/cisco/meraki/plugins/action/devices_live_tools_ping.py b/ansible_collections/cisco/meraki/plugins/action/devices_live_tools_ping.py index ba5ef2d67..bd91ad77e 100644 --- a/ansible_collections/cisco/meraki/plugins/action/devices_live_tools_ping.py +++ b/ansible_collections/cisco/meraki/plugins/action/devices_live_tools_ping.py @@ -31,8 +31,9 @@ argument_spec = meraki_argument_spec() # Add arguments specific for this module argument_spec.update(dict( state=dict(type="str", default="present", choices=["present"]), - target=dict(type="str"), + callback=dict(type="dict"), count=dict(type="int"), + target=dict(type="str"), serial=dict(type="str"), id=dict(type="str"), )) @@ -49,8 +50,9 @@ class DevicesLiveToolsPing(object): def __init__(self, params, meraki): self.meraki = meraki self.new_object = dict( - target=params.get("target"), + callback=params.get("callback"), count=params.get("count"), + target=params.get("target"), serial=params.get("serial"), id=params.get("id"), ) @@ -65,12 +67,15 @@ class DevicesLiveToolsPing(object): def create_params(self): new_object_params = {} - if self.new_object.get('target') is not None or self.new_object.get('target') is not None: - new_object_params['target'] = self.new_object.get('target') or \ - self.new_object.get('target') + if self.new_object.get('callback') is not None or self.new_object.get('callback') is not None: + new_object_params['callback'] = self.new_object.get('callback') or \ + self.new_object.get('callback') if self.new_object.get('count') is not None or self.new_object.get('count') is not None: new_object_params['count'] = self.new_object.get('count') or \ self.new_object.get('count') + if self.new_object.get('target') is not None or self.new_object.get('target') is not None: + new_object_params['target'] = self.new_object.get('target') or \ + self.new_object.get('target') if self.new_object.get('serial') is not None or self.new_object.get('serial') is not None: new_object_params['serial'] = self.new_object.get('serial') or \ self.new_object.get('serial') @@ -126,8 +131,9 @@ class DevicesLiveToolsPing(object): requested_obj = self.new_object obj_params = [ - ("target", "target"), + ("callback", "callback"), ("count", "count"), + ("target", "target"), ("serial", "serial"), ("id", "id"), ] diff --git a/ansible_collections/cisco/meraki/plugins/action/devices_live_tools_ping_device.py b/ansible_collections/cisco/meraki/plugins/action/devices_live_tools_ping_device.py index cb00a6c6b..4738511fb 100644 --- a/ansible_collections/cisco/meraki/plugins/action/devices_live_tools_ping_device.py +++ b/ansible_collections/cisco/meraki/plugins/action/devices_live_tools_ping_device.py @@ -31,6 +31,7 @@ argument_spec = meraki_argument_spec() # Add arguments specific for this module argument_spec.update(dict( state=dict(type="str", default="present", choices=["present"]), + callback=dict(type="dict"), count=dict(type="int"), serial=dict(type="str"), id=dict(type="str"), @@ -48,6 +49,7 @@ class DevicesLiveToolsPingDevice(object): def __init__(self, params, meraki): self.meraki = meraki self.new_object = dict( + callback=params.get("callback"), count=params.get("count"), serial=params.get("serial"), id=params.get("id"), @@ -63,6 +65,9 @@ class DevicesLiveToolsPingDevice(object): def create_params(self): new_object_params = {} + if self.new_object.get('callback') is not None or self.new_object.get('callback') is not None: + new_object_params['callback'] = self.new_object.get('callback') or \ + self.new_object.get('callback') if self.new_object.get('count') is not None or self.new_object.get('count') is not None: new_object_params['count'] = self.new_object.get('count') or \ self.new_object.get('count') @@ -121,6 +126,7 @@ class DevicesLiveToolsPingDevice(object): requested_obj = self.new_object obj_params = [ + ("callback", "callback"), ("count", "count"), ("serial", "serial"), ("id", "id"), diff --git a/ansible_collections/cisco/meraki/plugins/action/devices_live_tools_throughput_test.py b/ansible_collections/cisco/meraki/plugins/action/devices_live_tools_throughput_test.py new file mode 100644 index 000000000..50edfcffd --- /dev/null +++ b/ansible_collections/cisco/meraki/plugins/action/devices_live_tools_throughput_test.py @@ -0,0 +1,174 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +# Copyright (c) 2021, Cisco Systems +# 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 +from ansible.plugins.action import ActionBase +try: + from ansible_collections.ansible.utils.plugins.module_utils.common.argspec_validate import ( + AnsibleArgSpecValidator, + ) +except ImportError: + ANSIBLE_UTILS_IS_INSTALLED = False +else: + ANSIBLE_UTILS_IS_INSTALLED = True +from ansible.errors import AnsibleActionFail +from ansible_collections.cisco.meraki.plugins.plugin_utils.meraki import ( + MERAKI, + meraki_argument_spec, + meraki_compare_equality, +) +from ansible_collections.cisco.meraki.plugins.plugin_utils.exceptions import ( + InconsistentParameters, +) + +# Get common arguments specification +argument_spec = meraki_argument_spec() +# Add arguments specific for this module +argument_spec.update(dict( + state=dict(type="str", default="present", choices=["present"]), + callback=dict(type="dict"), + serial=dict(type="str"), +)) + +required_if = [ + ("state", "present", ["serial"], True), +] +required_one_of = [] +mutually_exclusive = [] +required_together = [] + + +class DevicesLiveToolsThroughputTest(object): + def __init__(self, params, meraki): + self.meraki = meraki + self.new_object = dict( + callback=params.get("callback"), + serial=params.get("serial"), + ) + + def create_params(self): + new_object_params = {} + if self.new_object.get('callback') is not None or self.new_object.get('callback') is not None: + new_object_params['callback'] = self.new_object.get('callback') or \ + self.new_object.get('callback') + if self.new_object.get('serial') is not None or self.new_object.get('serial') is not None: + new_object_params['serial'] = self.new_object.get('serial') or \ + self.new_object.get('serial') + return new_object_params + + def get_object_by_name(self, name): + result = None + # NOTE: Does not have a get by name and get all + return result + + def get_object_by_id(self, id): + result = None + # NOTE: Does not have a get by id method or it is in another action + return result + + def exists(self): + prev_obj = None + id_exists = False + name_exists = False + o_id = self.new_object.get("serial") + name = self.new_object.get("name") + if o_id: + prev_obj = self.get_object_by_name(o_id) + id_exists = prev_obj is not None and isinstance(prev_obj, dict) + if not id_exists and name: + prev_obj = self.get_object_by_name(name) + name_exists = prev_obj is not None and isinstance(prev_obj, dict) + if name_exists: + _id = prev_obj.get("id") + if id_exists and name_exists and o_id != _id: + raise InconsistentParameters( + "The 'id' and 'name' params don't refer to the same object") + if _id: + self.new_object.update(dict(id=_id)) + it_exists = prev_obj is not None and isinstance(prev_obj, dict) + return (it_exists, prev_obj) + + def requires_update(self, current_obj): + requested_obj = self.new_object + + obj_params = [ + ("callback", "callback"), + ("serial", "serial"), + ] + # Method 1. Params present in request (Ansible) obj are the same as the current (ISE) params + # If any does not have eq params, it requires update + return any(not meraki_compare_equality(current_obj.get(meraki_param), + requested_obj.get(ansible_param)) + for (meraki_param, ansible_param) in obj_params) + + def create(self): + result = self.meraki.exec_meraki( + family="devices", + function="createDeviceLiveToolsThroughputTest", + params=self.create_params(), + op_modifies=True, + ) + return result + + +class ActionModule(ActionBase): + def __init__(self, *args, **kwargs): + if not ANSIBLE_UTILS_IS_INSTALLED: + raise AnsibleActionFail( + "ansible.utils is not installed. Execute 'ansible-galaxy collection install ansible.utils'") + super(ActionModule, self).__init__(*args, **kwargs) + self._supports_async = False + self._supports_check_mode = False + self._result = None + + # Checks the supplied parameters against the argument spec for this module + def _check_argspec(self): + aav = AnsibleArgSpecValidator( + data=self._task.args, + schema=dict(argument_spec=argument_spec), + schema_format="argspec", + schema_conditionals=dict( + required_if=required_if, + required_one_of=required_one_of, + mutually_exclusive=mutually_exclusive, + required_together=required_together, + ), + name=self._task.action, + ) + valid, errors, self._task.args = aav.validate() + if not valid: + raise AnsibleActionFail(errors) + + def run(self, tmp=None, task_vars=None): + self._task.diff = False + self._result = super(ActionModule, self).run(tmp, task_vars) + self._result["changed"] = False + self._check_argspec() + + meraki = MERAKI(self._task.args) + obj = DevicesLiveToolsThroughputTest(self._task.args, meraki) + + state = self._task.args.get("state") + + response = None + if state == "present": + (obj_exists, prev_obj) = obj.exists() + if obj_exists: + if obj.requires_update(prev_obj): + response = prev_obj + meraki.object_present_and_different() + else: + response = prev_obj + meraki.object_already_present() + else: + response = obj.create() + meraki.object_created() + + self._result.update(dict(meraki_response=response)) + self._result.update(meraki.exit_json()) + return self._result diff --git a/ansible_collections/cisco/meraki/plugins/action/devices_live_tools_throughput_test_info.py b/ansible_collections/cisco/meraki/plugins/action/devices_live_tools_throughput_test_info.py new file mode 100644 index 000000000..8e972db51 --- /dev/null +++ b/ansible_collections/cisco/meraki/plugins/action/devices_live_tools_throughput_test_info.py @@ -0,0 +1,79 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +# Copyright (c) 2021, Cisco Systems +# 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 +from ansible.plugins.action import ActionBase +try: + from ansible_collections.ansible.utils.plugins.module_utils.common.argspec_validate import ( + AnsibleArgSpecValidator, + ) +except ImportError: + ANSIBLE_UTILS_IS_INSTALLED = False +else: + ANSIBLE_UTILS_IS_INSTALLED = True +from ansible.errors import AnsibleActionFail +from ansible_collections.cisco.meraki.plugins.plugin_utils.meraki import ( + MERAKI, + meraki_argument_spec, +) + +# Get common arguments specification +argument_spec = meraki_argument_spec() +# Add arguments specific for this module +argument_spec.update(dict( +)) + +required_if = [] +required_one_of = [] +mutually_exclusive = [] +required_together = [] + + +class ActionModule(ActionBase): + def __init__(self, *args, **kwargs): + if not ANSIBLE_UTILS_IS_INSTALLED: + raise AnsibleActionFail( + "ansible.utils is not installed. Execute 'ansible-galaxy collection install ansible.utils'") + super(ActionModule, self).__init__(*args, **kwargs) + self._supports_async = False + self._supports_check_mode = True + self._result = None + + # Checks the supplied parameters against the argument spec for this module + def _check_argspec(self): + aav = AnsibleArgSpecValidator( + data=self._task.args, + schema=dict(argument_spec=argument_spec), + schema_format="argspec", + schema_conditionals=dict( + required_if=required_if, + required_one_of=required_one_of, + mutually_exclusive=mutually_exclusive, + required_together=required_together, + ), + name=self._task.action, + ) + valid, errors, self._task.args = aav.validate() + if not valid: + raise AnsibleActionFail(errors) + + def run(self, tmp=None, task_vars=None): + self._task.diff = False + self._result = super(ActionModule, self).run(tmp, task_vars) + self._result["changed"] = False + self._check_argspec() + + self._result.update(dict(meraki_response={})) + + meraki = MERAKI(params=self._task.args) + + # NOTE: Does not have a get all method or it is in another action + response = None + meraki.object_modify_result(changed=False, result="Module does not have get all, check arguments of module") + self._result.update(dict(meraki_response=response)) + self._result.update(meraki.exit_json()) + return self._result diff --git a/ansible_collections/cisco/meraki/plugins/action/devices_live_tools_wake_on_lan.py b/ansible_collections/cisco/meraki/plugins/action/devices_live_tools_wake_on_lan.py new file mode 100644 index 000000000..4fc6873e4 --- /dev/null +++ b/ansible_collections/cisco/meraki/plugins/action/devices_live_tools_wake_on_lan.py @@ -0,0 +1,186 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +# Copyright (c) 2021, Cisco Systems +# 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 +from ansible.plugins.action import ActionBase +try: + from ansible_collections.ansible.utils.plugins.module_utils.common.argspec_validate import ( + AnsibleArgSpecValidator, + ) +except ImportError: + ANSIBLE_UTILS_IS_INSTALLED = False +else: + ANSIBLE_UTILS_IS_INSTALLED = True +from ansible.errors import AnsibleActionFail +from ansible_collections.cisco.meraki.plugins.plugin_utils.meraki import ( + MERAKI, + meraki_argument_spec, + meraki_compare_equality, +) +from ansible_collections.cisco.meraki.plugins.plugin_utils.exceptions import ( + InconsistentParameters, +) + +# Get common arguments specification +argument_spec = meraki_argument_spec() +# Add arguments specific for this module +argument_spec.update(dict( + state=dict(type="str", default="present", choices=["present"]), + callback=dict(type="dict"), + mac=dict(type="str"), + vlanId=dict(type="int"), + serial=dict(type="str"), +)) + +required_if = [ + ("state", "present", ["serial"], True), +] +required_one_of = [] +mutually_exclusive = [] +required_together = [] + + +class DevicesLiveToolsWakeOnLan(object): + def __init__(self, params, meraki): + self.meraki = meraki + self.new_object = dict( + callback=params.get("callback"), + mac=params.get("mac"), + vlanId=params.get("vlanId"), + serial=params.get("serial"), + ) + + def create_params(self): + new_object_params = {} + if self.new_object.get('callback') is not None or self.new_object.get('callback') is not None: + new_object_params['callback'] = self.new_object.get('callback') or \ + self.new_object.get('callback') + if self.new_object.get('mac') is not None or self.new_object.get('mac') is not None: + new_object_params['mac'] = self.new_object.get('mac') or \ + self.new_object.get('mac') + if self.new_object.get('vlanId') is not None or self.new_object.get('vlan_id') is not None: + new_object_params['vlanId'] = self.new_object.get('vlanId') or \ + self.new_object.get('vlan_id') + if self.new_object.get('serial') is not None or self.new_object.get('serial') is not None: + new_object_params['serial'] = self.new_object.get('serial') or \ + self.new_object.get('serial') + return new_object_params + + def get_object_by_name(self, name): + result = None + # NOTE: Does not have a get by name and get all + return result + + def get_object_by_id(self, id): + result = None + # NOTE: Does not have a get by id method or it is in another action + return result + + def exists(self): + prev_obj = None + id_exists = False + name_exists = False + o_id = self.new_object.get("serial") + name = self.new_object.get("name") + if o_id: + prev_obj = self.get_object_by_name(o_id) + id_exists = prev_obj is not None and isinstance(prev_obj, dict) + if not id_exists and name: + prev_obj = self.get_object_by_name(name) + name_exists = prev_obj is not None and isinstance(prev_obj, dict) + if name_exists: + _id = prev_obj.get("id") + if id_exists and name_exists and o_id != _id: + raise InconsistentParameters( + "The 'id' and 'name' params don't refer to the same object") + if _id: + self.new_object.update(dict(id=_id)) + it_exists = prev_obj is not None and isinstance(prev_obj, dict) + return (it_exists, prev_obj) + + def requires_update(self, current_obj): + requested_obj = self.new_object + + obj_params = [ + ("callback", "callback"), + ("mac", "mac"), + ("vlanId", "vlanId"), + ("serial", "serial"), + ] + # Method 1. Params present in request (Ansible) obj are the same as the current (ISE) params + # If any does not have eq params, it requires update + return any(not meraki_compare_equality(current_obj.get(meraki_param), + requested_obj.get(ansible_param)) + for (meraki_param, ansible_param) in obj_params) + + def create(self): + result = self.meraki.exec_meraki( + family="devices", + function="createDeviceLiveToolsWakeOnLan", + params=self.create_params(), + op_modifies=True, + ) + return result + + +class ActionModule(ActionBase): + def __init__(self, *args, **kwargs): + if not ANSIBLE_UTILS_IS_INSTALLED: + raise AnsibleActionFail( + "ansible.utils is not installed. Execute 'ansible-galaxy collection install ansible.utils'") + super(ActionModule, self).__init__(*args, **kwargs) + self._supports_async = False + self._supports_check_mode = False + self._result = None + + # Checks the supplied parameters against the argument spec for this module + def _check_argspec(self): + aav = AnsibleArgSpecValidator( + data=self._task.args, + schema=dict(argument_spec=argument_spec), + schema_format="argspec", + schema_conditionals=dict( + required_if=required_if, + required_one_of=required_one_of, + mutually_exclusive=mutually_exclusive, + required_together=required_together, + ), + name=self._task.action, + ) + valid, errors, self._task.args = aav.validate() + if not valid: + raise AnsibleActionFail(errors) + + def run(self, tmp=None, task_vars=None): + self._task.diff = False + self._result = super(ActionModule, self).run(tmp, task_vars) + self._result["changed"] = False + self._check_argspec() + + meraki = MERAKI(self._task.args) + obj = DevicesLiveToolsWakeOnLan(self._task.args, meraki) + + state = self._task.args.get("state") + + response = None + if state == "present": + (obj_exists, prev_obj) = obj.exists() + if obj_exists: + if obj.requires_update(prev_obj): + response = prev_obj + meraki.object_present_and_different() + else: + response = prev_obj + meraki.object_already_present() + else: + response = obj.create() + meraki.object_created() + + self._result.update(dict(meraki_response=response)) + self._result.update(meraki.exit_json()) + return self._result diff --git a/ansible_collections/cisco/meraki/plugins/action/devices_live_tools_wake_on_lan_info.py b/ansible_collections/cisco/meraki/plugins/action/devices_live_tools_wake_on_lan_info.py new file mode 100644 index 000000000..8e972db51 --- /dev/null +++ b/ansible_collections/cisco/meraki/plugins/action/devices_live_tools_wake_on_lan_info.py @@ -0,0 +1,79 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +# Copyright (c) 2021, Cisco Systems +# 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 +from ansible.plugins.action import ActionBase +try: + from ansible_collections.ansible.utils.plugins.module_utils.common.argspec_validate import ( + AnsibleArgSpecValidator, + ) +except ImportError: + ANSIBLE_UTILS_IS_INSTALLED = False +else: + ANSIBLE_UTILS_IS_INSTALLED = True +from ansible.errors import AnsibleActionFail +from ansible_collections.cisco.meraki.plugins.plugin_utils.meraki import ( + MERAKI, + meraki_argument_spec, +) + +# Get common arguments specification +argument_spec = meraki_argument_spec() +# Add arguments specific for this module +argument_spec.update(dict( +)) + +required_if = [] +required_one_of = [] +mutually_exclusive = [] +required_together = [] + + +class ActionModule(ActionBase): + def __init__(self, *args, **kwargs): + if not ANSIBLE_UTILS_IS_INSTALLED: + raise AnsibleActionFail( + "ansible.utils is not installed. Execute 'ansible-galaxy collection install ansible.utils'") + super(ActionModule, self).__init__(*args, **kwargs) + self._supports_async = False + self._supports_check_mode = True + self._result = None + + # Checks the supplied parameters against the argument spec for this module + def _check_argspec(self): + aav = AnsibleArgSpecValidator( + data=self._task.args, + schema=dict(argument_spec=argument_spec), + schema_format="argspec", + schema_conditionals=dict( + required_if=required_if, + required_one_of=required_one_of, + mutually_exclusive=mutually_exclusive, + required_together=required_together, + ), + name=self._task.action, + ) + valid, errors, self._task.args = aav.validate() + if not valid: + raise AnsibleActionFail(errors) + + def run(self, tmp=None, task_vars=None): + self._task.diff = False + self._result = super(ActionModule, self).run(tmp, task_vars) + self._result["changed"] = False + self._check_argspec() + + self._result.update(dict(meraki_response={})) + + meraki = MERAKI(params=self._task.args) + + # NOTE: Does not have a get all method or it is in another action + response = None + meraki.object_modify_result(changed=False, result="Module does not have get all, check arguments of module") + self._result.update(dict(meraki_response=response)) + self._result.update(meraki.exit_json()) + return self._result diff --git a/ansible_collections/cisco/meraki/plugins/action/devices_sensor_relationships.py b/ansible_collections/cisco/meraki/plugins/action/devices_sensor_relationships.py index 75c20b830..b55f44b6e 100644 --- a/ansible_collections/cisco/meraki/plugins/action/devices_sensor_relationships.py +++ b/ansible_collections/cisco/meraki/plugins/action/devices_sensor_relationships.py @@ -78,8 +78,8 @@ class DevicesSensorRelationships(object): params=self.get_all_params(name=name), ) if isinstance(items, dict): - if 'response' in items: - items = items.get('response') + if 'livestream' in items: + items = items.get('livestream') result = get_dict_result(items, 'name', name) if result is None: result = items diff --git a/ansible_collections/cisco/meraki/plugins/action/devices_switch_ports.py b/ansible_collections/cisco/meraki/plugins/action/devices_switch_ports.py index 659e6a4f8..44a238eb2 100644 --- a/ansible_collections/cisco/meraki/plugins/action/devices_switch_ports.py +++ b/ansible_collections/cisco/meraki/plugins/action/devices_switch_ports.py @@ -32,31 +32,31 @@ argument_spec = meraki_argument_spec() # Add arguments specific for this module argument_spec.update(dict( state=dict(type="str", default="present", choices=["present"]), - name=dict(type="str"), - tags=dict(type="list"), - enabled=dict(type="bool"), - poeEnabled=dict(type="bool"), - type=dict(type="str"), - vlan=dict(type="int"), - voiceVlan=dict(type="int"), + accessPolicyNumber=dict(type="int"), + accessPolicyType=dict(type="str"), + adaptivePolicyGroupId=dict(type="str"), allowedVlans=dict(type="str"), + daiTrusted=dict(type="bool"), + enabled=dict(type="bool"), + flexibleStackingEnabled=dict(type="bool"), isolationEnabled=dict(type="bool"), - rstpEnabled=dict(type="bool"), - stpGuard=dict(type="str"), linkNegotiation=dict(type="str"), - portScheduleId=dict(type="str"), - udld=dict(type="str"), - accessPolicyType=dict(type="str"), - accessPolicyNumber=dict(type="int"), macAllowList=dict(type="list"), + name=dict(type="str"), + peerSgtCapable=dict(type="bool"), + poeEnabled=dict(type="bool"), + portScheduleId=dict(type="str"), + profile=dict(type="dict"), + rstpEnabled=dict(type="bool"), stickyMacAllowList=dict(type="list"), stickyMacAllowListLimit=dict(type="int"), stormControlEnabled=dict(type="bool"), - adaptivePolicyGroupId=dict(type="str"), - peerSgtCapable=dict(type="bool"), - flexibleStackingEnabled=dict(type="bool"), - daiTrusted=dict(type="bool"), - profile=dict(type="dict"), + stpGuard=dict(type="str"), + tags=dict(type="list"), + type=dict(type="str"), + udld=dict(type="str"), + vlan=dict(type="int"), + voiceVlan=dict(type="int"), serial=dict(type="str"), portId=dict(type="str"), )) @@ -73,31 +73,31 @@ class DevicesSwitchPorts(object): def __init__(self, params, meraki): self.meraki = meraki self.new_object = dict( - name=params.get("name"), - tags=params.get("tags"), - enabled=params.get("enabled"), - poeEnabled=params.get("poeEnabled"), - type=params.get("type"), - vlan=params.get("vlan"), - voiceVlan=params.get("voiceVlan"), + accessPolicyNumber=params.get("accessPolicyNumber"), + accessPolicyType=params.get("accessPolicyType"), + adaptivePolicyGroupId=params.get("adaptivePolicyGroupId"), allowedVlans=params.get("allowedVlans"), + daiTrusted=params.get("daiTrusted"), + enabled=params.get("enabled"), + flexibleStackingEnabled=params.get("flexibleStackingEnabled"), isolationEnabled=params.get("isolationEnabled"), - rstpEnabled=params.get("rstpEnabled"), - stpGuard=params.get("stpGuard"), linkNegotiation=params.get("linkNegotiation"), - portScheduleId=params.get("portScheduleId"), - udld=params.get("udld"), - accessPolicyType=params.get("accessPolicyType"), - accessPolicyNumber=params.get("accessPolicyNumber"), macAllowList=params.get("macAllowList"), + name=params.get("name"), + peerSgtCapable=params.get("peerSgtCapable"), + poeEnabled=params.get("poeEnabled"), + portScheduleId=params.get("portScheduleId"), + profile=params.get("profile"), + rstpEnabled=params.get("rstpEnabled"), stickyMacAllowList=params.get("stickyMacAllowList"), stickyMacAllowListLimit=params.get("stickyMacAllowListLimit"), stormControlEnabled=params.get("stormControlEnabled"), - adaptivePolicyGroupId=params.get("adaptivePolicyGroupId"), - peerSgtCapable=params.get("peerSgtCapable"), - flexibleStackingEnabled=params.get("flexibleStackingEnabled"), - daiTrusted=params.get("daiTrusted"), - profile=params.get("profile"), + stpGuard=params.get("stpGuard"), + tags=params.get("tags"), + type=params.get("type"), + udld=params.get("udld"), + vlan=params.get("vlan"), + voiceVlan=params.get("voiceVlan"), serial=params.get("serial"), port_id=params.get("portId"), ) @@ -119,55 +119,47 @@ class DevicesSwitchPorts(object): def update_by_id_params(self): new_object_params = {} - if self.new_object.get('name') is not None or self.new_object.get('name') is not None: - new_object_params['name'] = self.new_object.get('name') or \ - self.new_object.get('name') - if self.new_object.get('tags') is not None or self.new_object.get('tags') is not None: - new_object_params['tags'] = self.new_object.get('tags') or \ - self.new_object.get('tags') - if self.new_object.get('enabled') is not None or self.new_object.get('enabled') is not None: - new_object_params['enabled'] = self.new_object.get('enabled') - if self.new_object.get('poeEnabled') is not None or self.new_object.get('poe_enabled') is not None: - new_object_params['poeEnabled'] = self.new_object.get('poeEnabled') - if self.new_object.get('type') is not None or self.new_object.get('type') is not None: - new_object_params['type'] = self.new_object.get('type') or \ - self.new_object.get('type') - if self.new_object.get('vlan') is not None or self.new_object.get('vlan') is not None: - new_object_params['vlan'] = self.new_object.get('vlan') or \ - self.new_object.get('vlan') - if self.new_object.get('voiceVlan') is not None or self.new_object.get('voice_vlan') is not None: - new_object_params['voiceVlan'] = self.new_object.get('voiceVlan') or \ - self.new_object.get('voice_vlan') + if self.new_object.get('accessPolicyNumber') is not None or self.new_object.get('access_policy_number') is not None: + new_object_params['accessPolicyNumber'] = self.new_object.get('accessPolicyNumber') or \ + self.new_object.get('access_policy_number') + if self.new_object.get('accessPolicyType') is not None or self.new_object.get('access_policy_type') is not None: + new_object_params['accessPolicyType'] = self.new_object.get('accessPolicyType') or \ + self.new_object.get('access_policy_type') + if self.new_object.get('adaptivePolicyGroupId') is not None or self.new_object.get('adaptive_policy_group_id') is not None: + new_object_params['adaptivePolicyGroupId'] = self.new_object.get('adaptivePolicyGroupId') or \ + self.new_object.get('adaptive_policy_group_id') if self.new_object.get('allowedVlans') is not None or self.new_object.get('allowed_vlans') is not None: new_object_params['allowedVlans'] = self.new_object.get('allowedVlans') or \ self.new_object.get('allowed_vlans') + if self.new_object.get('daiTrusted') is not None or self.new_object.get('dai_trusted') is not None: + new_object_params['daiTrusted'] = self.new_object.get('daiTrusted') + if self.new_object.get('enabled') is not None or self.new_object.get('enabled') is not None: + new_object_params['enabled'] = self.new_object.get('enabled') + if self.new_object.get('flexibleStackingEnabled') is not None or self.new_object.get('flexible_stacking_enabled') is not None: + new_object_params['flexibleStackingEnabled'] = self.new_object.get('flexibleStackingEnabled') if self.new_object.get('isolationEnabled') is not None or self.new_object.get('isolation_enabled') is not None: - new_object_params['isolationEnabled'] = self.new_object.get( - 'isolationEnabled') - if self.new_object.get('rstpEnabled') is not None or self.new_object.get('rstp_enabled') is not None: - new_object_params['rstpEnabled'] = self.new_object.get( - 'rstpEnabled') - if self.new_object.get('stpGuard') is not None or self.new_object.get('stp_guard') is not None: - new_object_params['stpGuard'] = self.new_object.get('stpGuard') or \ - self.new_object.get('stp_guard') + new_object_params['isolationEnabled'] = self.new_object.get('isolationEnabled') if self.new_object.get('linkNegotiation') is not None or self.new_object.get('link_negotiation') is not None: new_object_params['linkNegotiation'] = self.new_object.get('linkNegotiation') or \ self.new_object.get('link_negotiation') - if self.new_object.get('portScheduleId') is not None or self.new_object.get('port_schedule_id') is not None: - new_object_params['portScheduleId'] = self.new_object.get('portScheduleId') or \ - self.new_object.get('port_schedule_id') - if self.new_object.get('udld') is not None or self.new_object.get('udld') is not None: - new_object_params['udld'] = self.new_object.get('udld') or \ - self.new_object.get('udld') - if self.new_object.get('accessPolicyType') is not None or self.new_object.get('access_policy_type') is not None: - new_object_params['accessPolicyType'] = self.new_object.get('accessPolicyType') or \ - self.new_object.get('access_policy_type') - if self.new_object.get('accessPolicyNumber') is not None or self.new_object.get('access_policy_number') is not None: - new_object_params['accessPolicyNumber'] = self.new_object.get('accessPolicyNumber') or \ - self.new_object.get('access_policy_number') if self.new_object.get('macAllowList') is not None or self.new_object.get('mac_allow_list') is not None: new_object_params['macAllowList'] = self.new_object.get('macAllowList') or \ self.new_object.get('mac_allow_list') + if self.new_object.get('name') is not None or self.new_object.get('name') is not None: + new_object_params['name'] = self.new_object.get('name') or \ + self.new_object.get('name') + if self.new_object.get('peerSgtCapable') is not None or self.new_object.get('peer_sgt_capable') is not None: + new_object_params['peerSgtCapable'] = self.new_object.get('peerSgtCapable') + if self.new_object.get('poeEnabled') is not None or self.new_object.get('poe_enabled') is not None: + new_object_params['poeEnabled'] = self.new_object.get('poeEnabled') + if self.new_object.get('portScheduleId') is not None or self.new_object.get('port_schedule_id') is not None: + new_object_params['portScheduleId'] = self.new_object.get('portScheduleId') or \ + self.new_object.get('port_schedule_id') + if self.new_object.get('profile') is not None or self.new_object.get('profile') is not None: + new_object_params['profile'] = self.new_object.get('profile') or \ + self.new_object.get('profile') + if self.new_object.get('rstpEnabled') is not None or self.new_object.get('rstp_enabled') is not None: + new_object_params['rstpEnabled'] = self.new_object.get('rstpEnabled') if self.new_object.get('stickyMacAllowList') is not None or self.new_object.get('sticky_mac_allow_list') is not None: new_object_params['stickyMacAllowList'] = self.new_object.get('stickyMacAllowList') or \ self.new_object.get('sticky_mac_allow_list') @@ -175,22 +167,25 @@ class DevicesSwitchPorts(object): new_object_params['stickyMacAllowListLimit'] = self.new_object.get('stickyMacAllowListLimit') or \ self.new_object.get('sticky_mac_allow_list_limit') if self.new_object.get('stormControlEnabled') is not None or self.new_object.get('storm_control_enabled') is not None: - new_object_params['stormControlEnabled'] = self.new_object.get( - 'stormControlEnabled') - if self.new_object.get('adaptivePolicyGroupId') is not None or self.new_object.get('adaptive_policy_group_id') is not None: - new_object_params['adaptivePolicyGroupId'] = self.new_object.get('adaptivePolicyGroupId') or \ - self.new_object.get('adaptive_policy_group_id') - if self.new_object.get('peerSgtCapable') is not None or self.new_object.get('peer_sgt_capable') is not None: - new_object_params['peerSgtCapable'] = self.new_object.get( - 'peerSgtCapable') - if self.new_object.get('flexibleStackingEnabled') is not None or self.new_object.get('flexible_stacking_enabled') is not None: - new_object_params['flexibleStackingEnabled'] = self.new_object.get( - 'flexibleStackingEnabled') - if self.new_object.get('daiTrusted') is not None or self.new_object.get('dai_trusted') is not None: - new_object_params['daiTrusted'] = self.new_object.get('daiTrusted') - if self.new_object.get('profile') is not None or self.new_object.get('profile') is not None: - new_object_params['profile'] = self.new_object.get('profile') or \ - self.new_object.get('profile') + new_object_params['stormControlEnabled'] = self.new_object.get('stormControlEnabled') + if self.new_object.get('stpGuard') is not None or self.new_object.get('stp_guard') is not None: + new_object_params['stpGuard'] = self.new_object.get('stpGuard') or \ + self.new_object.get('stp_guard') + if self.new_object.get('tags') is not None or self.new_object.get('tags') is not None: + new_object_params['tags'] = self.new_object.get('tags') or \ + self.new_object.get('tags') + if self.new_object.get('type') is not None or self.new_object.get('type') is not None: + new_object_params['type'] = self.new_object.get('type') or \ + self.new_object.get('type') + if self.new_object.get('udld') is not None or self.new_object.get('udld') is not None: + new_object_params['udld'] = self.new_object.get('udld') or \ + self.new_object.get('udld') + if self.new_object.get('vlan') is not None or self.new_object.get('vlan') is not None: + new_object_params['vlan'] = self.new_object.get('vlan') or \ + self.new_object.get('vlan') + if self.new_object.get('voiceVlan') is not None or self.new_object.get('voice_vlan') is not None: + new_object_params['voiceVlan'] = self.new_object.get('voiceVlan') or \ + self.new_object.get('voice_vlan') if self.new_object.get('serial') is not None or self.new_object.get('serial') is not None: new_object_params['serial'] = self.new_object.get('serial') or \ self.new_object.get('serial') @@ -269,31 +264,31 @@ class DevicesSwitchPorts(object): requested_obj = self.new_object obj_params = [ - ("name", "name"), - ("tags", "tags"), - ("enabled", "enabled"), - ("poeEnabled", "poeEnabled"), - ("type", "type"), - ("vlan", "vlan"), - ("voiceVlan", "voiceVlan"), + ("accessPolicyNumber", "accessPolicyNumber"), + ("accessPolicyType", "accessPolicyType"), + ("adaptivePolicyGroupId", "adaptivePolicyGroupId"), ("allowedVlans", "allowedVlans"), + ("daiTrusted", "daiTrusted"), + ("enabled", "enabled"), + ("flexibleStackingEnabled", "flexibleStackingEnabled"), ("isolationEnabled", "isolationEnabled"), - ("rstpEnabled", "rstpEnabled"), - ("stpGuard", "stpGuard"), ("linkNegotiation", "linkNegotiation"), - ("portScheduleId", "portScheduleId"), - ("udld", "udld"), - ("accessPolicyType", "accessPolicyType"), - ("accessPolicyNumber", "accessPolicyNumber"), ("macAllowList", "macAllowList"), + ("name", "name"), + ("peerSgtCapable", "peerSgtCapable"), + ("poeEnabled", "poeEnabled"), + ("portScheduleId", "portScheduleId"), + ("profile", "profile"), + ("rstpEnabled", "rstpEnabled"), ("stickyMacAllowList", "stickyMacAllowList"), ("stickyMacAllowListLimit", "stickyMacAllowListLimit"), ("stormControlEnabled", "stormControlEnabled"), - ("adaptivePolicyGroupId", "adaptivePolicyGroupId"), - ("peerSgtCapable", "peerSgtCapable"), - ("flexibleStackingEnabled", "flexibleStackingEnabled"), - ("daiTrusted", "daiTrusted"), - ("profile", "profile"), + ("stpGuard", "stpGuard"), + ("tags", "tags"), + ("type", "type"), + ("udld", "udld"), + ("vlan", "vlan"), + ("voiceVlan", "voiceVlan"), ("serial", "serial"), ("portId", "portId"), ] diff --git a/ansible_collections/cisco/meraki/plugins/action/devices_switch_routing_interfaces.py b/ansible_collections/cisco/meraki/plugins/action/devices_switch_routing_interfaces.py index 774366850..c013c4bb5 100644 --- a/ansible_collections/cisco/meraki/plugins/action/devices_switch_routing_interfaces.py +++ b/ansible_collections/cisco/meraki/plugins/action/devices_switch_routing_interfaces.py @@ -32,15 +32,15 @@ argument_spec = meraki_argument_spec() # Add arguments specific for this module argument_spec.update(dict( state=dict(type="str", default="present", choices=["present", "absent"]), - name=dict(type="str"), - subnet=dict(type="str"), + defaultGateway=dict(type="str"), interfaceIp=dict(type="str"), + ipv6=dict(type="dict"), multicastRouting=dict(type="str"), - vlanId=dict(type="int"), - defaultGateway=dict(type="str"), + name=dict(type="str"), ospfSettings=dict(type="dict"), ospfV3=dict(type="dict"), - ipv6=dict(type="dict"), + subnet=dict(type="str"), + vlanId=dict(type="int"), serial=dict(type="str"), interfaceId=dict(type="str"), )) @@ -58,15 +58,15 @@ class DevicesSwitchRoutingInterfaces(object): def __init__(self, params, meraki): self.meraki = meraki self.new_object = dict( - name=params.get("name"), - subnet=params.get("subnet"), + defaultGateway=params.get("defaultGateway"), interfaceIp=params.get("interfaceIp"), + ipv6=params.get("ipv6"), multicastRouting=params.get("multicastRouting"), - vlanId=params.get("vlanId"), - defaultGateway=params.get("defaultGateway"), + name=params.get("name"), ospfSettings=params.get("ospfSettings"), ospfV3=params.get("ospfV3"), - ipv6=params.get("ipv6"), + subnet=params.get("subnet"), + vlanId=params.get("vlanId"), serial=params.get("serial"), interfaceId=params.get("interfaceId"), ) @@ -88,33 +88,33 @@ class DevicesSwitchRoutingInterfaces(object): def create_params(self): new_object_params = {} - if self.new_object.get('name') is not None or self.new_object.get('name') is not None: - new_object_params['name'] = self.new_object.get('name') or \ - self.new_object.get('name') - if self.new_object.get('subnet') is not None or self.new_object.get('subnet') is not None: - new_object_params['subnet'] = self.new_object.get('subnet') or \ - self.new_object.get('subnet') + if self.new_object.get('defaultGateway') is not None or self.new_object.get('default_gateway') is not None: + new_object_params['defaultGateway'] = self.new_object.get('defaultGateway') or \ + self.new_object.get('default_gateway') if self.new_object.get('interfaceIp') is not None or self.new_object.get('interface_ip') is not None: new_object_params['interfaceIp'] = self.new_object.get('interfaceIp') or \ self.new_object.get('interface_ip') + if self.new_object.get('ipv6') is not None or self.new_object.get('ipv6') is not None: + new_object_params['ipv6'] = self.new_object.get('ipv6') or \ + self.new_object.get('ipv6') if self.new_object.get('multicastRouting') is not None or self.new_object.get('multicast_routing') is not None: new_object_params['multicastRouting'] = self.new_object.get('multicastRouting') or \ self.new_object.get('multicast_routing') - if self.new_object.get('vlanId') is not None or self.new_object.get('vlan_id') is not None: - new_object_params['vlanId'] = self.new_object.get('vlanId') or \ - self.new_object.get('vlan_id') - if self.new_object.get('defaultGateway') is not None or self.new_object.get('default_gateway') is not None: - new_object_params['defaultGateway'] = self.new_object.get('defaultGateway') or \ - self.new_object.get('default_gateway') + if self.new_object.get('name') is not None or self.new_object.get('name') is not None: + new_object_params['name'] = self.new_object.get('name') or \ + self.new_object.get('name') if self.new_object.get('ospfSettings') is not None or self.new_object.get('ospf_settings') is not None: new_object_params['ospfSettings'] = self.new_object.get('ospfSettings') or \ self.new_object.get('ospf_settings') if self.new_object.get('ospfV3') is not None or self.new_object.get('ospf_v3') is not None: new_object_params['ospfV3'] = self.new_object.get('ospfV3') or \ self.new_object.get('ospf_v3') - if self.new_object.get('ipv6') is not None or self.new_object.get('ipv6') is not None: - new_object_params['ipv6'] = self.new_object.get('ipv6') or \ - self.new_object.get('ipv6') + if self.new_object.get('subnet') is not None or self.new_object.get('subnet') is not None: + new_object_params['subnet'] = self.new_object.get('subnet') or \ + self.new_object.get('subnet') + if self.new_object.get('vlanId') is not None or self.new_object.get('vlan_id') is not None: + new_object_params['vlanId'] = self.new_object.get('vlanId') or \ + self.new_object.get('vlan_id') if self.new_object.get('serial') is not None or self.new_object.get('serial') is not None: new_object_params['serial'] = self.new_object.get('serial') or \ self.new_object.get('serial') @@ -132,33 +132,33 @@ class DevicesSwitchRoutingInterfaces(object): def update_by_id_params(self): new_object_params = {} - if self.new_object.get('name') is not None or self.new_object.get('name') is not None: - new_object_params['name'] = self.new_object.get('name') or \ - self.new_object.get('name') - if self.new_object.get('subnet') is not None or self.new_object.get('subnet') is not None: - new_object_params['subnet'] = self.new_object.get('subnet') or \ - self.new_object.get('subnet') + if self.new_object.get('defaultGateway') is not None or self.new_object.get('default_gateway') is not None: + new_object_params['defaultGateway'] = self.new_object.get('defaultGateway') or \ + self.new_object.get('default_gateway') if self.new_object.get('interfaceIp') is not None or self.new_object.get('interface_ip') is not None: new_object_params['interfaceIp'] = self.new_object.get('interfaceIp') or \ self.new_object.get('interface_ip') + if self.new_object.get('ipv6') is not None or self.new_object.get('ipv6') is not None: + new_object_params['ipv6'] = self.new_object.get('ipv6') or \ + self.new_object.get('ipv6') if self.new_object.get('multicastRouting') is not None or self.new_object.get('multicast_routing') is not None: new_object_params['multicastRouting'] = self.new_object.get('multicastRouting') or \ self.new_object.get('multicast_routing') - if self.new_object.get('vlanId') is not None or self.new_object.get('vlan_id') is not None: - new_object_params['vlanId'] = self.new_object.get('vlanId') or \ - self.new_object.get('vlan_id') - if self.new_object.get('defaultGateway') is not None or self.new_object.get('default_gateway') is not None: - new_object_params['defaultGateway'] = self.new_object.get('defaultGateway') or \ - self.new_object.get('default_gateway') + if self.new_object.get('name') is not None or self.new_object.get('name') is not None: + new_object_params['name'] = self.new_object.get('name') or \ + self.new_object.get('name') if self.new_object.get('ospfSettings') is not None or self.new_object.get('ospf_settings') is not None: new_object_params['ospfSettings'] = self.new_object.get('ospfSettings') or \ self.new_object.get('ospf_settings') if self.new_object.get('ospfV3') is not None or self.new_object.get('ospf_v3') is not None: new_object_params['ospfV3'] = self.new_object.get('ospfV3') or \ self.new_object.get('ospf_v3') - if self.new_object.get('ipv6') is not None or self.new_object.get('ipv6') is not None: - new_object_params['ipv6'] = self.new_object.get('ipv6') or \ - self.new_object.get('ipv6') + if self.new_object.get('subnet') is not None or self.new_object.get('subnet') is not None: + new_object_params['subnet'] = self.new_object.get('subnet') or \ + self.new_object.get('subnet') + if self.new_object.get('vlanId') is not None or self.new_object.get('vlan_id') is not None: + new_object_params['vlanId'] = self.new_object.get('vlanId') or \ + self.new_object.get('vlan_id') if self.new_object.get('serial') is not None or self.new_object.get('serial') is not None: new_object_params['serial'] = self.new_object.get('serial') or \ self.new_object.get('serial') @@ -236,15 +236,15 @@ class DevicesSwitchRoutingInterfaces(object): requested_obj = self.new_object obj_params = [ - ("name", "name"), - ("subnet", "subnet"), + ("defaultGateway", "defaultGateway"), ("interfaceIp", "interfaceIp"), + ("ipv6", "ipv6"), ("multicastRouting", "multicastRouting"), - ("vlanId", "vlanId"), - ("defaultGateway", "defaultGateway"), + ("name", "name"), ("ospfSettings", "ospfSettings"), ("ospfV3", "ospfV3"), - ("ipv6", "ipv6"), + ("subnet", "subnet"), + ("vlanId", "vlanId"), ("serial", "serial"), ("interfaceId", "interfaceId"), ] diff --git a/ansible_collections/cisco/meraki/plugins/action/devices_switch_routing_interfaces_dhcp.py b/ansible_collections/cisco/meraki/plugins/action/devices_switch_routing_interfaces_dhcp.py index 4fdb74e4e..39063de9f 100644 --- a/ansible_collections/cisco/meraki/plugins/action/devices_switch_routing_interfaces_dhcp.py +++ b/ansible_collections/cisco/meraki/plugins/action/devices_switch_routing_interfaces_dhcp.py @@ -32,17 +32,17 @@ argument_spec = meraki_argument_spec() # Add arguments specific for this module argument_spec.update(dict( state=dict(type="str", default="present", choices=["present"]), + bootFileName=dict(type="str"), + bootNextServer=dict(type="str"), + bootOptionsEnabled=dict(type="bool"), + dhcpLeaseTime=dict(type="str"), dhcpMode=dict(type="str"), + dhcpOptions=dict(type="list"), dhcpRelayServerIps=dict(type="list"), - dhcpLeaseTime=dict(type="str"), - dnsNameserversOption=dict(type="str"), dnsCustomNameservers=dict(type="list"), - bootOptionsEnabled=dict(type="bool"), - bootNextServer=dict(type="str"), - bootFileName=dict(type="str"), - dhcpOptions=dict(type="list"), - reservedIpRanges=dict(type="list"), + dnsNameserversOption=dict(type="str"), fixedIpAssignments=dict(type="list"), + reservedIpRanges=dict(type="list"), serial=dict(type="str"), interfaceId=dict(type="str"), )) @@ -59,17 +59,17 @@ class DevicesSwitchRoutingInterfacesDhcp(object): def __init__(self, params, meraki): self.meraki = meraki self.new_object = dict( + bootFileName=params.get("bootFileName"), + bootNextServer=params.get("bootNextServer"), + bootOptionsEnabled=params.get("bootOptionsEnabled"), + dhcpLeaseTime=params.get("dhcpLeaseTime"), dhcpMode=params.get("dhcpMode"), + dhcpOptions=params.get("dhcpOptions"), dhcpRelayServerIps=params.get("dhcpRelayServerIps"), - dhcpLeaseTime=params.get("dhcpLeaseTime"), - dnsNameserversOption=params.get("dnsNameserversOption"), dnsCustomNameservers=params.get("dnsCustomNameservers"), - bootOptionsEnabled=params.get("bootOptionsEnabled"), - bootNextServer=params.get("bootNextServer"), - bootFileName=params.get("bootFileName"), - dhcpOptions=params.get("dhcpOptions"), - reservedIpRanges=params.get("reservedIpRanges"), + dnsNameserversOption=params.get("dnsNameserversOption"), fixedIpAssignments=params.get("fixedIpAssignments"), + reservedIpRanges=params.get("reservedIpRanges"), serial=params.get("serial"), interface_id=params.get("interfaceId"), ) @@ -85,38 +85,38 @@ class DevicesSwitchRoutingInterfacesDhcp(object): def update_all_params(self): new_object_params = {} + if self.new_object.get('bootFileName') is not None or self.new_object.get('boot_file_name') is not None: + new_object_params['bootFileName'] = self.new_object.get('bootFileName') or \ + self.new_object.get('boot_file_name') + if self.new_object.get('bootNextServer') is not None or self.new_object.get('boot_next_server') is not None: + new_object_params['bootNextServer'] = self.new_object.get('bootNextServer') or \ + self.new_object.get('boot_next_server') + if self.new_object.get('bootOptionsEnabled') is not None or self.new_object.get('boot_options_enabled') is not None: + new_object_params['bootOptionsEnabled'] = self.new_object.get('bootOptionsEnabled') + if self.new_object.get('dhcpLeaseTime') is not None or self.new_object.get('dhcp_lease_time') is not None: + new_object_params['dhcpLeaseTime'] = self.new_object.get('dhcpLeaseTime') or \ + self.new_object.get('dhcp_lease_time') if self.new_object.get('dhcpMode') is not None or self.new_object.get('dhcp_mode') is not None: new_object_params['dhcpMode'] = self.new_object.get('dhcpMode') or \ self.new_object.get('dhcp_mode') + if self.new_object.get('dhcpOptions') is not None or self.new_object.get('dhcp_options') is not None: + new_object_params['dhcpOptions'] = self.new_object.get('dhcpOptions') or \ + self.new_object.get('dhcp_options') if self.new_object.get('dhcpRelayServerIps') is not None or self.new_object.get('dhcp_relay_server_ips') is not None: new_object_params['dhcpRelayServerIps'] = self.new_object.get('dhcpRelayServerIps') or \ self.new_object.get('dhcp_relay_server_ips') - if self.new_object.get('dhcpLeaseTime') is not None or self.new_object.get('dhcp_lease_time') is not None: - new_object_params['dhcpLeaseTime'] = self.new_object.get('dhcpLeaseTime') or \ - self.new_object.get('dhcp_lease_time') - if self.new_object.get('dnsNameserversOption') is not None or self.new_object.get('dns_nameservers_option') is not None: - new_object_params['dnsNameserversOption'] = self.new_object.get('dnsNameserversOption') or \ - self.new_object.get('dns_nameservers_option') if self.new_object.get('dnsCustomNameservers') is not None or self.new_object.get('dns_custom_nameservers') is not None: new_object_params['dnsCustomNameservers'] = self.new_object.get('dnsCustomNameservers') or \ self.new_object.get('dns_custom_nameservers') - if self.new_object.get('bootOptionsEnabled') is not None or self.new_object.get('boot_options_enabled') is not None: - new_object_params['bootOptionsEnabled'] = self.new_object.get('bootOptionsEnabled') - if self.new_object.get('bootNextServer') is not None or self.new_object.get('boot_next_server') is not None: - new_object_params['bootNextServer'] = self.new_object.get('bootNextServer') or \ - self.new_object.get('boot_next_server') - if self.new_object.get('bootFileName') is not None or self.new_object.get('boot_file_name') is not None: - new_object_params['bootFileName'] = self.new_object.get('bootFileName') or \ - self.new_object.get('boot_file_name') - if self.new_object.get('dhcpOptions') is not None or self.new_object.get('dhcp_options') is not None: - new_object_params['dhcpOptions'] = self.new_object.get('dhcpOptions') or \ - self.new_object.get('dhcp_options') - if self.new_object.get('reservedIpRanges') is not None or self.new_object.get('reserved_ip_ranges') is not None: - new_object_params['reservedIpRanges'] = self.new_object.get('reservedIpRanges') or \ - self.new_object.get('reserved_ip_ranges') + if self.new_object.get('dnsNameserversOption') is not None or self.new_object.get('dns_nameservers_option') is not None: + new_object_params['dnsNameserversOption'] = self.new_object.get('dnsNameserversOption') or \ + self.new_object.get('dns_nameservers_option') if self.new_object.get('fixedIpAssignments') is not None or self.new_object.get('fixed_ip_assignments') is not None: new_object_params['fixedIpAssignments'] = self.new_object.get('fixedIpAssignments') or \ self.new_object.get('fixed_ip_assignments') + if self.new_object.get('reservedIpRanges') is not None or self.new_object.get('reserved_ip_ranges') is not None: + new_object_params['reservedIpRanges'] = self.new_object.get('reservedIpRanges') or \ + self.new_object.get('reserved_ip_ranges') if self.new_object.get('serial') is not None or self.new_object.get('serial') is not None: new_object_params['serial'] = self.new_object.get('serial') or \ self.new_object.get('serial') @@ -176,17 +176,17 @@ class DevicesSwitchRoutingInterfacesDhcp(object): requested_obj = self.new_object obj_params = [ + ("bootFileName", "bootFileName"), + ("bootNextServer", "bootNextServer"), + ("bootOptionsEnabled", "bootOptionsEnabled"), + ("dhcpLeaseTime", "dhcpLeaseTime"), ("dhcpMode", "dhcpMode"), + ("dhcpOptions", "dhcpOptions"), ("dhcpRelayServerIps", "dhcpRelayServerIps"), - ("dhcpLeaseTime", "dhcpLeaseTime"), - ("dnsNameserversOption", "dnsNameserversOption"), ("dnsCustomNameservers", "dnsCustomNameservers"), - ("bootOptionsEnabled", "bootOptionsEnabled"), - ("bootNextServer", "bootNextServer"), - ("bootFileName", "bootFileName"), - ("dhcpOptions", "dhcpOptions"), - ("reservedIpRanges", "reservedIpRanges"), + ("dnsNameserversOption", "dnsNameserversOption"), ("fixedIpAssignments", "fixedIpAssignments"), + ("reservedIpRanges", "reservedIpRanges"), ("serial", "serial"), ("interfaceId", "interfaceId"), ] diff --git a/ansible_collections/cisco/meraki/plugins/action/devices_switch_routing_static_routes.py b/ansible_collections/cisco/meraki/plugins/action/devices_switch_routing_static_routes.py index e24a6e721..f146b8447 100644 --- a/ansible_collections/cisco/meraki/plugins/action/devices_switch_routing_static_routes.py +++ b/ansible_collections/cisco/meraki/plugins/action/devices_switch_routing_static_routes.py @@ -32,11 +32,11 @@ argument_spec = meraki_argument_spec() # Add arguments specific for this module argument_spec.update(dict( state=dict(type="str", default="present", choices=["present", "absent"]), + advertiseViaOspfEnabled=dict(type="bool"), name=dict(type="str"), - subnet=dict(type="str"), nextHopIp=dict(type="str"), - advertiseViaOspfEnabled=dict(type="bool"), preferOverOspfRoutesEnabled=dict(type="bool"), + subnet=dict(type="str"), serial=dict(type="str"), staticRouteId=dict(type="str"), )) @@ -54,11 +54,11 @@ class DevicesSwitchRoutingStaticRoutes(object): def __init__(self, params, meraki): self.meraki = meraki self.new_object = dict( + advertiseViaOspfEnabled=params.get("advertiseViaOspfEnabled"), name=params.get("name"), - subnet=params.get("subnet"), nextHopIp=params.get("nextHopIp"), - advertiseViaOspfEnabled=params.get("advertiseViaOspfEnabled"), preferOverOspfRoutesEnabled=params.get("preferOverOspfRoutesEnabled"), + subnet=params.get("subnet"), serial=params.get("serial"), staticRouteId=params.get("staticRouteId"), ) @@ -80,19 +80,19 @@ class DevicesSwitchRoutingStaticRoutes(object): def create_params(self): new_object_params = {} + if self.new_object.get('advertiseViaOspfEnabled') is not None or self.new_object.get('advertise_via_ospf_enabled') is not None: + new_object_params['advertiseViaOspfEnabled'] = self.new_object.get('advertiseViaOspfEnabled') if self.new_object.get('name') is not None or self.new_object.get('name') is not None: new_object_params['name'] = self.new_object.get('name') or \ self.new_object.get('name') - if self.new_object.get('subnet') is not None or self.new_object.get('subnet') is not None: - new_object_params['subnet'] = self.new_object.get('subnet') or \ - self.new_object.get('subnet') if self.new_object.get('nextHopIp') is not None or self.new_object.get('next_hop_ip') is not None: new_object_params['nextHopIp'] = self.new_object.get('nextHopIp') or \ self.new_object.get('next_hop_ip') - if self.new_object.get('advertiseViaOspfEnabled') is not None or self.new_object.get('advertise_via_ospf_enabled') is not None: - new_object_params['advertiseViaOspfEnabled'] = self.new_object.get('advertiseViaOspfEnabled') if self.new_object.get('preferOverOspfRoutesEnabled') is not None or self.new_object.get('prefer_over_ospf_routes_enabled') is not None: new_object_params['preferOverOspfRoutesEnabled'] = self.new_object.get('preferOverOspfRoutesEnabled') + if self.new_object.get('subnet') is not None or self.new_object.get('subnet') is not None: + new_object_params['subnet'] = self.new_object.get('subnet') or \ + self.new_object.get('subnet') if self.new_object.get('serial') is not None or self.new_object.get('serial') is not None: new_object_params['serial'] = self.new_object.get('serial') or \ self.new_object.get('serial') @@ -110,19 +110,19 @@ class DevicesSwitchRoutingStaticRoutes(object): def update_by_id_params(self): new_object_params = {} + if self.new_object.get('advertiseViaOspfEnabled') is not None or self.new_object.get('advertise_via_ospf_enabled') is not None: + new_object_params['advertiseViaOspfEnabled'] = self.new_object.get('advertiseViaOspfEnabled') if self.new_object.get('name') is not None or self.new_object.get('name') is not None: new_object_params['name'] = self.new_object.get('name') or \ self.new_object.get('name') - if self.new_object.get('subnet') is not None or self.new_object.get('subnet') is not None: - new_object_params['subnet'] = self.new_object.get('subnet') or \ - self.new_object.get('subnet') if self.new_object.get('nextHopIp') is not None or self.new_object.get('next_hop_ip') is not None: new_object_params['nextHopIp'] = self.new_object.get('nextHopIp') or \ self.new_object.get('next_hop_ip') - if self.new_object.get('advertiseViaOspfEnabled') is not None or self.new_object.get('advertise_via_ospf_enabled') is not None: - new_object_params['advertiseViaOspfEnabled'] = self.new_object.get('advertiseViaOspfEnabled') if self.new_object.get('preferOverOspfRoutesEnabled') is not None or self.new_object.get('prefer_over_ospf_routes_enabled') is not None: new_object_params['preferOverOspfRoutesEnabled'] = self.new_object.get('preferOverOspfRoutesEnabled') + if self.new_object.get('subnet') is not None or self.new_object.get('subnet') is not None: + new_object_params['subnet'] = self.new_object.get('subnet') or \ + self.new_object.get('subnet') if self.new_object.get('serial') is not None or self.new_object.get('serial') is not None: new_object_params['serial'] = self.new_object.get('serial') or \ self.new_object.get('serial') @@ -200,11 +200,11 @@ class DevicesSwitchRoutingStaticRoutes(object): requested_obj = self.new_object obj_params = [ + ("advertiseViaOspfEnabled", "advertiseViaOspfEnabled"), ("name", "name"), - ("subnet", "subnet"), ("nextHopIp", "nextHopIp"), - ("advertiseViaOspfEnabled", "advertiseViaOspfEnabled"), ("preferOverOspfRoutesEnabled", "preferOverOspfRoutesEnabled"), + ("subnet", "subnet"), ("serial", "serial"), ("staticRouteId", "staticRouteId"), ] diff --git a/ansible_collections/cisco/meraki/plugins/action/devices_wireless_alternate_management_interface_ipv6.py b/ansible_collections/cisco/meraki/plugins/action/devices_wireless_alternate_management_interface_ipv6.py new file mode 100644 index 000000000..41447bb98 --- /dev/null +++ b/ansible_collections/cisco/meraki/plugins/action/devices_wireless_alternate_management_interface_ipv6.py @@ -0,0 +1,89 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +# Copyright (c) 2021, Cisco Systems +# 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 +from ansible.plugins.action import ActionBase +try: + from ansible_collections.ansible.utils.plugins.module_utils.common.argspec_validate import ( + AnsibleArgSpecValidator, + ) +except ImportError: + ANSIBLE_UTILS_IS_INSTALLED = False +else: + ANSIBLE_UTILS_IS_INSTALLED = True +from ansible.errors import AnsibleActionFail +from ansible_collections.cisco.meraki.plugins.plugin_utils.meraki import ( + MERAKI, + meraki_argument_spec, +) + +# Get common arguements specification +argument_spec = meraki_argument_spec() +# Add arguments specific for this module +argument_spec.update(dict( + addresses=dict(type="list"), + serial=dict(type="str"), +)) + +required_if = [] +required_one_of = [] +mutually_exclusive = [] +required_together = [] + + +class ActionModule(ActionBase): + def __init__(self, *args, **kwargs): + if not ANSIBLE_UTILS_IS_INSTALLED: + raise AnsibleActionFail( + "ansible.utils is not installed. Execute 'ansible-galaxy collection install ansible.utils'") + super(ActionModule, self).__init__(*args, **kwargs) + self._supports_async = False + self._supports_check_mode = False + self._result = None + + # Checks the supplied parameters against the argument spec for this module + def _check_argspec(self): + aav = AnsibleArgSpecValidator( + data=self._task.args, + schema=dict(argument_spec=argument_spec), + schema_format="argspec", + schema_conditionals=dict( + required_if=required_if, + required_one_of=required_one_of, + mutually_exclusive=mutually_exclusive, + required_together=required_together, + ), + name=self._task.action, + ) + valid, errors, self._task.args = aav.validate() + if not valid: + raise AnsibleActionFail(errors) + + def get_object(self, params): + new_object = dict( + addresses=params.get("addresses"), + serial=params.get("serial"), + ) + return new_object + + def run(self, tmp=None, task_vars=None): + self._task.diff = False + self._result = super(ActionModule, self).run(tmp, task_vars) + self._result["changed"] = False + self._check_argspec() + + meraki = MERAKI(params=self._task.args) + + response = meraki.exec_meraki( + family="wireless", + function='updateDeviceWirelessAlternateManagementInterfaceIpv6', + op_modifies=True, + params=self.get_object(self._task.args), + ) + self._result.update(dict(meraki_response=response)) + self._result.update(meraki.exit_json()) + return self._result diff --git a/ansible_collections/cisco/meraki/plugins/action/devices_wireless_bluetooth_settings.py b/ansible_collections/cisco/meraki/plugins/action/devices_wireless_bluetooth_settings.py index dd3712df6..f1f41d07c 100644 --- a/ansible_collections/cisco/meraki/plugins/action/devices_wireless_bluetooth_settings.py +++ b/ansible_collections/cisco/meraki/plugins/action/devices_wireless_bluetooth_settings.py @@ -32,9 +32,9 @@ argument_spec = meraki_argument_spec() # Add arguments specific for this module argument_spec.update(dict( state=dict(type="str", default="present", choices=["present"]), - uuid=dict(type="str"), major=dict(type="int"), minor=dict(type="int"), + uuid=dict(type="str"), serial=dict(type="str"), )) @@ -50,9 +50,9 @@ class DevicesWirelessBluetoothSettings(object): def __init__(self, params, meraki): self.meraki = meraki self.new_object = dict( - uuid=params.get("uuid"), major=params.get("major"), minor=params.get("minor"), + uuid=params.get("uuid"), serial=params.get("serial"), ) @@ -64,15 +64,15 @@ class DevicesWirelessBluetoothSettings(object): def update_all_params(self): new_object_params = {} - if self.new_object.get('uuid') is not None or self.new_object.get('uuid') is not None: - new_object_params['uuid'] = self.new_object.get('uuid') or \ - self.new_object.get('uuid') if self.new_object.get('major') is not None or self.new_object.get('major') is not None: new_object_params['major'] = self.new_object.get('major') or \ self.new_object.get('major') if self.new_object.get('minor') is not None or self.new_object.get('minor') is not None: new_object_params['minor'] = self.new_object.get('minor') or \ self.new_object.get('minor') + if self.new_object.get('uuid') is not None or self.new_object.get('uuid') is not None: + new_object_params['uuid'] = self.new_object.get('uuid') or \ + self.new_object.get('uuid') if self.new_object.get('serial') is not None or self.new_object.get('serial') is not None: new_object_params['serial'] = self.new_object.get('serial') or \ self.new_object.get('serial') @@ -129,9 +129,9 @@ class DevicesWirelessBluetoothSettings(object): requested_obj = self.new_object obj_params = [ - ("uuid", "uuid"), ("major", "major"), ("minor", "minor"), + ("uuid", "uuid"), ("serial", "serial"), ] # Method 1. Params present in request (Ansible) obj are the same as the current (ISE) params diff --git a/ansible_collections/cisco/meraki/plugins/action/devices_wireless_radio_settings.py b/ansible_collections/cisco/meraki/plugins/action/devices_wireless_radio_settings.py index 72dad3f48..2fc35da7b 100644 --- a/ansible_collections/cisco/meraki/plugins/action/devices_wireless_radio_settings.py +++ b/ansible_collections/cisco/meraki/plugins/action/devices_wireless_radio_settings.py @@ -32,9 +32,9 @@ argument_spec = meraki_argument_spec() # Add arguments specific for this module argument_spec.update(dict( state=dict(type="str", default="present", choices=["present"]), + fiveGhzSettings=dict(type="dict"), rfProfileId=dict(type="str"), twoFourGhzSettings=dict(type="dict"), - fiveGhzSettings=dict(type="dict"), serial=dict(type="str"), )) @@ -50,9 +50,9 @@ class DevicesWirelessRadioSettings(object): def __init__(self, params, meraki): self.meraki = meraki self.new_object = dict( + fiveGhzSettings=params.get("fiveGhzSettings"), rfProfileId=params.get("rfProfileId"), twoFourGhzSettings=params.get("twoFourGhzSettings"), - fiveGhzSettings=params.get("fiveGhzSettings"), serial=params.get("serial"), ) @@ -64,15 +64,15 @@ class DevicesWirelessRadioSettings(object): def update_all_params(self): new_object_params = {} + if self.new_object.get('fiveGhzSettings') is not None or self.new_object.get('five_ghz_settings') is not None: + new_object_params['fiveGhzSettings'] = self.new_object.get('fiveGhzSettings') or \ + self.new_object.get('five_ghz_settings') if self.new_object.get('rfProfileId') is not None or self.new_object.get('rf_profile_id') is not None: new_object_params['rfProfileId'] = self.new_object.get('rfProfileId') or \ self.new_object.get('rf_profile_id') if self.new_object.get('twoFourGhzSettings') is not None or self.new_object.get('two_four_ghz_settings') is not None: new_object_params['twoFourGhzSettings'] = self.new_object.get('twoFourGhzSettings') or \ self.new_object.get('two_four_ghz_settings') - if self.new_object.get('fiveGhzSettings') is not None or self.new_object.get('five_ghz_settings') is not None: - new_object_params['fiveGhzSettings'] = self.new_object.get('fiveGhzSettings') or \ - self.new_object.get('five_ghz_settings') if self.new_object.get('serial') is not None or self.new_object.get('serial') is not None: new_object_params['serial'] = self.new_object.get('serial') or \ self.new_object.get('serial') @@ -129,9 +129,9 @@ class DevicesWirelessRadioSettings(object): requested_obj = self.new_object obj_params = [ + ("fiveGhzSettings", "fiveGhzSettings"), ("rfProfileId", "rfProfileId"), ("twoFourGhzSettings", "twoFourGhzSettings"), - ("fiveGhzSettings", "fiveGhzSettings"), ("serial", "serial"), ] # Method 1. Params present in request (Ansible) obj are the same as the current (ISE) params diff --git a/ansible_collections/cisco/meraki/plugins/action/networks.py b/ansible_collections/cisco/meraki/plugins/action/networks.py index 378b0bc0d..17904b9f8 100644 --- a/ansible_collections/cisco/meraki/plugins/action/networks.py +++ b/ansible_collections/cisco/meraki/plugins/action/networks.py @@ -32,12 +32,12 @@ argument_spec = meraki_argument_spec() # Add arguments specific for this module argument_spec.update(dict( state=dict(type="str", default="present", choices=["present", "absent"]), + copyFromNetworkId=dict(type="str"), name=dict(type="str"), + notes=dict(type="str"), productTypes=dict(type="list"), tags=dict(type="list"), timeZone=dict(type="str"), - copyFromNetworkId=dict(type="str"), - notes=dict(type="str"), organizationId=dict(type="str"), networkId=dict(type="str"), enrollmentString=dict(type="str"), @@ -56,12 +56,12 @@ class Networks(object): def __init__(self, params, meraki): self.meraki = meraki self.new_object = dict( + copyFromNetworkId=params.get("copyFromNetworkId"), name=params.get("name"), + notes=params.get("notes"), productTypes=params.get("productTypes"), tags=params.get("tags"), timeZone=params.get("timeZone"), - copyFromNetworkId=params.get("copyFromNetworkId"), - notes=params.get("notes"), organizationId=params.get("organizationId"), networkId=params.get("networkId"), enrollmentString=params.get("enrollmentString"), @@ -104,9 +104,15 @@ class Networks(object): def create_params(self): new_object_params = {} + if self.new_object.get('copyFromNetworkId') is not None or self.new_object.get('copy_from_network_id') is not None: + new_object_params['copyFromNetworkId'] = self.new_object.get('copyFromNetworkId') or \ + self.new_object.get('copy_from_network_id') if self.new_object.get('name') is not None or self.new_object.get('name') is not None: new_object_params['name'] = self.new_object.get('name') or \ self.new_object.get('name') + if self.new_object.get('notes') is not None or self.new_object.get('notes') is not None: + new_object_params['notes'] = self.new_object.get('notes') or \ + self.new_object.get('notes') if self.new_object.get('productTypes') is not None or self.new_object.get('product_types') is not None: new_object_params['productTypes'] = self.new_object.get('productTypes') or \ self.new_object.get('product_types') @@ -116,12 +122,6 @@ class Networks(object): if self.new_object.get('timeZone') is not None or self.new_object.get('time_zone') is not None: new_object_params['timeZone'] = self.new_object.get('timeZone') or \ self.new_object.get('time_zone') - if self.new_object.get('copyFromNetworkId') is not None or self.new_object.get('copy_from_network_id') is not None: - new_object_params['copyFromNetworkId'] = self.new_object.get('copyFromNetworkId') or \ - self.new_object.get('copy_from_network_id') - if self.new_object.get('notes') is not None or self.new_object.get('notes') is not None: - new_object_params['notes'] = self.new_object.get('notes') or \ - self.new_object.get('notes') if self.new_object.get('organizationId') is not None or self.new_object.get('organization_id') is not None: new_object_params['organizationId'] = self.new_object.get('organizationId') or \ self.new_object.get('organization_id') @@ -136,24 +136,21 @@ class Networks(object): def update_by_id_params(self): new_object_params = {} - if self.new_object.get('name') is not None or self.new_object.get('name') is not None: - new_object_params['name'] = self.new_object.get('name') or \ - self.new_object.get('name') - if self.new_object.get('timeZone') is not None or self.new_object.get('time_zone') is not None: - new_object_params['timeZone'] = self.new_object.get('timeZone') or \ - self.new_object.get('time_zone') - if self.new_object.get('productTypes') is not None or self.new_object.get('product_types') is not None: - new_object_params['productTypes'] = self.new_object.get('productTypes') or \ - self.new_object.get('product_types') - if self.new_object.get('tags') is not None or self.new_object.get('tags') is not None: - new_object_params['tags'] = self.new_object.get('tags') or \ - self.new_object.get('tags') if self.new_object.get('enrollmentString') is not None or self.new_object.get('enrollment_string') is not None: new_object_params['enrollmentString'] = self.new_object.get('enrollmentString') or \ self.new_object.get('enrollment_string') + if self.new_object.get('name') is not None or self.new_object.get('name') is not None: + new_object_params['name'] = self.new_object.get('name') or \ + self.new_object.get('name') if self.new_object.get('notes') is not None or self.new_object.get('notes') is not None: new_object_params['notes'] = self.new_object.get('notes') or \ self.new_object.get('notes') + if self.new_object.get('tags') is not None or self.new_object.get('tags') is not None: + new_object_params['tags'] = self.new_object.get('tags') or \ + self.new_object.get('tags') + if self.new_object.get('timeZone') is not None or self.new_object.get('time_zone') is not None: + new_object_params['timeZone'] = self.new_object.get('timeZone') or \ + self.new_object.get('time_zone') if self.new_object.get('networkId') is not None or self.new_object.get('network_id') is not None: new_object_params['networkId'] = self.new_object.get('networkId') or \ self.new_object.get('network_id') @@ -228,12 +225,12 @@ class Networks(object): requested_obj = self.new_object obj_params = [ + ("copyFromNetworkId", "copyFromNetworkId"), ("name", "name"), + ("notes", "notes"), ("productTypes", "productTypes"), ("tags", "tags"), ("timeZone", "timeZone"), - ("copyFromNetworkId", "copyFromNetworkId"), - ("notes", "notes"), ("organizationId", "organizationId"), ("networkId", "networkId"), ("enrollmentString", "enrollmentString"), diff --git a/ansible_collections/cisco/meraki/plugins/action/networks_alerts_settings.py b/ansible_collections/cisco/meraki/plugins/action/networks_alerts_settings.py index 9389b5db1..6d0da8e32 100644 --- a/ansible_collections/cisco/meraki/plugins/action/networks_alerts_settings.py +++ b/ansible_collections/cisco/meraki/plugins/action/networks_alerts_settings.py @@ -32,8 +32,9 @@ argument_spec = meraki_argument_spec() # Add arguments specific for this module argument_spec.update(dict( state=dict(type="str", default="present", choices=["present"]), - defaultDestinations=dict(type="dict"), alerts=dict(type="list"), + defaultDestinations=dict(type="dict"), + muting=dict(type="dict"), networkId=dict(type="str"), )) @@ -49,8 +50,9 @@ class NetworksAlertsSettings(object): def __init__(self, params, meraki): self.meraki = meraki self.new_object = dict( - defaultDestinations=params.get("defaultDestinations"), alerts=params.get("alerts"), + defaultDestinations=params.get("defaultDestinations"), + muting=params.get("muting"), network_id=params.get("networkId"), ) @@ -63,12 +65,15 @@ class NetworksAlertsSettings(object): def update_all_params(self): new_object_params = {} - if self.new_object.get('defaultDestinations') is not None or self.new_object.get('default_destinations') is not None: - new_object_params['defaultDestinations'] = self.new_object.get('defaultDestinations') or \ - self.new_object.get('default_destinations') if self.new_object.get('alerts') is not None or self.new_object.get('alerts') is not None: new_object_params['alerts'] = self.new_object.get('alerts') or \ self.new_object.get('alerts') + if self.new_object.get('defaultDestinations') is not None or self.new_object.get('default_destinations') is not None: + new_object_params['defaultDestinations'] = self.new_object.get('defaultDestinations') or \ + self.new_object.get('default_destinations') + if self.new_object.get('muting') is not None or self.new_object.get('muting') is not None: + new_object_params['muting'] = self.new_object.get('muting') or \ + self.new_object.get('muting') if self.new_object.get('networkId') is not None or self.new_object.get('network_id') is not None: new_object_params['networkId'] = self.new_object.get('networkId') or \ self.new_object.get('network_id') @@ -125,8 +130,9 @@ class NetworksAlertsSettings(object): requested_obj = self.new_object obj_params = [ - ("defaultDestinations", "defaultDestinations"), ("alerts", "alerts"), + ("defaultDestinations", "defaultDestinations"), + ("muting", "muting"), ("networkId", "networkId"), ] # Method 1. Params present in request (Ansible) obj are the same as the current (ISE) params diff --git a/ansible_collections/cisco/meraki/plugins/action/networks_appliance_content_filtering.py b/ansible_collections/cisco/meraki/plugins/action/networks_appliance_content_filtering.py index 5cad13ae6..3f1144ee3 100644 --- a/ansible_collections/cisco/meraki/plugins/action/networks_appliance_content_filtering.py +++ b/ansible_collections/cisco/meraki/plugins/action/networks_appliance_content_filtering.py @@ -33,8 +33,8 @@ argument_spec = meraki_argument_spec() argument_spec.update(dict( state=dict(type="str", default="present", choices=["present"]), allowedUrlPatterns=dict(type="list"), - blockedUrlPatterns=dict(type="list"), blockedUrlCategories=dict(type="list"), + blockedUrlPatterns=dict(type="list"), urlCategoryListSize=dict(type="str"), networkId=dict(type="str"), )) @@ -52,8 +52,8 @@ class NetworksApplianceContentFiltering(object): self.meraki = meraki self.new_object = dict( allowedUrlPatterns=params.get("allowedUrlPatterns"), - blockedUrlPatterns=params.get("blockedUrlPatterns"), blockedUrlCategories=params.get("blockedUrlCategories"), + blockedUrlPatterns=params.get("blockedUrlPatterns"), urlCategoryListSize=params.get("urlCategoryListSize"), network_id=params.get("networkId"), ) @@ -70,12 +70,12 @@ class NetworksApplianceContentFiltering(object): if self.new_object.get('allowedUrlPatterns') is not None or self.new_object.get('allowed_url_patterns') is not None: new_object_params['allowedUrlPatterns'] = self.new_object.get('allowedUrlPatterns') or \ self.new_object.get('allowed_url_patterns') - if self.new_object.get('blockedUrlPatterns') is not None or self.new_object.get('blocked_url_patterns') is not None: - new_object_params['blockedUrlPatterns'] = self.new_object.get('blockedUrlPatterns') or \ - self.new_object.get('blocked_url_patterns') if self.new_object.get('blockedUrlCategories') is not None or self.new_object.get('blocked_url_categories') is not None: new_object_params['blockedUrlCategories'] = self.new_object.get('blockedUrlCategories') or \ self.new_object.get('blocked_url_categories') + if self.new_object.get('blockedUrlPatterns') is not None or self.new_object.get('blocked_url_patterns') is not None: + new_object_params['blockedUrlPatterns'] = self.new_object.get('blockedUrlPatterns') or \ + self.new_object.get('blocked_url_patterns') if self.new_object.get('urlCategoryListSize') is not None or self.new_object.get('url_category_list_size') is not None: new_object_params['urlCategoryListSize'] = self.new_object.get('urlCategoryListSize') or \ self.new_object.get('url_category_list_size') @@ -136,8 +136,8 @@ class NetworksApplianceContentFiltering(object): obj_params = [ ("allowedUrlPatterns", "allowedUrlPatterns"), - ("blockedUrlPatterns", "blockedUrlPatterns"), ("blockedUrlCategories", "blockedUrlCategories"), + ("blockedUrlPatterns", "blockedUrlPatterns"), ("urlCategoryListSize", "urlCategoryListSize"), ("networkId", "networkId"), ] diff --git a/ansible_collections/cisco/meraki/plugins/action/networks_appliance_ports.py b/ansible_collections/cisco/meraki/plugins/action/networks_appliance_ports.py index 1c57e3fb3..c6a4ddbfb 100644 --- a/ansible_collections/cisco/meraki/plugins/action/networks_appliance_ports.py +++ b/ansible_collections/cisco/meraki/plugins/action/networks_appliance_ports.py @@ -32,12 +32,12 @@ argument_spec = meraki_argument_spec() # Add arguments specific for this module argument_spec.update(dict( state=dict(type="str", default="present", choices=["present"]), - enabled=dict(type="bool"), + accessPolicy=dict(type="str"), + allowedVlans=dict(type="str"), dropUntaggedTraffic=dict(type="bool"), + enabled=dict(type="bool"), type=dict(type="str"), vlan=dict(type="int"), - allowedVlans=dict(type="str"), - accessPolicy=dict(type="str"), networkId=dict(type="str"), portId=dict(type="str"), )) @@ -54,12 +54,12 @@ class NetworksAppliancePorts(object): def __init__(self, params, meraki): self.meraki = meraki self.new_object = dict( - enabled=params.get("enabled"), + accessPolicy=params.get("accessPolicy"), + allowedVlans=params.get("allowedVlans"), dropUntaggedTraffic=params.get("dropUntaggedTraffic"), + enabled=params.get("enabled"), type=params.get("type"), vlan=params.get("vlan"), - allowedVlans=params.get("allowedVlans"), - accessPolicy=params.get("accessPolicy"), network_id=params.get("networkId"), port_id=params.get("portId"), ) @@ -83,22 +83,22 @@ class NetworksAppliancePorts(object): def update_by_id_params(self): new_object_params = {} - if self.new_object.get('enabled') is not None or self.new_object.get('enabled') is not None: - new_object_params['enabled'] = self.new_object.get('enabled') + if self.new_object.get('accessPolicy') is not None or self.new_object.get('access_policy') is not None: + new_object_params['accessPolicy'] = self.new_object.get('accessPolicy') or \ + self.new_object.get('access_policy') + if self.new_object.get('allowedVlans') is not None or self.new_object.get('allowed_vlans') is not None: + new_object_params['allowedVlans'] = self.new_object.get('allowedVlans') or \ + self.new_object.get('allowed_vlans') if self.new_object.get('dropUntaggedTraffic') is not None or self.new_object.get('drop_untagged_traffic') is not None: new_object_params['dropUntaggedTraffic'] = self.new_object.get('dropUntaggedTraffic') + if self.new_object.get('enabled') is not None or self.new_object.get('enabled') is not None: + new_object_params['enabled'] = self.new_object.get('enabled') if self.new_object.get('type') is not None or self.new_object.get('type') is not None: new_object_params['type'] = self.new_object.get('type') or \ self.new_object.get('type') if self.new_object.get('vlan') is not None or self.new_object.get('vlan') is not None: new_object_params['vlan'] = self.new_object.get('vlan') or \ self.new_object.get('vlan') - if self.new_object.get('allowedVlans') is not None or self.new_object.get('allowed_vlans') is not None: - new_object_params['allowedVlans'] = self.new_object.get('allowedVlans') or \ - self.new_object.get('allowed_vlans') - if self.new_object.get('accessPolicy') is not None or self.new_object.get('access_policy') is not None: - new_object_params['accessPolicy'] = self.new_object.get('accessPolicy') or \ - self.new_object.get('access_policy') if self.new_object.get('networkId') is not None or self.new_object.get('network_id') is not None: new_object_params['networkId'] = self.new_object.get('networkId') or \ self.new_object.get('network_id') @@ -176,12 +176,12 @@ class NetworksAppliancePorts(object): requested_obj = self.new_object obj_params = [ - ("enabled", "enabled"), + ("accessPolicy", "accessPolicy"), + ("allowedVlans", "allowedVlans"), ("dropUntaggedTraffic", "dropUntaggedTraffic"), + ("enabled", "enabled"), ("type", "type"), ("vlan", "vlan"), - ("allowedVlans", "allowedVlans"), - ("accessPolicy", "accessPolicy"), ("networkId", "networkId"), ("portId", "portId"), ] diff --git a/ansible_collections/cisco/meraki/plugins/action/networks_appliance_prefixes_delegated_statics.py b/ansible_collections/cisco/meraki/plugins/action/networks_appliance_prefixes_delegated_statics.py index 0297ff01e..f0fdfec7c 100644 --- a/ansible_collections/cisco/meraki/plugins/action/networks_appliance_prefixes_delegated_statics.py +++ b/ansible_collections/cisco/meraki/plugins/action/networks_appliance_prefixes_delegated_statics.py @@ -32,9 +32,9 @@ argument_spec = meraki_argument_spec() # Add arguments specific for this module argument_spec.update(dict( state=dict(type="str", default="present", choices=["present", "absent"]), - prefix=dict(type="str"), - origin=dict(type="dict"), description=dict(type="str"), + origin=dict(type="dict"), + prefix=dict(type="str"), networkId=dict(type="str"), staticDelegatedPrefixId=dict(type="str"), )) @@ -52,9 +52,9 @@ class NetworksAppliancePrefixesDelegatedStatics(object): def __init__(self, params, meraki): self.meraki = meraki self.new_object = dict( - prefix=params.get("prefix"), - origin=params.get("origin"), description=params.get("description"), + origin=params.get("origin"), + prefix=params.get("prefix"), networkId=params.get("networkId"), staticDelegatedPrefixId=params.get("staticDelegatedPrefixId"), ) @@ -78,15 +78,15 @@ class NetworksAppliancePrefixesDelegatedStatics(object): def create_params(self): new_object_params = {} - if self.new_object.get('prefix') is not None or self.new_object.get('prefix') is not None: - new_object_params['prefix'] = self.new_object.get('prefix') or \ - self.new_object.get('prefix') - if self.new_object.get('origin') is not None or self.new_object.get('origin') is not None: - new_object_params['origin'] = self.new_object.get('origin') or \ - self.new_object.get('origin') if self.new_object.get('description') is not None or self.new_object.get('description') is not None: new_object_params['description'] = self.new_object.get('description') or \ self.new_object.get('description') + if self.new_object.get('origin') is not None or self.new_object.get('origin') is not None: + new_object_params['origin'] = self.new_object.get('origin') or \ + self.new_object.get('origin') + if self.new_object.get('prefix') is not None or self.new_object.get('prefix') is not None: + new_object_params['prefix'] = self.new_object.get('prefix') or \ + self.new_object.get('prefix') if self.new_object.get('networkId') is not None or self.new_object.get('network_id') is not None: new_object_params['networkId'] = self.new_object.get('networkId') or \ self.new_object.get('network_id') @@ -104,15 +104,15 @@ class NetworksAppliancePrefixesDelegatedStatics(object): def update_by_id_params(self): new_object_params = {} - if self.new_object.get('prefix') is not None or self.new_object.get('prefix') is not None: - new_object_params['prefix'] = self.new_object.get('prefix') or \ - self.new_object.get('prefix') - if self.new_object.get('origin') is not None or self.new_object.get('origin') is not None: - new_object_params['origin'] = self.new_object.get('origin') or \ - self.new_object.get('origin') if self.new_object.get('description') is not None or self.new_object.get('description') is not None: new_object_params['description'] = self.new_object.get('description') or \ self.new_object.get('description') + if self.new_object.get('origin') is not None or self.new_object.get('origin') is not None: + new_object_params['origin'] = self.new_object.get('origin') or \ + self.new_object.get('origin') + if self.new_object.get('prefix') is not None or self.new_object.get('prefix') is not None: + new_object_params['prefix'] = self.new_object.get('prefix') or \ + self.new_object.get('prefix') if self.new_object.get('networkId') is not None or self.new_object.get('network_id') is not None: new_object_params['networkId'] = self.new_object.get('networkId') or \ self.new_object.get('network_id') @@ -190,9 +190,9 @@ class NetworksAppliancePrefixesDelegatedStatics(object): requested_obj = self.new_object obj_params = [ - ("prefix", "prefix"), - ("origin", "origin"), ("description", "description"), + ("origin", "origin"), + ("prefix", "prefix"), ("networkId", "networkId"), ("staticDelegatedPrefixId", "staticDelegatedPrefixId"), ] diff --git a/ansible_collections/cisco/meraki/plugins/action/networks_appliance_rf_profiles.py b/ansible_collections/cisco/meraki/plugins/action/networks_appliance_rf_profiles.py new file mode 100644 index 000000000..88a31b2d1 --- /dev/null +++ b/ansible_collections/cisco/meraki/plugins/action/networks_appliance_rf_profiles.py @@ -0,0 +1,252 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +# Copyright (c) 2021, Cisco Systems +# 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 +from ansible.plugins.action import ActionBase +try: + from ansible_collections.ansible.utils.plugins.module_utils.common.argspec_validate import ( + AnsibleArgSpecValidator, + ) +except ImportError: + ANSIBLE_UTILS_IS_INSTALLED = False +else: + ANSIBLE_UTILS_IS_INSTALLED = True +from ansible.errors import AnsibleActionFail +from ansible_collections.cisco.meraki.plugins.plugin_utils.meraki import ( + MERAKI, + meraki_argument_spec, + meraki_compare_equality, + get_dict_result, +) +from ansible_collections.cisco.meraki.plugins.plugin_utils.exceptions import ( + InconsistentParameters, +) + +# Get common arguments specification +argument_spec = meraki_argument_spec() +# Add arguments specific for this module +argument_spec.update(dict( + state=dict(type="str", default="present", choices=["present", "absent"]), + fiveGhzSettings=dict(type="dict"), + name=dict(type="str"), + perSsidSettings=dict(type="dict"), + twoFourGhzSettings=dict(type="dict"), + networkId=dict(type="str"), +)) + +required_if = [ + ("state", "present", ["name", "networkId"], True), + ("state", "absent", ["name", "networkId"], True), +] +required_one_of = [] +mutually_exclusive = [] +required_together = [] + + +class NetworksApplianceRfProfiles(object): + def __init__(self, params, meraki): + self.meraki = meraki + self.new_object = dict( + fiveGhzSettings=params.get("fiveGhzSettings"), + name=params.get("name"), + perSsidSettings=params.get("perSsidSettings"), + twoFourGhzSettings=params.get("twoFourGhzSettings"), + networkId=params.get("networkId"), + ) + + def get_all_params(self, name=None, id=None): + new_object_params = {} + if self.new_object.get('networkId') is not None or self.new_object.get('network_id') is not None: + new_object_params['networkId'] = self.new_object.get('networkId') or \ + self.new_object.get('network_id') + return new_object_params + + def create_params(self): + new_object_params = {} + if self.new_object.get('fiveGhzSettings') is not None or self.new_object.get('five_ghz_settings') is not None: + new_object_params['fiveGhzSettings'] = self.new_object.get('fiveGhzSettings') or \ + self.new_object.get('five_ghz_settings') + if self.new_object.get('name') is not None or self.new_object.get('name') is not None: + new_object_params['name'] = self.new_object.get('name') or \ + self.new_object.get('name') + if self.new_object.get('perSsidSettings') is not None or self.new_object.get('per_ssid_settings') is not None: + new_object_params['perSsidSettings'] = self.new_object.get('perSsidSettings') or \ + self.new_object.get('per_ssid_settings') + if self.new_object.get('twoFourGhzSettings') is not None or self.new_object.get('two_four_ghz_settings') is not None: + new_object_params['twoFourGhzSettings'] = self.new_object.get('twoFourGhzSettings') or \ + self.new_object.get('two_four_ghz_settings') + if self.new_object.get('networkId') is not None or self.new_object.get('network_id') is not None: + new_object_params['networkId'] = self.new_object.get('networkId') or \ + self.new_object.get('network_id') + return new_object_params + + def get_object_by_name(self, name): + result = None + # NOTE: Does not have a get by name method or it is in another action + try: + items = self.meraki.exec_meraki( + family="appliance", + function="getNetworkApplianceRfProfiles", + params=self.get_all_params(name=name), + ) + if isinstance(items, dict): + if 'assigned' in items: + items = items.get('assigned') + result = get_dict_result(items, 'name', name) + if result is None: + result = items + except Exception as e: + print("Error: ", e) + result = None + return result + + def get_object_by_id(self, id): + result = None + # NOTE: Does not have a get by id method or it is in another action + try: + items = self.meraki.exec_meraki( + family="appliance", + function="getNetworkApplianceRfProfiles", + params=self.get_all_params(id=id), + ) + if isinstance(items, dict): + if 'response' in items: + items = items.get('response') + result = get_dict_result(items, 'id', id) + except Exception as e: + print("Error: ", e) + result = None + return result + + def exists(self): + id_exists = False + name_exists = False + prev_obj = None + o_id = self.new_object.get("id") + name = self.new_object.get("name") + if o_id: + prev_obj = self.get_object_by_id(o_id) + id_exists = prev_obj is not None and isinstance(prev_obj, dict) + if not id_exists and name: + prev_obj = self.get_object_by_name(name) + name_exists = prev_obj is not None and isinstance(prev_obj, dict) + if name_exists: + _id = prev_obj.get("id") + if id_exists and name_exists and o_id != _id: + raise InconsistentParameters( + "The 'id' and 'name' params don't refer to the same object") + if _id: + self.new_object.update(dict(id=_id)) + it_exists = prev_obj is not None and isinstance(prev_obj, dict) + return (it_exists, prev_obj) + + def requires_update(self, current_obj): + requested_obj = self.new_object + + obj_params = [ + ("fiveGhzSettings", "fiveGhzSettings"), + ("name", "name"), + ("perSsidSettings", "perSsidSettings"), + ("twoFourGhzSettings", "twoFourGhzSettings"), + ("networkId", "networkId"), + ] + # Method 1. Params present in request (Ansible) obj are the same as the current (DNAC) params + # If any does not have eq params, it requires update + return any(not meraki_compare_equality(current_obj.get(meraki_param), + requested_obj.get(ansible_param)) + for (meraki_param, ansible_param) in obj_params) + + def create(self): + result = self.meraki.exec_meraki( + family="appliance", + function="createNetworkApplianceRfProfile", + params=self.create_params(), + op_modifies=True, + ) + return result + + def update(self): + id = self.new_object.get("id") + name = self.new_object.get("name") + result = None + # NOTE: Does not have update method. What do we do? + return result + + def delete(self): + id = self.new_object.get("id") + name = self.new_object.get("name") + result = None + # NOTE: Does not have delete method. What do we do? + return result + + +class ActionModule(ActionBase): + def __init__(self, *args, **kwargs): + if not ANSIBLE_UTILS_IS_INSTALLED: + raise AnsibleActionFail( + "ansible.utils is not installed. Execute 'ansible-galaxy collection install ansible.utils'") + super(ActionModule, self).__init__(*args, **kwargs) + self._supports_async = False + self._supports_check_mode = False + self._result = None + + # Checks the supplied parameters against the argument spec for this module + def _check_argspec(self): + aav = AnsibleArgSpecValidator( + data=self._task.args, + schema=dict(argument_spec=argument_spec), + schema_format="argspec", + schema_conditionals=dict( + required_if=required_if, + required_one_of=required_one_of, + mutually_exclusive=mutually_exclusive, + required_together=required_together, + ), + name=self._task.action, + ) + valid, errors, self._task.args = aav.validate() + if not valid: + raise AnsibleActionFail(errors) + + def run(self, tmp=None, task_vars=None): + self._task.diff = False + self._result = super(ActionModule, self).run(tmp, task_vars) + self._result["changed"] = False + self._check_argspec() + + meraki = MERAKI(self._task.args) + obj = NetworksApplianceRfProfiles(self._task.args, meraki) + + state = self._task.args.get("state") + + response = None + + if state == "present": + (obj_exists, prev_obj) = obj.exists() + if obj_exists: + if obj.requires_update(prev_obj): + response = obj.update() + meraki.object_updated() + else: + response = prev_obj + meraki.object_already_present() + else: + response = obj.create() + meraki.object_created() + + elif state == "absent": + (obj_exists, prev_obj) = obj.exists() + if obj_exists: + response = obj.delete() + meraki.object_deleted() + else: + meraki.object_already_absent() + + self._result.update(dict(meraki_response=response)) + self._result.update(meraki.exit_json()) + return self._result diff --git a/ansible_collections/cisco/meraki/plugins/action/networks_appliance_rf_profiles_info.py b/ansible_collections/cisco/meraki/plugins/action/networks_appliance_rf_profiles_info.py new file mode 100644 index 000000000..863571233 --- /dev/null +++ b/ansible_collections/cisco/meraki/plugins/action/networks_appliance_rf_profiles_info.py @@ -0,0 +1,90 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +# Copyright (c) 2021, Cisco Systems +# 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 +from ansible.plugins.action import ActionBase +try: + from ansible_collections.ansible.utils.plugins.module_utils.common.argspec_validate import ( + AnsibleArgSpecValidator, + ) +except ImportError: + ANSIBLE_UTILS_IS_INSTALLED = False +else: + ANSIBLE_UTILS_IS_INSTALLED = True +from ansible.errors import AnsibleActionFail +from ansible_collections.cisco.meraki.plugins.plugin_utils.meraki import ( + MERAKI, + meraki_argument_spec, +) + +# Get common arguments specification +argument_spec = meraki_argument_spec() +# Add arguments specific for this module +argument_spec.update(dict( + networkId=dict(type="str"), +)) + +required_if = [] +required_one_of = [] +mutually_exclusive = [] +required_together = [] + + +class ActionModule(ActionBase): + def __init__(self, *args, **kwargs): + if not ANSIBLE_UTILS_IS_INSTALLED: + raise AnsibleActionFail( + "ansible.utils is not installed. Execute 'ansible-galaxy collection install ansible.utils'") + super(ActionModule, self).__init__(*args, **kwargs) + self._supports_async = False + self._supports_check_mode = True + self._result = None + + # Checks the supplied parameters against the argument spec for this module + def _check_argspec(self): + aav = AnsibleArgSpecValidator( + data=self._task.args, + schema=dict(argument_spec=argument_spec), + schema_format="argspec", + schema_conditionals=dict( + required_if=required_if, + required_one_of=required_one_of, + mutually_exclusive=mutually_exclusive, + required_together=required_together, + ), + name=self._task.action, + ) + valid, errors, self._task.args = aav.validate() + if not valid: + raise AnsibleActionFail(errors) + + def get_all(self, params): + new_object = {} + if params.get("networkId") is not None: + new_object["networkId"] = params.get( + "networkId") + + return new_object + + def run(self, tmp=None, task_vars=None): + self._task.diff = False + self._result = super(ActionModule, self).run(tmp, task_vars) + self._result["changed"] = False + self._check_argspec() + + self._result.update(dict(meraki_response={})) + + meraki = MERAKI(params=self._task.args) + + response = meraki.exec_meraki( + family="appliance", + function='getNetworkApplianceRfProfiles', + params=self.get_all(self._task.args), + ) + self._result.update(dict(meraki_response=response)) + self._result.update(meraki.exit_json()) + return self._result diff --git a/ansible_collections/cisco/meraki/plugins/action/networks_appliance_security_intrusion.py b/ansible_collections/cisco/meraki/plugins/action/networks_appliance_security_intrusion.py index 3449abf9c..6da952d48 100644 --- a/ansible_collections/cisco/meraki/plugins/action/networks_appliance_security_intrusion.py +++ b/ansible_collections/cisco/meraki/plugins/action/networks_appliance_security_intrusion.py @@ -32,8 +32,8 @@ argument_spec = meraki_argument_spec() # Add arguments specific for this module argument_spec.update(dict( state=dict(type="str", default="present", choices=["present"]), - mode=dict(type="str"), idsRulesets=dict(type="str"), + mode=dict(type="str"), protectedNetworks=dict(type="dict"), networkId=dict(type="str"), )) @@ -50,8 +50,8 @@ class NetworksApplianceSecurityIntrusion(object): def __init__(self, params, meraki): self.meraki = meraki self.new_object = dict( - mode=params.get("mode"), idsRulesets=params.get("idsRulesets"), + mode=params.get("mode"), protectedNetworks=params.get("protectedNetworks"), network_id=params.get("networkId"), ) @@ -65,12 +65,12 @@ class NetworksApplianceSecurityIntrusion(object): def update_all_params(self): new_object_params = {} - if self.new_object.get('mode') is not None or self.new_object.get('mode') is not None: - new_object_params['mode'] = self.new_object.get('mode') or \ - self.new_object.get('mode') if self.new_object.get('idsRulesets') is not None or self.new_object.get('ids_rulesets') is not None: new_object_params['idsRulesets'] = self.new_object.get('idsRulesets') or \ self.new_object.get('ids_rulesets') + if self.new_object.get('mode') is not None or self.new_object.get('mode') is not None: + new_object_params['mode'] = self.new_object.get('mode') or \ + self.new_object.get('mode') if self.new_object.get('protectedNetworks') is not None or self.new_object.get('protected_networks') is not None: new_object_params['protectedNetworks'] = self.new_object.get('protectedNetworks') or \ self.new_object.get('protected_networks') @@ -130,8 +130,8 @@ class NetworksApplianceSecurityIntrusion(object): requested_obj = self.new_object obj_params = [ - ("mode", "mode"), ("idsRulesets", "idsRulesets"), + ("mode", "mode"), ("protectedNetworks", "protectedNetworks"), ("networkId", "networkId"), ] diff --git a/ansible_collections/cisco/meraki/plugins/action/networks_appliance_security_malware.py b/ansible_collections/cisco/meraki/plugins/action/networks_appliance_security_malware.py index 904889494..faef0ed12 100644 --- a/ansible_collections/cisco/meraki/plugins/action/networks_appliance_security_malware.py +++ b/ansible_collections/cisco/meraki/plugins/action/networks_appliance_security_malware.py @@ -32,9 +32,9 @@ argument_spec = meraki_argument_spec() # Add arguments specific for this module argument_spec.update(dict( state=dict(type="str", default="present", choices=["present"]), - mode=dict(type="str"), - allowedUrls=dict(type="list"), allowedFiles=dict(type="list"), + allowedUrls=dict(type="list"), + mode=dict(type="str"), networkId=dict(type="str"), )) @@ -50,9 +50,9 @@ class NetworksApplianceSecurityMalware(object): def __init__(self, params, meraki): self.meraki = meraki self.new_object = dict( - mode=params.get("mode"), - allowedUrls=params.get("allowedUrls"), allowedFiles=params.get("allowedFiles"), + allowedUrls=params.get("allowedUrls"), + mode=params.get("mode"), network_id=params.get("networkId"), ) @@ -65,15 +65,15 @@ class NetworksApplianceSecurityMalware(object): def update_all_params(self): new_object_params = {} - if self.new_object.get('mode') is not None or self.new_object.get('mode') is not None: - new_object_params['mode'] = self.new_object.get('mode') or \ - self.new_object.get('mode') - if self.new_object.get('allowedUrls') is not None or self.new_object.get('allowed_urls') is not None: - new_object_params['allowedUrls'] = self.new_object.get('allowedUrls') or \ - self.new_object.get('allowed_urls') if self.new_object.get('allowedFiles') is not None or self.new_object.get('allowed_files') is not None: new_object_params['allowedFiles'] = self.new_object.get('allowedFiles') or \ self.new_object.get('allowed_files') + if self.new_object.get('allowedUrls') is not None or self.new_object.get('allowed_urls') is not None: + new_object_params['allowedUrls'] = self.new_object.get('allowedUrls') or \ + self.new_object.get('allowed_urls') + if self.new_object.get('mode') is not None or self.new_object.get('mode') is not None: + new_object_params['mode'] = self.new_object.get('mode') or \ + self.new_object.get('mode') if self.new_object.get('networkId') is not None or self.new_object.get('network_id') is not None: new_object_params['networkId'] = self.new_object.get('networkId') or \ self.new_object.get('network_id') @@ -130,9 +130,9 @@ class NetworksApplianceSecurityMalware(object): requested_obj = self.new_object obj_params = [ - ("mode", "mode"), - ("allowedUrls", "allowedUrls"), ("allowedFiles", "allowedFiles"), + ("allowedUrls", "allowedUrls"), + ("mode", "mode"), ("networkId", "networkId"), ] # Method 1. Params present in request (Ansible) obj are the same as the current (ISE) params diff --git a/ansible_collections/cisco/meraki/plugins/action/networks_appliance_single_lan.py b/ansible_collections/cisco/meraki/plugins/action/networks_appliance_single_lan.py index fd8219403..4254f631f 100644 --- a/ansible_collections/cisco/meraki/plugins/action/networks_appliance_single_lan.py +++ b/ansible_collections/cisco/meraki/plugins/action/networks_appliance_single_lan.py @@ -32,10 +32,10 @@ argument_spec = meraki_argument_spec() # Add arguments specific for this module argument_spec.update(dict( state=dict(type="str", default="present", choices=["present"]), - subnet=dict(type="str"), applianceIp=dict(type="str"), ipv6=dict(type="dict"), mandatoryDhcp=dict(type="dict"), + subnet=dict(type="str"), networkId=dict(type="str"), )) @@ -51,10 +51,10 @@ class NetworksApplianceSingleLan(object): def __init__(self, params, meraki): self.meraki = meraki self.new_object = dict( - subnet=params.get("subnet"), applianceIp=params.get("applianceIp"), ipv6=params.get("ipv6"), mandatoryDhcp=params.get("mandatoryDhcp"), + subnet=params.get("subnet"), network_id=params.get("networkId"), ) @@ -67,9 +67,6 @@ class NetworksApplianceSingleLan(object): def update_all_params(self): new_object_params = {} - if self.new_object.get('subnet') is not None or self.new_object.get('subnet') is not None: - new_object_params['subnet'] = self.new_object.get('subnet') or \ - self.new_object.get('subnet') if self.new_object.get('applianceIp') is not None or self.new_object.get('appliance_ip') is not None: new_object_params['applianceIp'] = self.new_object.get('applianceIp') or \ self.new_object.get('appliance_ip') @@ -79,6 +76,9 @@ class NetworksApplianceSingleLan(object): if self.new_object.get('mandatoryDhcp') is not None or self.new_object.get('mandatory_dhcp') is not None: new_object_params['mandatoryDhcp'] = self.new_object.get('mandatoryDhcp') or \ self.new_object.get('mandatory_dhcp') + if self.new_object.get('subnet') is not None or self.new_object.get('subnet') is not None: + new_object_params['subnet'] = self.new_object.get('subnet') or \ + self.new_object.get('subnet') if self.new_object.get('networkId') is not None or self.new_object.get('network_id') is not None: new_object_params['networkId'] = self.new_object.get('networkId') or \ self.new_object.get('network_id') @@ -135,10 +135,10 @@ class NetworksApplianceSingleLan(object): requested_obj = self.new_object obj_params = [ - ("subnet", "subnet"), ("applianceIp", "applianceIp"), ("ipv6", "ipv6"), ("mandatoryDhcp", "mandatoryDhcp"), + ("subnet", "subnet"), ("networkId", "networkId"), ] # Method 1. Params present in request (Ansible) obj are the same as the current (ISE) params diff --git a/ansible_collections/cisco/meraki/plugins/action/networks_appliance_ssids.py b/ansible_collections/cisco/meraki/plugins/action/networks_appliance_ssids.py index cfe172d5a..364855692 100644 --- a/ansible_collections/cisco/meraki/plugins/action/networks_appliance_ssids.py +++ b/ansible_collections/cisco/meraki/plugins/action/networks_appliance_ssids.py @@ -32,16 +32,17 @@ argument_spec = meraki_argument_spec() # Add arguments specific for this module argument_spec.update(dict( state=dict(type="str", default="present", choices=["present"]), - name=dict(type="str"), - enabled=dict(type="bool"), - defaultVlanId=dict(type="int"), authMode=dict(type="str"), + defaultVlanId=dict(type="int"), + dhcpEnforcedDeauthentication=dict(type="dict"), + dot11w=dict(type="dict"), + enabled=dict(type="bool"), + encryptionMode=dict(type="str"), + name=dict(type="str"), psk=dict(type="str"), radiusServers=dict(type="list"), - encryptionMode=dict(type="str"), - wpaEncryptionMode=dict(type="str"), visible=dict(type="bool"), - dhcpEnforcedDeauthentication=dict(type="dict"), + wpaEncryptionMode=dict(type="str"), networkId=dict(type="str"), number=dict(type="str"), )) @@ -58,16 +59,17 @@ class NetworksApplianceSsids(object): def __init__(self, params, meraki): self.meraki = meraki self.new_object = dict( - name=params.get("name"), - enabled=params.get("enabled"), - defaultVlanId=params.get("defaultVlanId"), authMode=params.get("authMode"), + defaultVlanId=params.get("defaultVlanId"), + dhcpEnforcedDeauthentication=params.get("dhcpEnforcedDeauthentication"), + dot11w=params.get("dot11w"), + enabled=params.get("enabled"), + encryptionMode=params.get("encryptionMode"), + name=params.get("name"), psk=params.get("psk"), radiusServers=params.get("radiusServers"), - encryptionMode=params.get("encryptionMode"), - wpaEncryptionMode=params.get("wpaEncryptionMode"), visible=params.get("visible"), - dhcpEnforcedDeauthentication=params.get("dhcpEnforcedDeauthentication"), + wpaEncryptionMode=params.get("wpaEncryptionMode"), network_id=params.get("networkId"), number=params.get("number"), ) @@ -90,34 +92,37 @@ class NetworksApplianceSsids(object): def update_by_id_params(self): new_object_params = {} - if self.new_object.get('name') is not None or self.new_object.get('name') is not None: - new_object_params['name'] = self.new_object.get('name') or \ - self.new_object.get('name') - if self.new_object.get('enabled') is not None or self.new_object.get('enabled') is not None: - new_object_params['enabled'] = self.new_object.get('enabled') - if self.new_object.get('defaultVlanId') is not None or self.new_object.get('default_vlan_id') is not None: - new_object_params['defaultVlanId'] = self.new_object.get('defaultVlanId') or \ - self.new_object.get('default_vlan_id') if self.new_object.get('authMode') is not None or self.new_object.get('auth_mode') is not None: new_object_params['authMode'] = self.new_object.get('authMode') or \ self.new_object.get('auth_mode') + if self.new_object.get('defaultVlanId') is not None or self.new_object.get('default_vlan_id') is not None: + new_object_params['defaultVlanId'] = self.new_object.get('defaultVlanId') or \ + self.new_object.get('default_vlan_id') + if self.new_object.get('dhcpEnforcedDeauthentication') is not None or self.new_object.get('dhcp_enforced_deauthentication') is not None: + new_object_params['dhcpEnforcedDeauthentication'] = self.new_object.get('dhcpEnforcedDeauthentication') or \ + self.new_object.get('dhcp_enforced_deauthentication') + if self.new_object.get('dot11w') is not None or self.new_object.get('dot11w') is not None: + new_object_params['dot11w'] = self.new_object.get('dot11w') or \ + self.new_object.get('dot11w') + if self.new_object.get('enabled') is not None or self.new_object.get('enabled') is not None: + new_object_params['enabled'] = self.new_object.get('enabled') + if self.new_object.get('encryptionMode') is not None or self.new_object.get('encryption_mode') is not None: + new_object_params['encryptionMode'] = self.new_object.get('encryptionMode') or \ + self.new_object.get('encryption_mode') + if self.new_object.get('name') is not None or self.new_object.get('name') is not None: + new_object_params['name'] = self.new_object.get('name') or \ + self.new_object.get('name') if self.new_object.get('psk') is not None or self.new_object.get('psk') is not None: new_object_params['psk'] = self.new_object.get('psk') or \ self.new_object.get('psk') if self.new_object.get('radiusServers') is not None or self.new_object.get('radius_servers') is not None: new_object_params['radiusServers'] = self.new_object.get('radiusServers') or \ self.new_object.get('radius_servers') - if self.new_object.get('encryptionMode') is not None or self.new_object.get('encryption_mode') is not None: - new_object_params['encryptionMode'] = self.new_object.get('encryptionMode') or \ - self.new_object.get('encryption_mode') + if self.new_object.get('visible') is not None or self.new_object.get('visible') is not None: + new_object_params['visible'] = self.new_object.get('visible') if self.new_object.get('wpaEncryptionMode') is not None or self.new_object.get('wpa_encryption_mode') is not None: new_object_params['wpaEncryptionMode'] = self.new_object.get('wpaEncryptionMode') or \ self.new_object.get('wpa_encryption_mode') - if self.new_object.get('visible') is not None or self.new_object.get('visible') is not None: - new_object_params['visible'] = self.new_object.get('visible') - if self.new_object.get('dhcpEnforcedDeauthentication') is not None or self.new_object.get('dhcp_enforced_deauthentication') is not None: - new_object_params['dhcpEnforcedDeauthentication'] = self.new_object.get('dhcpEnforcedDeauthentication') or \ - self.new_object.get('dhcp_enforced_deauthentication') if self.new_object.get('networkId') is not None or self.new_object.get('network_id') is not None: new_object_params['networkId'] = self.new_object.get('networkId') or \ self.new_object.get('network_id') @@ -195,16 +200,17 @@ class NetworksApplianceSsids(object): requested_obj = self.new_object obj_params = [ - ("name", "name"), - ("enabled", "enabled"), - ("defaultVlanId", "defaultVlanId"), ("authMode", "authMode"), + ("defaultVlanId", "defaultVlanId"), + ("dhcpEnforcedDeauthentication", "dhcpEnforcedDeauthentication"), + ("dot11w", "dot11w"), + ("enabled", "enabled"), + ("encryptionMode", "encryptionMode"), + ("name", "name"), ("psk", "psk"), ("radiusServers", "radiusServers"), - ("encryptionMode", "encryptionMode"), - ("wpaEncryptionMode", "wpaEncryptionMode"), ("visible", "visible"), - ("dhcpEnforcedDeauthentication", "dhcpEnforcedDeauthentication"), + ("wpaEncryptionMode", "wpaEncryptionMode"), ("networkId", "networkId"), ("number", "number"), ] diff --git a/ansible_collections/cisco/meraki/plugins/action/networks_appliance_traffic_shaping_custom_performance_classes.py b/ansible_collections/cisco/meraki/plugins/action/networks_appliance_traffic_shaping_custom_performance_classes.py index 4331bc9b2..dd072c4c8 100644 --- a/ansible_collections/cisco/meraki/plugins/action/networks_appliance_traffic_shaping_custom_performance_classes.py +++ b/ansible_collections/cisco/meraki/plugins/action/networks_appliance_traffic_shaping_custom_performance_classes.py @@ -25,10 +25,10 @@ from ansible_collections.cisco.meraki.plugins.plugin_utils.meraki import ( argument_spec = meraki_argument_spec() # Add arguments specific for this module argument_spec.update(dict( - name=dict(type="str"), - maxLatency=dict(type="int"), maxJitter=dict(type="int"), + maxLatency=dict(type="int"), maxLossPercentage=dict(type="int"), + name=dict(type="str"), networkId=dict(type="str"), )) @@ -68,10 +68,10 @@ class ActionModule(ActionBase): def get_object(self, params): new_object = dict( - name=params.get("name"), - maxLatency=params.get("maxLatency"), maxJitter=params.get("maxJitter"), + maxLatency=params.get("maxLatency"), maxLossPercentage=params.get("maxLossPercentage"), + name=params.get("name"), networkId=params.get("networkId"), ) return new_object diff --git a/ansible_collections/cisco/meraki/plugins/action/networks_appliance_traffic_shaping_uplink_selection.py b/ansible_collections/cisco/meraki/plugins/action/networks_appliance_traffic_shaping_uplink_selection.py index 79b737a1e..525ba5f77 100644 --- a/ansible_collections/cisco/meraki/plugins/action/networks_appliance_traffic_shaping_uplink_selection.py +++ b/ansible_collections/cisco/meraki/plugins/action/networks_appliance_traffic_shaping_uplink_selection.py @@ -34,10 +34,10 @@ argument_spec.update(dict( state=dict(type="str", default="present", choices=["present"]), activeActiveAutoVpnEnabled=dict(type="bool"), defaultUplink=dict(type="str"), - loadBalancingEnabled=dict(type="bool"), failoverAndFailback=dict(type="dict"), - wanTrafficUplinkPreferences=dict(type="list"), + loadBalancingEnabled=dict(type="bool"), vpnTrafficUplinkPreferences=dict(type="list"), + wanTrafficUplinkPreferences=dict(type="list"), networkId=dict(type="str"), )) @@ -55,10 +55,10 @@ class NetworksApplianceTrafficShapingUplinkSelection(object): self.new_object = dict( activeActiveAutoVpnEnabled=params.get("activeActiveAutoVpnEnabled"), defaultUplink=params.get("defaultUplink"), - loadBalancingEnabled=params.get("loadBalancingEnabled"), failoverAndFailback=params.get("failoverAndFailback"), - wanTrafficUplinkPreferences=params.get("wanTrafficUplinkPreferences"), + loadBalancingEnabled=params.get("loadBalancingEnabled"), vpnTrafficUplinkPreferences=params.get("vpnTrafficUplinkPreferences"), + wanTrafficUplinkPreferences=params.get("wanTrafficUplinkPreferences"), network_id=params.get("networkId"), ) @@ -76,17 +76,17 @@ class NetworksApplianceTrafficShapingUplinkSelection(object): if self.new_object.get('defaultUplink') is not None or self.new_object.get('default_uplink') is not None: new_object_params['defaultUplink'] = self.new_object.get('defaultUplink') or \ self.new_object.get('default_uplink') - if self.new_object.get('loadBalancingEnabled') is not None or self.new_object.get('load_balancing_enabled') is not None: - new_object_params['loadBalancingEnabled'] = self.new_object.get('loadBalancingEnabled') if self.new_object.get('failoverAndFailback') is not None or self.new_object.get('failover_and_failback') is not None: new_object_params['failoverAndFailback'] = self.new_object.get('failoverAndFailback') or \ self.new_object.get('failover_and_failback') - if self.new_object.get('wanTrafficUplinkPreferences') is not None or self.new_object.get('wan_traffic_uplink_preferences') is not None: - new_object_params['wanTrafficUplinkPreferences'] = self.new_object.get('wanTrafficUplinkPreferences') or \ - self.new_object.get('wan_traffic_uplink_preferences') + if self.new_object.get('loadBalancingEnabled') is not None or self.new_object.get('load_balancing_enabled') is not None: + new_object_params['loadBalancingEnabled'] = self.new_object.get('loadBalancingEnabled') if self.new_object.get('vpnTrafficUplinkPreferences') is not None or self.new_object.get('vpn_traffic_uplink_preferences') is not None: new_object_params['vpnTrafficUplinkPreferences'] = self.new_object.get('vpnTrafficUplinkPreferences') or \ self.new_object.get('vpn_traffic_uplink_preferences') + if self.new_object.get('wanTrafficUplinkPreferences') is not None or self.new_object.get('wan_traffic_uplink_preferences') is not None: + new_object_params['wanTrafficUplinkPreferences'] = self.new_object.get('wanTrafficUplinkPreferences') or \ + self.new_object.get('wan_traffic_uplink_preferences') if self.new_object.get('networkId') is not None or self.new_object.get('network_id') is not None: new_object_params['networkId'] = self.new_object.get('networkId') or \ self.new_object.get('network_id') @@ -145,10 +145,10 @@ class NetworksApplianceTrafficShapingUplinkSelection(object): obj_params = [ ("activeActiveAutoVpnEnabled", "activeActiveAutoVpnEnabled"), ("defaultUplink", "defaultUplink"), - ("loadBalancingEnabled", "loadBalancingEnabled"), ("failoverAndFailback", "failoverAndFailback"), - ("wanTrafficUplinkPreferences", "wanTrafficUplinkPreferences"), + ("loadBalancingEnabled", "loadBalancingEnabled"), ("vpnTrafficUplinkPreferences", "vpnTrafficUplinkPreferences"), + ("wanTrafficUplinkPreferences", "wanTrafficUplinkPreferences"), ("networkId", "networkId"), ] # Method 1. Params present in request (Ansible) obj are the same as the current (ISE) params diff --git a/ansible_collections/cisco/meraki/plugins/action/networks_appliance_traffic_shaping_vpn_exclusions.py b/ansible_collections/cisco/meraki/plugins/action/networks_appliance_traffic_shaping_vpn_exclusions.py new file mode 100644 index 000000000..447231a08 --- /dev/null +++ b/ansible_collections/cisco/meraki/plugins/action/networks_appliance_traffic_shaping_vpn_exclusions.py @@ -0,0 +1,91 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +# Copyright (c) 2021, Cisco Systems +# 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 +from ansible.plugins.action import ActionBase +try: + from ansible_collections.ansible.utils.plugins.module_utils.common.argspec_validate import ( + AnsibleArgSpecValidator, + ) +except ImportError: + ANSIBLE_UTILS_IS_INSTALLED = False +else: + ANSIBLE_UTILS_IS_INSTALLED = True +from ansible.errors import AnsibleActionFail +from ansible_collections.cisco.meraki.plugins.plugin_utils.meraki import ( + MERAKI, + meraki_argument_spec, +) + +# Get common arguements specification +argument_spec = meraki_argument_spec() +# Add arguments specific for this module +argument_spec.update(dict( + custom=dict(type="list"), + majorApplications=dict(type="list"), + networkId=dict(type="str"), +)) + +required_if = [] +required_one_of = [] +mutually_exclusive = [] +required_together = [] + + +class ActionModule(ActionBase): + def __init__(self, *args, **kwargs): + if not ANSIBLE_UTILS_IS_INSTALLED: + raise AnsibleActionFail( + "ansible.utils is not installed. Execute 'ansible-galaxy collection install ansible.utils'") + super(ActionModule, self).__init__(*args, **kwargs) + self._supports_async = False + self._supports_check_mode = False + self._result = None + + # Checks the supplied parameters against the argument spec for this module + def _check_argspec(self): + aav = AnsibleArgSpecValidator( + data=self._task.args, + schema=dict(argument_spec=argument_spec), + schema_format="argspec", + schema_conditionals=dict( + required_if=required_if, + required_one_of=required_one_of, + mutually_exclusive=mutually_exclusive, + required_together=required_together, + ), + name=self._task.action, + ) + valid, errors, self._task.args = aav.validate() + if not valid: + raise AnsibleActionFail(errors) + + def get_object(self, params): + new_object = dict( + custom=params.get("custom"), + majorApplications=params.get("majorApplications"), + networkId=params.get("networkId"), + ) + return new_object + + def run(self, tmp=None, task_vars=None): + self._task.diff = False + self._result = super(ActionModule, self).run(tmp, task_vars) + self._result["changed"] = False + self._check_argspec() + + meraki = MERAKI(params=self._task.args) + + response = meraki.exec_meraki( + family="appliance", + function='updateNetworkApplianceTrafficShapingVpnExclusions', + op_modifies=True, + params=self.get_object(self._task.args), + ) + self._result.update(dict(meraki_response=response)) + self._result.update(meraki.exit_json()) + return self._result diff --git a/ansible_collections/cisco/meraki/plugins/action/networks_appliance_vlans.py b/ansible_collections/cisco/meraki/plugins/action/networks_appliance_vlans.py index ba4835a9d..48ebdb4ca 100644 --- a/ansible_collections/cisco/meraki/plugins/action/networks_appliance_vlans.py +++ b/ansible_collections/cisco/meraki/plugins/action/networks_appliance_vlans.py @@ -32,29 +32,29 @@ argument_spec = meraki_argument_spec() # Add arguments specific for this module argument_spec.update(dict( state=dict(type="str", default="present", choices=["present", "absent"]), - id=dict(type="str"), - name=dict(type="str"), - subnet=dict(type="str"), applianceIp=dict(type="str"), - groupPolicyId=dict(type="str"), - templateVlanType=dict(type="str"), cidr=dict(type="str"), - mask=dict(type="int"), + groupPolicyId=dict(type="str"), + id=dict(type="str"), ipv6=dict(type="dict"), mandatoryDhcp=dict(type="dict"), + mask=dict(type="int"), + name=dict(type="str"), + subnet=dict(type="str"), + templateVlanType=dict(type="str"), networkId=dict(type="str"), vlanId=dict(type="str"), - vpnNatSubnet=dict(type="str"), + dhcpBootFilename=dict(type="str"), + dhcpBootNextServer=dict(type="str"), + dhcpBootOptionsEnabled=dict(type="bool"), dhcpHandling=dict(type="str"), - dhcpRelayServerIps=dict(type="list"), dhcpLeaseTime=dict(type="str"), - dhcpBootOptionsEnabled=dict(type="bool"), - dhcpBootNextServer=dict(type="str"), - dhcpBootFilename=dict(type="str"), + dhcpOptions=dict(type="list"), + dhcpRelayServerIps=dict(type="list"), + dnsNameservers=dict(type="str"), fixedIpAssignments=dict(type="dict"), reservedIpRanges=dict(type="list"), - dnsNameservers=dict(type="str"), - dhcpOptions=dict(type="list"), + vpnNatSubnet=dict(type="str"), )) required_if = [ @@ -70,29 +70,29 @@ class NetworksApplianceVlans(object): def __init__(self, params, meraki): self.meraki = meraki self.new_object = dict( - id=params.get("id"), - name=params.get("name"), - subnet=params.get("subnet"), applianceIp=params.get("applianceIp"), - groupPolicyId=params.get("groupPolicyId"), - templateVlanType=params.get("templateVlanType"), cidr=params.get("cidr"), - mask=params.get("mask"), + groupPolicyId=params.get("groupPolicyId"), + id=params.get("id"), ipv6=params.get("ipv6"), mandatoryDhcp=params.get("mandatoryDhcp"), + mask=params.get("mask"), + name=params.get("name"), + subnet=params.get("subnet"), + templateVlanType=params.get("templateVlanType"), networkId=params.get("networkId"), vlanId=params.get("vlanId"), - vpnNatSubnet=params.get("vpnNatSubnet"), + dhcpBootFilename=params.get("dhcpBootFilename"), + dhcpBootNextServer=params.get("dhcpBootNextServer"), + dhcpBootOptionsEnabled=params.get("dhcpBootOptionsEnabled"), dhcpHandling=params.get("dhcpHandling"), - dhcpRelayServerIps=params.get("dhcpRelayServerIps"), dhcpLeaseTime=params.get("dhcpLeaseTime"), - dhcpBootOptionsEnabled=params.get("dhcpBootOptionsEnabled"), - dhcpBootNextServer=params.get("dhcpBootNextServer"), - dhcpBootFilename=params.get("dhcpBootFilename"), + dhcpOptions=params.get("dhcpOptions"), + dhcpRelayServerIps=params.get("dhcpRelayServerIps"), + dnsNameservers=params.get("dnsNameservers"), fixedIpAssignments=params.get("fixedIpAssignments"), reservedIpRanges=params.get("reservedIpRanges"), - dnsNameservers=params.get("dnsNameservers"), - dhcpOptions=params.get("dhcpOptions"), + vpnNatSubnet=params.get("vpnNatSubnet"), ) def get_all_params(self, name=None, id=None): @@ -107,43 +107,43 @@ class NetworksApplianceVlans(object): if self.new_object.get('networkId') is not None or self.new_object.get('network_id') is not None: new_object_params['networkId'] = self.new_object.get('networkId') or \ self.new_object.get('network_id') - if self.new_object.get('vlanId') is not None or self.new_object.get('vlan_id') is not None or self.new_object.get('id') is not None: + if self.new_object.get('vlanId') is not None or self.new_object.get('vlan_id') is not None: new_object_params['vlanId'] = self.new_object.get('vlanId') or \ - self.new_object.get('vlan_id') or self.new_object.get('id') + self.new_object.get('vlan_id') return new_object_params def create_params(self): new_object_params = {} - if self.new_object.get('id') is not None or self.new_object.get('id') is not None: - new_object_params['id'] = self.new_object.get('id') or \ - self.new_object.get('id') - if self.new_object.get('name') is not None or self.new_object.get('name') is not None: - new_object_params['name'] = self.new_object.get('name') or \ - self.new_object.get('name') - if self.new_object.get('subnet') is not None or self.new_object.get('subnet') is not None: - new_object_params['subnet'] = self.new_object.get('subnet') or \ - self.new_object.get('subnet') if self.new_object.get('applianceIp') is not None or self.new_object.get('appliance_ip') is not None: new_object_params['applianceIp'] = self.new_object.get('applianceIp') or \ self.new_object.get('appliance_ip') - if self.new_object.get('groupPolicyId') is not None or self.new_object.get('group_policy_id') is not None: - new_object_params['groupPolicyId'] = self.new_object.get('groupPolicyId') or \ - self.new_object.get('group_policy_id') - if self.new_object.get('templateVlanType') is not None or self.new_object.get('template_vlan_type') is not None: - new_object_params['templateVlanType'] = self.new_object.get('templateVlanType') or \ - self.new_object.get('template_vlan_type') if self.new_object.get('cidr') is not None or self.new_object.get('cidr') is not None: new_object_params['cidr'] = self.new_object.get('cidr') or \ self.new_object.get('cidr') - if self.new_object.get('mask') is not None or self.new_object.get('mask') is not None: - new_object_params['mask'] = self.new_object.get('mask') or \ - self.new_object.get('mask') + if self.new_object.get('groupPolicyId') is not None or self.new_object.get('group_policy_id') is not None: + new_object_params['groupPolicyId'] = self.new_object.get('groupPolicyId') or \ + self.new_object.get('group_policy_id') + if self.new_object.get('id') is not None or self.new_object.get('id') is not None: + new_object_params['id'] = self.new_object.get('id') or \ + self.new_object.get('id') if self.new_object.get('ipv6') is not None or self.new_object.get('ipv6') is not None: new_object_params['ipv6'] = self.new_object.get('ipv6') or \ self.new_object.get('ipv6') if self.new_object.get('mandatoryDhcp') is not None or self.new_object.get('mandatory_dhcp') is not None: new_object_params['mandatoryDhcp'] = self.new_object.get('mandatoryDhcp') or \ self.new_object.get('mandatory_dhcp') + if self.new_object.get('mask') is not None or self.new_object.get('mask') is not None: + new_object_params['mask'] = self.new_object.get('mask') or \ + self.new_object.get('mask') + if self.new_object.get('name') is not None or self.new_object.get('name') is not None: + new_object_params['name'] = self.new_object.get('name') or \ + self.new_object.get('name') + if self.new_object.get('subnet') is not None or self.new_object.get('subnet') is not None: + new_object_params['subnet'] = self.new_object.get('subnet') or \ + self.new_object.get('subnet') + if self.new_object.get('templateVlanType') is not None or self.new_object.get('template_vlan_type') is not None: + new_object_params['templateVlanType'] = self.new_object.get('templateVlanType') or \ + self.new_object.get('template_vlan_type') if self.new_object.get('networkId') is not None or self.new_object.get('network_id') is not None: new_object_params['networkId'] = self.new_object.get('networkId') or \ self.new_object.get('network_id') @@ -154,79 +154,78 @@ class NetworksApplianceVlans(object): if self.new_object.get('networkId') is not None or self.new_object.get('network_id') is not None: new_object_params['networkId'] = self.new_object.get('networkId') or \ self.new_object.get('network_id') - if self.new_object.get('vlanId') is not None or self.new_object.get('vlan_id') is not None is not None or self.new_object.get('id') is not None: + if self.new_object.get('vlanId') is not None or self.new_object.get('vlan_id') is not None: new_object_params['vlanId'] = self.new_object.get('vlanId') or \ - self.new_object.get('vlan_id') or self.new_object.get('id') + self.new_object.get('vlan_id') return new_object_params def update_by_id_params(self): new_object_params = {} - if self.new_object.get('name') is not None or self.new_object.get('name') is not None: - new_object_params['name'] = self.new_object.get('name') or \ - self.new_object.get('name') - if self.new_object.get('subnet') is not None or self.new_object.get('subnet') is not None: - new_object_params['subnet'] = self.new_object.get('subnet') or \ - self.new_object.get('subnet') if self.new_object.get('applianceIp') is not None or self.new_object.get('appliance_ip') is not None: new_object_params['applianceIp'] = self.new_object.get('applianceIp') or \ self.new_object.get('appliance_ip') - if self.new_object.get('groupPolicyId') is not None or self.new_object.get('group_policy_id') is not None: - new_object_params['groupPolicyId'] = self.new_object.get('groupPolicyId') or \ - self.new_object.get('group_policy_id') - if self.new_object.get('vpnNatSubnet') is not None or self.new_object.get('vpn_nat_subnet') is not None: - new_object_params['vpnNatSubnet'] = self.new_object.get('vpnNatSubnet') or \ - self.new_object.get('vpn_nat_subnet') + if self.new_object.get('cidr') is not None or self.new_object.get('cidr') is not None: + new_object_params['cidr'] = self.new_object.get('cidr') or \ + self.new_object.get('cidr') + if self.new_object.get('dhcpBootFilename') is not None or self.new_object.get('dhcp_boot_filename') is not None: + new_object_params['dhcpBootFilename'] = self.new_object.get('dhcpBootFilename') or \ + self.new_object.get('dhcp_boot_filename') + if self.new_object.get('dhcpBootNextServer') is not None or self.new_object.get('dhcp_boot_next_server') is not None: + new_object_params['dhcpBootNextServer'] = self.new_object.get('dhcpBootNextServer') or \ + self.new_object.get('dhcp_boot_next_server') + if self.new_object.get('dhcpBootOptionsEnabled') is not None or self.new_object.get('dhcp_boot_options_enabled') is not None: + new_object_params['dhcpBootOptionsEnabled'] = self.new_object.get('dhcpBootOptionsEnabled') if self.new_object.get('dhcpHandling') is not None or self.new_object.get('dhcp_handling') is not None: new_object_params['dhcpHandling'] = self.new_object.get('dhcpHandling') or \ self.new_object.get('dhcp_handling') - if self.new_object.get('dhcpRelayServerIps') is not None or self.new_object.get('dhcp_relay_server_ips') is not None: - new_object_params['dhcpRelayServerIps'] = self.new_object.get('dhcpRelayServerIps') or \ - self.new_object.get('dhcp_relay_server_ips') if self.new_object.get('dhcpLeaseTime') is not None or self.new_object.get('dhcp_lease_time') is not None: new_object_params['dhcpLeaseTime'] = self.new_object.get('dhcpLeaseTime') or \ self.new_object.get('dhcp_lease_time') - if self.new_object.get('dhcpBootOptionsEnabled') is not None or self.new_object.get('dhcp_boot_options_enabled') is not None: - new_object_params['dhcpBootOptionsEnabled'] = self.new_object.get( - 'dhcpBootOptionsEnabled') - if self.new_object.get('dhcpBootNextServer') is not None or self.new_object.get('dhcp_boot_next_server') is not None: - new_object_params['dhcpBootNextServer'] = self.new_object.get('dhcpBootNextServer') or \ - self.new_object.get('dhcp_boot_next_server') - if self.new_object.get('dhcpBootFilename') is not None or self.new_object.get('dhcp_boot_filename') is not None: - new_object_params['dhcpBootFilename'] = self.new_object.get('dhcpBootFilename') or \ - self.new_object.get('dhcp_boot_filename') - if self.new_object.get('fixedIpAssignments') is not None or self.new_object.get('fixed_ip_assignments') is not None: - new_object_params['fixedIpAssignments'] = self.new_object.get('fixedIpAssignments') or \ - self.new_object.get('fixed_ip_assignments') - if self.new_object.get('reservedIpRanges') is not None or self.new_object.get('reserved_ip_ranges') is not None: - new_object_params['reservedIpRanges'] = self.new_object.get('reservedIpRanges') or \ - self.new_object.get('reserved_ip_ranges') - if self.new_object.get('dnsNameservers') is not None or self.new_object.get('dns_nameservers') is not None: - new_object_params['dnsNameservers'] = self.new_object.get('dnsNameservers') or \ - self.new_object.get('dns_nameservers') if self.new_object.get('dhcpOptions') is not None or self.new_object.get('dhcp_options') is not None: new_object_params['dhcpOptions'] = self.new_object.get('dhcpOptions') or \ self.new_object.get('dhcp_options') - if self.new_object.get('templateVlanType') is not None or self.new_object.get('template_vlan_type') is not None: - new_object_params['templateVlanType'] = self.new_object.get('templateVlanType') or \ - self.new_object.get('template_vlan_type') - if self.new_object.get('cidr') is not None or self.new_object.get('cidr') is not None: - new_object_params['cidr'] = self.new_object.get('cidr') or \ - self.new_object.get('cidr') - if self.new_object.get('mask') is not None or self.new_object.get('mask') is not None: - new_object_params['mask'] = self.new_object.get('mask') or \ - self.new_object.get('mask') + if self.new_object.get('dhcpRelayServerIps') is not None or self.new_object.get('dhcp_relay_server_ips') is not None: + new_object_params['dhcpRelayServerIps'] = self.new_object.get('dhcpRelayServerIps') or \ + self.new_object.get('dhcp_relay_server_ips') + if self.new_object.get('dnsNameservers') is not None or self.new_object.get('dns_nameservers') is not None: + new_object_params['dnsNameservers'] = self.new_object.get('dnsNameservers') or \ + self.new_object.get('dns_nameservers') + if self.new_object.get('fixedIpAssignments') is not None or self.new_object.get('fixed_ip_assignments') is not None: + new_object_params['fixedIpAssignments'] = self.new_object.get('fixedIpAssignments') or \ + self.new_object.get('fixed_ip_assignments') + if self.new_object.get('groupPolicyId') is not None or self.new_object.get('group_policy_id') is not None: + new_object_params['groupPolicyId'] = self.new_object.get('groupPolicyId') or \ + self.new_object.get('group_policy_id') if self.new_object.get('ipv6') is not None or self.new_object.get('ipv6') is not None: new_object_params['ipv6'] = self.new_object.get('ipv6') or \ self.new_object.get('ipv6') if self.new_object.get('mandatoryDhcp') is not None or self.new_object.get('mandatory_dhcp') is not None: new_object_params['mandatoryDhcp'] = self.new_object.get('mandatoryDhcp') or \ self.new_object.get('mandatory_dhcp') + if self.new_object.get('mask') is not None or self.new_object.get('mask') is not None: + new_object_params['mask'] = self.new_object.get('mask') or \ + self.new_object.get('mask') + if self.new_object.get('name') is not None or self.new_object.get('name') is not None: + new_object_params['name'] = self.new_object.get('name') or \ + self.new_object.get('name') + if self.new_object.get('reservedIpRanges') is not None or self.new_object.get('reserved_ip_ranges') is not None: + new_object_params['reservedIpRanges'] = self.new_object.get('reservedIpRanges') or \ + self.new_object.get('reserved_ip_ranges') + if self.new_object.get('subnet') is not None or self.new_object.get('subnet') is not None: + new_object_params['subnet'] = self.new_object.get('subnet') or \ + self.new_object.get('subnet') + if self.new_object.get('templateVlanType') is not None or self.new_object.get('template_vlan_type') is not None: + new_object_params['templateVlanType'] = self.new_object.get('templateVlanType') or \ + self.new_object.get('template_vlan_type') + if self.new_object.get('vpnNatSubnet') is not None or self.new_object.get('vpn_nat_subnet') is not None: + new_object_params['vpnNatSubnet'] = self.new_object.get('vpnNatSubnet') or \ + self.new_object.get('vpn_nat_subnet') if self.new_object.get('networkId') is not None or self.new_object.get('network_id') is not None: new_object_params['networkId'] = self.new_object.get('networkId') or \ self.new_object.get('network_id') - if self.new_object.get('vlanId') is not None or self.new_object.get('vlan_id') is not None is not None or self.new_object.get('id') is not None: + if self.new_object.get('vlanId') is not None or self.new_object.get('vlan_id') is not None: new_object_params['vlanId'] = self.new_object.get('vlanId') or \ - self.new_object.get('vlan_id') or self.new_object.get('id') + self.new_object.get('vlan_id') return new_object_params def get_object_by_name(self, name): @@ -298,29 +297,29 @@ class NetworksApplianceVlans(object): requested_obj = self.new_object obj_params = [ - ("id", "id"), - ("name", "name"), - ("subnet", "subnet"), ("applianceIp", "applianceIp"), - ("groupPolicyId", "groupPolicyId"), - ("templateVlanType", "templateVlanType"), ("cidr", "cidr"), - ("mask", "mask"), + ("groupPolicyId", "groupPolicyId"), + ("id", "id"), ("ipv6", "ipv6"), ("mandatoryDhcp", "mandatoryDhcp"), + ("mask", "mask"), + ("name", "name"), + ("subnet", "subnet"), + ("templateVlanType", "templateVlanType"), ("networkId", "networkId"), ("vlanId", "vlanId"), - ("vpnNatSubnet", "vpnNatSubnet"), + ("dhcpBootFilename", "dhcpBootFilename"), + ("dhcpBootNextServer", "dhcpBootNextServer"), + ("dhcpBootOptionsEnabled", "dhcpBootOptionsEnabled"), ("dhcpHandling", "dhcpHandling"), - ("dhcpRelayServerIps", "dhcpRelayServerIps"), ("dhcpLeaseTime", "dhcpLeaseTime"), - ("dhcpBootOptionsEnabled", "dhcpBootOptionsEnabled"), - ("dhcpBootNextServer", "dhcpBootNextServer"), - ("dhcpBootFilename", "dhcpBootFilename"), + ("dhcpOptions", "dhcpOptions"), + ("dhcpRelayServerIps", "dhcpRelayServerIps"), + ("dnsNameservers", "dnsNameservers"), ("fixedIpAssignments", "fixedIpAssignments"), ("reservedIpRanges", "reservedIpRanges"), - ("dnsNameservers", "dnsNameservers"), - ("dhcpOptions", "dhcpOptions"), + ("vpnNatSubnet", "vpnNatSubnet"), ] # Method 1. Params present in request (Ansible) obj are the same as the current (DNAC) params # If any does not have eq params, it requires update diff --git a/ansible_collections/cisco/meraki/plugins/action/networks_appliance_vpn_bgp.py b/ansible_collections/cisco/meraki/plugins/action/networks_appliance_vpn_bgp.py index e3eba8000..956e2bf59 100644 --- a/ansible_collections/cisco/meraki/plugins/action/networks_appliance_vpn_bgp.py +++ b/ansible_collections/cisco/meraki/plugins/action/networks_appliance_vpn_bgp.py @@ -32,8 +32,8 @@ argument_spec = meraki_argument_spec() # Add arguments specific for this module argument_spec.update(dict( state=dict(type="str", default="present", choices=["present"]), - enabled=dict(type="bool"), asNumber=dict(type="int"), + enabled=dict(type="bool"), ibgpHoldTimer=dict(type="int"), neighbors=dict(type="list"), networkId=dict(type="str"), @@ -51,8 +51,8 @@ class NetworksApplianceVpnBgp(object): def __init__(self, params, meraki): self.meraki = meraki self.new_object = dict( - enabled=params.get("enabled"), asNumber=params.get("asNumber"), + enabled=params.get("enabled"), ibgpHoldTimer=params.get("ibgpHoldTimer"), neighbors=params.get("neighbors"), network_id=params.get("networkId"), @@ -67,11 +67,11 @@ class NetworksApplianceVpnBgp(object): def update_all_params(self): new_object_params = {} - if self.new_object.get('enabled') is not None or self.new_object.get('enabled') is not None: - new_object_params['enabled'] = self.new_object.get('enabled') if self.new_object.get('asNumber') is not None or self.new_object.get('as_number') is not None: new_object_params['asNumber'] = self.new_object.get('asNumber') or \ self.new_object.get('as_number') + if self.new_object.get('enabled') is not None or self.new_object.get('enabled') is not None: + new_object_params['enabled'] = self.new_object.get('enabled') if self.new_object.get('ibgpHoldTimer') is not None or self.new_object.get('ibgp_hold_timer') is not None: new_object_params['ibgpHoldTimer'] = self.new_object.get('ibgpHoldTimer') or \ self.new_object.get('ibgp_hold_timer') @@ -134,8 +134,8 @@ class NetworksApplianceVpnBgp(object): requested_obj = self.new_object obj_params = [ - ("enabled", "enabled"), ("asNumber", "asNumber"), + ("enabled", "enabled"), ("ibgpHoldTimer", "ibgpHoldTimer"), ("neighbors", "neighbors"), ("networkId", "networkId"), diff --git a/ansible_collections/cisco/meraki/plugins/action/networks_appliance_vpn_site_to_site_vpn.py b/ansible_collections/cisco/meraki/plugins/action/networks_appliance_vpn_site_to_site_vpn.py index 1a73bb08d..e687d1ed4 100644 --- a/ansible_collections/cisco/meraki/plugins/action/networks_appliance_vpn_site_to_site_vpn.py +++ b/ansible_collections/cisco/meraki/plugins/action/networks_appliance_vpn_site_to_site_vpn.py @@ -32,8 +32,8 @@ argument_spec = meraki_argument_spec() # Add arguments specific for this module argument_spec.update(dict( state=dict(type="str", default="present", choices=["present"]), - mode=dict(type="str"), hubs=dict(type="list"), + mode=dict(type="str"), subnets=dict(type="list"), networkId=dict(type="str"), )) @@ -50,8 +50,8 @@ class NetworksApplianceVpnSiteToSiteVpn(object): def __init__(self, params, meraki): self.meraki = meraki self.new_object = dict( - mode=params.get("mode"), hubs=params.get("hubs"), + mode=params.get("mode"), subnets=params.get("subnets"), network_id=params.get("networkId"), ) @@ -65,12 +65,12 @@ class NetworksApplianceVpnSiteToSiteVpn(object): def update_all_params(self): new_object_params = {} - if self.new_object.get('mode') is not None or self.new_object.get('mode') is not None: - new_object_params['mode'] = self.new_object.get('mode') or \ - self.new_object.get('mode') if self.new_object.get('hubs') is not None or self.new_object.get('hubs') is not None: new_object_params['hubs'] = self.new_object.get('hubs') or \ self.new_object.get('hubs') + if self.new_object.get('mode') is not None or self.new_object.get('mode') is not None: + new_object_params['mode'] = self.new_object.get('mode') or \ + self.new_object.get('mode') if self.new_object.get('subnets') is not None or self.new_object.get('subnets') is not None: new_object_params['subnets'] = self.new_object.get('subnets') or \ self.new_object.get('subnets') @@ -130,8 +130,8 @@ class NetworksApplianceVpnSiteToSiteVpn(object): requested_obj = self.new_object obj_params = [ - ("mode", "mode"), ("hubs", "hubs"), + ("mode", "mode"), ("subnets", "subnets"), ("networkId", "networkId"), ] diff --git a/ansible_collections/cisco/meraki/plugins/action/networks_bind.py b/ansible_collections/cisco/meraki/plugins/action/networks_bind.py index 2e65eefb3..e25f56335 100644 --- a/ansible_collections/cisco/meraki/plugins/action/networks_bind.py +++ b/ansible_collections/cisco/meraki/plugins/action/networks_bind.py @@ -25,8 +25,8 @@ from ansible_collections.cisco.meraki.plugins.plugin_utils.meraki import ( argument_spec = meraki_argument_spec() # Add arguments specific for this module argument_spec.update(dict( - configTemplateId=dict(type="str"), autoBind=dict(type="bool"), + configTemplateId=dict(type="str"), networkId=dict(type="str"), )) @@ -66,8 +66,8 @@ class ActionModule(ActionBase): def get_object(self, params): new_object = dict( - configTemplateId=params.get("configTemplateId"), autoBind=params.get("autoBind"), + configTemplateId=params.get("configTemplateId"), networkId=params.get("networkId"), ) return new_object diff --git a/ansible_collections/cisco/meraki/plugins/action/networks_camera_quality_retention_profiles.py b/ansible_collections/cisco/meraki/plugins/action/networks_camera_quality_retention_profiles.py index 29e1aae17..4b33683b8 100644 --- a/ansible_collections/cisco/meraki/plugins/action/networks_camera_quality_retention_profiles.py +++ b/ansible_collections/cisco/meraki/plugins/action/networks_camera_quality_retention_profiles.py @@ -32,14 +32,14 @@ argument_spec = meraki_argument_spec() # Add arguments specific for this module argument_spec.update(dict( state=dict(type="str", default="present", choices=["present", "absent"]), - name=dict(type="str"), - motionBasedRetentionEnabled=dict(type="bool"), - restrictedBandwidthModeEnabled=dict(type="bool"), audioRecordingEnabled=dict(type="bool"), cloudArchiveEnabled=dict(type="bool"), + maxRetentionDays=dict(type="int"), + motionBasedRetentionEnabled=dict(type="bool"), motionDetectorVersion=dict(type="int"), + name=dict(type="str"), + restrictedBandwidthModeEnabled=dict(type="bool"), scheduleId=dict(type="str"), - maxRetentionDays=dict(type="int"), videoSettings=dict(type="dict"), networkId=dict(type="str"), qualityRetentionProfileId=dict(type="str"), @@ -58,14 +58,14 @@ class NetworksCameraQualityRetentionProfiles(object): def __init__(self, params, meraki): self.meraki = meraki self.new_object = dict( - name=params.get("name"), - motionBasedRetentionEnabled=params.get("motionBasedRetentionEnabled"), - restrictedBandwidthModeEnabled=params.get("restrictedBandwidthModeEnabled"), audioRecordingEnabled=params.get("audioRecordingEnabled"), cloudArchiveEnabled=params.get("cloudArchiveEnabled"), + maxRetentionDays=params.get("maxRetentionDays"), + motionBasedRetentionEnabled=params.get("motionBasedRetentionEnabled"), motionDetectorVersion=params.get("motionDetectorVersion"), + name=params.get("name"), + restrictedBandwidthModeEnabled=params.get("restrictedBandwidthModeEnabled"), scheduleId=params.get("scheduleId"), - maxRetentionDays=params.get("maxRetentionDays"), videoSettings=params.get("videoSettings"), networkId=params.get("networkId"), qualityRetentionProfileId=params.get("qualityRetentionProfileId"), @@ -90,26 +90,26 @@ class NetworksCameraQualityRetentionProfiles(object): def create_params(self): new_object_params = {} - if self.new_object.get('name') is not None or self.new_object.get('name') is not None: - new_object_params['name'] = self.new_object.get('name') or \ - self.new_object.get('name') - if self.new_object.get('motionBasedRetentionEnabled') is not None or self.new_object.get('motion_based_retention_enabled') is not None: - new_object_params['motionBasedRetentionEnabled'] = self.new_object.get('motionBasedRetentionEnabled') - if self.new_object.get('restrictedBandwidthModeEnabled') is not None or self.new_object.get('restricted_bandwidth_mode_enabled') is not None: - new_object_params['restrictedBandwidthModeEnabled'] = self.new_object.get('restrictedBandwidthModeEnabled') if self.new_object.get('audioRecordingEnabled') is not None or self.new_object.get('audio_recording_enabled') is not None: new_object_params['audioRecordingEnabled'] = self.new_object.get('audioRecordingEnabled') if self.new_object.get('cloudArchiveEnabled') is not None or self.new_object.get('cloud_archive_enabled') is not None: new_object_params['cloudArchiveEnabled'] = self.new_object.get('cloudArchiveEnabled') + if self.new_object.get('maxRetentionDays') is not None or self.new_object.get('max_retention_days') is not None: + new_object_params['maxRetentionDays'] = self.new_object.get('maxRetentionDays') or \ + self.new_object.get('max_retention_days') + if self.new_object.get('motionBasedRetentionEnabled') is not None or self.new_object.get('motion_based_retention_enabled') is not None: + new_object_params['motionBasedRetentionEnabled'] = self.new_object.get('motionBasedRetentionEnabled') if self.new_object.get('motionDetectorVersion') is not None or self.new_object.get('motion_detector_version') is not None: new_object_params['motionDetectorVersion'] = self.new_object.get('motionDetectorVersion') or \ self.new_object.get('motion_detector_version') + if self.new_object.get('name') is not None or self.new_object.get('name') is not None: + new_object_params['name'] = self.new_object.get('name') or \ + self.new_object.get('name') + if self.new_object.get('restrictedBandwidthModeEnabled') is not None or self.new_object.get('restricted_bandwidth_mode_enabled') is not None: + new_object_params['restrictedBandwidthModeEnabled'] = self.new_object.get('restrictedBandwidthModeEnabled') if self.new_object.get('scheduleId') is not None or self.new_object.get('schedule_id') is not None: new_object_params['scheduleId'] = self.new_object.get('scheduleId') or \ self.new_object.get('schedule_id') - if self.new_object.get('maxRetentionDays') is not None or self.new_object.get('max_retention_days') is not None: - new_object_params['maxRetentionDays'] = self.new_object.get('maxRetentionDays') or \ - self.new_object.get('max_retention_days') if self.new_object.get('videoSettings') is not None or self.new_object.get('video_settings') is not None: new_object_params['videoSettings'] = self.new_object.get('videoSettings') or \ self.new_object.get('video_settings') @@ -130,26 +130,26 @@ class NetworksCameraQualityRetentionProfiles(object): def update_by_id_params(self): new_object_params = {} - if self.new_object.get('name') is not None or self.new_object.get('name') is not None: - new_object_params['name'] = self.new_object.get('name') or \ - self.new_object.get('name') - if self.new_object.get('motionBasedRetentionEnabled') is not None or self.new_object.get('motion_based_retention_enabled') is not None: - new_object_params['motionBasedRetentionEnabled'] = self.new_object.get('motionBasedRetentionEnabled') - if self.new_object.get('restrictedBandwidthModeEnabled') is not None or self.new_object.get('restricted_bandwidth_mode_enabled') is not None: - new_object_params['restrictedBandwidthModeEnabled'] = self.new_object.get('restrictedBandwidthModeEnabled') if self.new_object.get('audioRecordingEnabled') is not None or self.new_object.get('audio_recording_enabled') is not None: new_object_params['audioRecordingEnabled'] = self.new_object.get('audioRecordingEnabled') if self.new_object.get('cloudArchiveEnabled') is not None or self.new_object.get('cloud_archive_enabled') is not None: new_object_params['cloudArchiveEnabled'] = self.new_object.get('cloudArchiveEnabled') + if self.new_object.get('maxRetentionDays') is not None or self.new_object.get('max_retention_days') is not None: + new_object_params['maxRetentionDays'] = self.new_object.get('maxRetentionDays') or \ + self.new_object.get('max_retention_days') + if self.new_object.get('motionBasedRetentionEnabled') is not None or self.new_object.get('motion_based_retention_enabled') is not None: + new_object_params['motionBasedRetentionEnabled'] = self.new_object.get('motionBasedRetentionEnabled') if self.new_object.get('motionDetectorVersion') is not None or self.new_object.get('motion_detector_version') is not None: new_object_params['motionDetectorVersion'] = self.new_object.get('motionDetectorVersion') or \ self.new_object.get('motion_detector_version') + if self.new_object.get('name') is not None or self.new_object.get('name') is not None: + new_object_params['name'] = self.new_object.get('name') or \ + self.new_object.get('name') + if self.new_object.get('restrictedBandwidthModeEnabled') is not None or self.new_object.get('restricted_bandwidth_mode_enabled') is not None: + new_object_params['restrictedBandwidthModeEnabled'] = self.new_object.get('restrictedBandwidthModeEnabled') if self.new_object.get('scheduleId') is not None or self.new_object.get('schedule_id') is not None: new_object_params['scheduleId'] = self.new_object.get('scheduleId') or \ self.new_object.get('schedule_id') - if self.new_object.get('maxRetentionDays') is not None or self.new_object.get('max_retention_days') is not None: - new_object_params['maxRetentionDays'] = self.new_object.get('maxRetentionDays') or \ - self.new_object.get('max_retention_days') if self.new_object.get('videoSettings') is not None or self.new_object.get('video_settings') is not None: new_object_params['videoSettings'] = self.new_object.get('videoSettings') or \ self.new_object.get('video_settings') @@ -230,14 +230,14 @@ class NetworksCameraQualityRetentionProfiles(object): requested_obj = self.new_object obj_params = [ - ("name", "name"), - ("motionBasedRetentionEnabled", "motionBasedRetentionEnabled"), - ("restrictedBandwidthModeEnabled", "restrictedBandwidthModeEnabled"), ("audioRecordingEnabled", "audioRecordingEnabled"), ("cloudArchiveEnabled", "cloudArchiveEnabled"), + ("maxRetentionDays", "maxRetentionDays"), + ("motionBasedRetentionEnabled", "motionBasedRetentionEnabled"), ("motionDetectorVersion", "motionDetectorVersion"), + ("name", "name"), + ("restrictedBandwidthModeEnabled", "restrictedBandwidthModeEnabled"), ("scheduleId", "scheduleId"), - ("maxRetentionDays", "maxRetentionDays"), ("videoSettings", "videoSettings"), ("networkId", "networkId"), ("qualityRetentionProfileId", "qualityRetentionProfileId"), diff --git a/ansible_collections/cisco/meraki/plugins/action/networks_camera_wireless_profiles.py b/ansible_collections/cisco/meraki/plugins/action/networks_camera_wireless_profiles.py index 4aedf37c2..4525ab771 100644 --- a/ansible_collections/cisco/meraki/plugins/action/networks_camera_wireless_profiles.py +++ b/ansible_collections/cisco/meraki/plugins/action/networks_camera_wireless_profiles.py @@ -32,9 +32,9 @@ argument_spec = meraki_argument_spec() # Add arguments specific for this module argument_spec.update(dict( state=dict(type="str", default="present", choices=["present", "absent"]), + identity=dict(type="dict"), name=dict(type="str"), ssid=dict(type="dict"), - identity=dict(type="dict"), networkId=dict(type="str"), wirelessProfileId=dict(type="str"), )) @@ -52,9 +52,9 @@ class NetworksCameraWirelessProfiles(object): def __init__(self, params, meraki): self.meraki = meraki self.new_object = dict( + identity=params.get("identity"), name=params.get("name"), ssid=params.get("ssid"), - identity=params.get("identity"), networkId=params.get("networkId"), wirelessProfileId=params.get("wirelessProfileId"), ) @@ -78,15 +78,15 @@ class NetworksCameraWirelessProfiles(object): def create_params(self): new_object_params = {} + if self.new_object.get('identity') is not None or self.new_object.get('identity') is not None: + new_object_params['identity'] = self.new_object.get('identity') or \ + self.new_object.get('identity') if self.new_object.get('name') is not None or self.new_object.get('name') is not None: new_object_params['name'] = self.new_object.get('name') or \ self.new_object.get('name') if self.new_object.get('ssid') is not None or self.new_object.get('ssid') is not None: new_object_params['ssid'] = self.new_object.get('ssid') or \ self.new_object.get('ssid') - if self.new_object.get('identity') is not None or self.new_object.get('identity') is not None: - new_object_params['identity'] = self.new_object.get('identity') or \ - self.new_object.get('identity') if self.new_object.get('networkId') is not None or self.new_object.get('network_id') is not None: new_object_params['networkId'] = self.new_object.get('networkId') or \ self.new_object.get('network_id') @@ -104,15 +104,15 @@ class NetworksCameraWirelessProfiles(object): def update_by_id_params(self): new_object_params = {} + if self.new_object.get('identity') is not None or self.new_object.get('identity') is not None: + new_object_params['identity'] = self.new_object.get('identity') or \ + self.new_object.get('identity') if self.new_object.get('name') is not None or self.new_object.get('name') is not None: new_object_params['name'] = self.new_object.get('name') or \ self.new_object.get('name') if self.new_object.get('ssid') is not None or self.new_object.get('ssid') is not None: new_object_params['ssid'] = self.new_object.get('ssid') or \ self.new_object.get('ssid') - if self.new_object.get('identity') is not None or self.new_object.get('identity') is not None: - new_object_params['identity'] = self.new_object.get('identity') or \ - self.new_object.get('identity') if self.new_object.get('networkId') is not None or self.new_object.get('network_id') is not None: new_object_params['networkId'] = self.new_object.get('networkId') or \ self.new_object.get('network_id') @@ -190,9 +190,9 @@ class NetworksCameraWirelessProfiles(object): requested_obj = self.new_object obj_params = [ + ("identity", "identity"), ("name", "name"), ("ssid", "ssid"), - ("identity", "identity"), ("networkId", "networkId"), ("wirelessProfileId", "wirelessProfileId"), ] diff --git a/ansible_collections/cisco/meraki/plugins/action/networks_cellular_gateway_dhcp.py b/ansible_collections/cisco/meraki/plugins/action/networks_cellular_gateway_dhcp.py index a02d4c4d4..823ff2348 100644 --- a/ansible_collections/cisco/meraki/plugins/action/networks_cellular_gateway_dhcp.py +++ b/ansible_collections/cisco/meraki/plugins/action/networks_cellular_gateway_dhcp.py @@ -33,8 +33,8 @@ argument_spec = meraki_argument_spec() argument_spec.update(dict( state=dict(type="str", default="present", choices=["present"]), dhcpLeaseTime=dict(type="str"), - dnsNameservers=dict(type="str"), dnsCustomNameservers=dict(type="list"), + dnsNameservers=dict(type="str"), networkId=dict(type="str"), )) @@ -51,8 +51,8 @@ class NetworksCellularGatewayDhcp(object): self.meraki = meraki self.new_object = dict( dhcpLeaseTime=params.get("dhcpLeaseTime"), - dnsNameservers=params.get("dnsNameservers"), dnsCustomNameservers=params.get("dnsCustomNameservers"), + dnsNameservers=params.get("dnsNameservers"), network_id=params.get("networkId"), ) @@ -68,12 +68,12 @@ class NetworksCellularGatewayDhcp(object): if self.new_object.get('dhcpLeaseTime') is not None or self.new_object.get('dhcp_lease_time') is not None: new_object_params['dhcpLeaseTime'] = self.new_object.get('dhcpLeaseTime') or \ self.new_object.get('dhcp_lease_time') - if self.new_object.get('dnsNameservers') is not None or self.new_object.get('dns_nameservers') is not None: - new_object_params['dnsNameservers'] = self.new_object.get('dnsNameservers') or \ - self.new_object.get('dns_nameservers') if self.new_object.get('dnsCustomNameservers') is not None or self.new_object.get('dns_custom_nameservers') is not None: new_object_params['dnsCustomNameservers'] = self.new_object.get('dnsCustomNameservers') or \ self.new_object.get('dns_custom_nameservers') + if self.new_object.get('dnsNameservers') is not None or self.new_object.get('dns_nameservers') is not None: + new_object_params['dnsNameservers'] = self.new_object.get('dnsNameservers') or \ + self.new_object.get('dns_nameservers') if self.new_object.get('networkId') is not None or self.new_object.get('network_id') is not None: new_object_params['networkId'] = self.new_object.get('networkId') or \ self.new_object.get('network_id') @@ -131,8 +131,8 @@ class NetworksCellularGatewayDhcp(object): obj_params = [ ("dhcpLeaseTime", "dhcpLeaseTime"), - ("dnsNameservers", "dnsNameservers"), ("dnsCustomNameservers", "dnsCustomNameservers"), + ("dnsNameservers", "dnsNameservers"), ("networkId", "networkId"), ] # Method 1. Params present in request (Ansible) obj are the same as the current (ISE) params diff --git a/ansible_collections/cisco/meraki/plugins/action/networks_cellular_gateway_subnet_pool.py b/ansible_collections/cisco/meraki/plugins/action/networks_cellular_gateway_subnet_pool.py index 4af5e75ad..328e935ae 100644 --- a/ansible_collections/cisco/meraki/plugins/action/networks_cellular_gateway_subnet_pool.py +++ b/ansible_collections/cisco/meraki/plugins/action/networks_cellular_gateway_subnet_pool.py @@ -32,8 +32,8 @@ argument_spec = meraki_argument_spec() # Add arguments specific for this module argument_spec.update(dict( state=dict(type="str", default="present", choices=["present"]), - mask=dict(type="int"), cidr=dict(type="str"), + mask=dict(type="int"), networkId=dict(type="str"), )) @@ -49,8 +49,8 @@ class NetworksCellularGatewaySubnetPool(object): def __init__(self, params, meraki): self.meraki = meraki self.new_object = dict( - mask=params.get("mask"), cidr=params.get("cidr"), + mask=params.get("mask"), network_id=params.get("networkId"), ) @@ -63,12 +63,12 @@ class NetworksCellularGatewaySubnetPool(object): def update_all_params(self): new_object_params = {} - if self.new_object.get('mask') is not None or self.new_object.get('mask') is not None: - new_object_params['mask'] = self.new_object.get('mask') or \ - self.new_object.get('mask') if self.new_object.get('cidr') is not None or self.new_object.get('cidr') is not None: new_object_params['cidr'] = self.new_object.get('cidr') or \ self.new_object.get('cidr') + if self.new_object.get('mask') is not None or self.new_object.get('mask') is not None: + new_object_params['mask'] = self.new_object.get('mask') or \ + self.new_object.get('mask') if self.new_object.get('networkId') is not None or self.new_object.get('network_id') is not None: new_object_params['networkId'] = self.new_object.get('networkId') or \ self.new_object.get('network_id') @@ -125,8 +125,8 @@ class NetworksCellularGatewaySubnetPool(object): requested_obj = self.new_object obj_params = [ - ("mask", "mask"), ("cidr", "cidr"), + ("mask", "mask"), ("networkId", "networkId"), ] # Method 1. Params present in request (Ansible) obj are the same as the current (ISE) params diff --git a/ansible_collections/cisco/meraki/plugins/action/networks_clients_info.py b/ansible_collections/cisco/meraki/plugins/action/networks_clients_info.py index 7f6eae8dc..cb865220d 100644 --- a/ansible_collections/cisco/meraki/plugins/action/networks_clients_info.py +++ b/ansible_collections/cisco/meraki/plugins/action/networks_clients_info.py @@ -26,23 +26,7 @@ argument_spec = meraki_argument_spec() # Add arguments specific for this module argument_spec.update(dict( networkId=dict(type="str"), - t0=dict(type="str"), - timespan=dict(type="float"), - perPage=dict(type="int"), - total_pages=dict(type="int"), - direction=dict(type="str"), - startingAfter=dict(type="str"), - endingBefore=dict(type="str"), - statuses=dict(type="list"), - ip=dict(type="str"), - ip6=dict(type="str"), - ip6Local=dict(type="str"), - mac=dict(type="str"), - os=dict(type="str"), - pskGroup=dict(type="str"), - description=dict(type="str"), - vlan=dict(type="str"), - recentDeviceConnections=dict(type="list"), + clientId=dict(type="str"), )) required_if = [] @@ -79,61 +63,14 @@ class ActionModule(ActionBase): if not valid: raise AnsibleActionFail(errors) - def get_all(self, params): + def get_object(self, params): new_object = {} if params.get("networkId") is not None: new_object["networkId"] = params.get( "networkId") - if params.get("t0") is not None: - new_object["t0"] = params.get( - "t0") - if params.get("timespan") is not None: - new_object["timespan"] = params.get( - "timespan") - if params.get("perPage") is not None: - new_object["perPage"] = params.get( - "perPage") - new_object['total_pages'] = params.get( - "total_pages") or 1 - new_object['direction'] = params.get( - "direction") or "next" - if params.get("startingAfter") is not None: - new_object["startingAfter"] = params.get( - "startingAfter") - if params.get("endingBefore") is not None: - new_object["endingBefore"] = params.get( - "endingBefore") - if params.get("statuses") is not None: - new_object["statuses"] = params.get( - "statuses") - if params.get("ip") is not None: - new_object["ip"] = params.get( - "ip") - if params.get("ip6") is not None: - new_object["ip6"] = params.get( - "ip6") - if params.get("ip6Local") is not None: - new_object["ip6Local"] = params.get( - "ip6Local") - if params.get("mac") is not None: - new_object["mac"] = params.get( - "mac") - if params.get("os") is not None: - new_object["os"] = params.get( - "os") - if params.get("pskGroup") is not None: - new_object["pskGroup"] = params.get( - "pskGroup") - if params.get("description") is not None: - new_object["description"] = params.get( - "description") - if params.get("vlan") is not None: - new_object["vlan"] = params.get( - "vlan") - if params.get("recentDeviceConnections") is not None: - new_object["recentDeviceConnections"] = params.get( - "recentDeviceConnections") - + if params.get("clientId") is not None: + new_object["clientId"] = params.get( + "clientId") return new_object def run(self, tmp=None, task_vars=None): @@ -146,11 +83,20 @@ class ActionModule(ActionBase): meraki = MERAKI(params=self._task.args) - response = meraki.exec_meraki( - family="networks", - function='getNetworkClients', - params=self.get_all(self._task.args), - ) - self._result.update(dict(meraki_response=response)) - self._result.update(meraki.exit_json()) - return self._result + id = self._task.args.get("clientId") + if id: + response = meraki.exec_meraki( + family="networks", + function='getNetworkClient', + params=self.get_object(self._task.args), + ) + self._result.update(dict(meraki_response=response)) + self._result.update(meraki.exit_json()) + return self._result + if not id: + # NOTE: Does not have a get all method or it is in another action + response = None + meraki.object_modify_result(changed=False, result="Module does not have get all, check arguments of module") + self._result.update(dict(meraki_response=response)) + self._result.update(meraki.exit_json()) + return self._result diff --git a/ansible_collections/cisco/meraki/plugins/action/networks_firmware_upgrades.py b/ansible_collections/cisco/meraki/plugins/action/networks_firmware_upgrades.py index d60217404..f3cc453f0 100644 --- a/ansible_collections/cisco/meraki/plugins/action/networks_firmware_upgrades.py +++ b/ansible_collections/cisco/meraki/plugins/action/networks_firmware_upgrades.py @@ -32,9 +32,9 @@ argument_spec = meraki_argument_spec() # Add arguments specific for this module argument_spec.update(dict( state=dict(type="str", default="present", choices=["present"]), - upgradeWindow=dict(type="dict"), - timezone=dict(type="str"), products=dict(type="dict"), + timezone=dict(type="str"), + upgradeWindow=dict(type="dict"), networkId=dict(type="str"), )) @@ -50,9 +50,9 @@ class NetworksFirmwareUpgrades(object): def __init__(self, params, meraki): self.meraki = meraki self.new_object = dict( - upgradeWindow=params.get("upgradeWindow"), - timezone=params.get("timezone"), products=params.get("products"), + timezone=params.get("timezone"), + upgradeWindow=params.get("upgradeWindow"), network_id=params.get("networkId"), ) @@ -65,15 +65,15 @@ class NetworksFirmwareUpgrades(object): def update_all_params(self): new_object_params = {} - if self.new_object.get('upgradeWindow') is not None or self.new_object.get('upgrade_window') is not None: - new_object_params['upgradeWindow'] = self.new_object.get('upgradeWindow') or \ - self.new_object.get('upgrade_window') - if self.new_object.get('timezone') is not None or self.new_object.get('timezone') is not None: - new_object_params['timezone'] = self.new_object.get('timezone') or \ - self.new_object.get('timezone') if self.new_object.get('products') is not None or self.new_object.get('products') is not None: new_object_params['products'] = self.new_object.get('products') or \ self.new_object.get('products') + if self.new_object.get('timezone') is not None or self.new_object.get('timezone') is not None: + new_object_params['timezone'] = self.new_object.get('timezone') or \ + self.new_object.get('timezone') + if self.new_object.get('upgradeWindow') is not None or self.new_object.get('upgrade_window') is not None: + new_object_params['upgradeWindow'] = self.new_object.get('upgradeWindow') or \ + self.new_object.get('upgrade_window') if self.new_object.get('networkId') is not None or self.new_object.get('network_id') is not None: new_object_params['networkId'] = self.new_object.get('networkId') or \ self.new_object.get('network_id') @@ -130,9 +130,9 @@ class NetworksFirmwareUpgrades(object): requested_obj = self.new_object obj_params = [ - ("upgradeWindow", "upgradeWindow"), - ("timezone", "timezone"), ("products", "products"), + ("timezone", "timezone"), + ("upgradeWindow", "upgradeWindow"), ("networkId", "networkId"), ] # Method 1. Params present in request (Ansible) obj are the same as the current (ISE) params diff --git a/ansible_collections/cisco/meraki/plugins/action/networks_firmware_upgrades_rollbacks.py b/ansible_collections/cisco/meraki/plugins/action/networks_firmware_upgrades_rollbacks.py index 02dd7a060..ac1f8efea 100644 --- a/ansible_collections/cisco/meraki/plugins/action/networks_firmware_upgrades_rollbacks.py +++ b/ansible_collections/cisco/meraki/plugins/action/networks_firmware_upgrades_rollbacks.py @@ -26,8 +26,8 @@ argument_spec = meraki_argument_spec() # Add arguments specific for this module argument_spec.update(dict( product=dict(type="str"), - time=dict(type="str"), reasons=dict(type="list"), + time=dict(type="str"), toVersion=dict(type="dict"), networkId=dict(type="str"), )) @@ -69,8 +69,8 @@ class ActionModule(ActionBase): def get_object(self, params): new_object = dict( product=params.get("product"), - time=params.get("time"), reasons=params.get("reasons"), + time=params.get("time"), toVersion=params.get("toVersion"), networkId=params.get("networkId"), ) diff --git a/ansible_collections/cisco/meraki/plugins/action/networks_firmware_upgrades_staged_events_defer.py b/ansible_collections/cisco/meraki/plugins/action/networks_firmware_upgrades_staged_events_defer.py index db07326b4..f4676d6e5 100644 --- a/ansible_collections/cisco/meraki/plugins/action/networks_firmware_upgrades_staged_events_defer.py +++ b/ansible_collections/cisco/meraki/plugins/action/networks_firmware_upgrades_staged_events_defer.py @@ -64,7 +64,7 @@ class ActionModule(ActionBase): def get_object(self, params): new_object = dict( - network_id=params.get("networkId"), + networkId=params.get("networkId"), ) return new_object diff --git a/ansible_collections/cisco/meraki/plugins/action/networks_firmware_upgrades_staged_events_rollbacks.py b/ansible_collections/cisco/meraki/plugins/action/networks_firmware_upgrades_staged_events_rollbacks.py index 72ab2abcc..4a7b0d8aa 100644 --- a/ansible_collections/cisco/meraki/plugins/action/networks_firmware_upgrades_staged_events_rollbacks.py +++ b/ansible_collections/cisco/meraki/plugins/action/networks_firmware_upgrades_staged_events_rollbacks.py @@ -25,8 +25,8 @@ from ansible_collections.cisco.meraki.plugins.plugin_utils.meraki import ( argument_spec = meraki_argument_spec() # Add arguments specific for this module argument_spec.update(dict( - stages=dict(type="list"), reasons=dict(type="list"), + stages=dict(type="list"), networkId=dict(type="str"), )) diff --git a/ansible_collections/cisco/meraki/plugins/action/networks_firmware_upgrades_staged_groups.py b/ansible_collections/cisco/meraki/plugins/action/networks_firmware_upgrades_staged_groups.py index ea0902e37..61f7f1b4b 100644 --- a/ansible_collections/cisco/meraki/plugins/action/networks_firmware_upgrades_staged_groups.py +++ b/ansible_collections/cisco/meraki/plugins/action/networks_firmware_upgrades_staged_groups.py @@ -32,10 +32,10 @@ argument_spec = meraki_argument_spec() # Add arguments specific for this module argument_spec.update(dict( state=dict(type="str", default="present", choices=["present", "absent"]), - name=dict(type="str"), + assignedDevices=dict(type="dict"), description=dict(type="str"), isDefault=dict(type="bool"), - assignedDevices=dict(type="dict"), + name=dict(type="str"), networkId=dict(type="str"), groupId=dict(type="str"), )) @@ -53,10 +53,10 @@ class NetworksFirmwareUpgradesStagedGroups(object): def __init__(self, params, meraki): self.meraki = meraki self.new_object = dict( - name=params.get("name"), + assignedDevices=params.get("assignedDevices"), description=params.get("description"), isDefault=params.get("isDefault"), - assignedDevices=params.get("assignedDevices"), + name=params.get("name"), networkId=params.get("networkId"), groupId=params.get("groupId"), ) @@ -80,17 +80,17 @@ class NetworksFirmwareUpgradesStagedGroups(object): def create_params(self): new_object_params = {} - if self.new_object.get('name') is not None or self.new_object.get('name') is not None: - new_object_params['name'] = self.new_object.get('name') or \ - self.new_object.get('name') + if self.new_object.get('assignedDevices') is not None or self.new_object.get('assigned_devices') is not None: + new_object_params['assignedDevices'] = self.new_object.get('assignedDevices') or \ + self.new_object.get('assigned_devices') if self.new_object.get('description') is not None or self.new_object.get('description') is not None: new_object_params['description'] = self.new_object.get('description') or \ self.new_object.get('description') if self.new_object.get('isDefault') is not None or self.new_object.get('is_default') is not None: new_object_params['isDefault'] = self.new_object.get('isDefault') - if self.new_object.get('assignedDevices') is not None or self.new_object.get('assigned_devices') is not None: - new_object_params['assignedDevices'] = self.new_object.get('assignedDevices') or \ - self.new_object.get('assigned_devices') + if self.new_object.get('name') is not None or self.new_object.get('name') is not None: + new_object_params['name'] = self.new_object.get('name') or \ + self.new_object.get('name') if self.new_object.get('networkId') is not None or self.new_object.get('network_id') is not None: new_object_params['networkId'] = self.new_object.get('networkId') or \ self.new_object.get('network_id') @@ -108,17 +108,17 @@ class NetworksFirmwareUpgradesStagedGroups(object): def update_by_id_params(self): new_object_params = {} - if self.new_object.get('name') is not None or self.new_object.get('name') is not None: - new_object_params['name'] = self.new_object.get('name') or \ - self.new_object.get('name') + if self.new_object.get('assignedDevices') is not None or self.new_object.get('assigned_devices') is not None: + new_object_params['assignedDevices'] = self.new_object.get('assignedDevices') or \ + self.new_object.get('assigned_devices') if self.new_object.get('description') is not None or self.new_object.get('description') is not None: new_object_params['description'] = self.new_object.get('description') or \ self.new_object.get('description') if self.new_object.get('isDefault') is not None or self.new_object.get('is_default') is not None: new_object_params['isDefault'] = self.new_object.get('isDefault') - if self.new_object.get('assignedDevices') is not None or self.new_object.get('assigned_devices') is not None: - new_object_params['assignedDevices'] = self.new_object.get('assignedDevices') or \ - self.new_object.get('assigned_devices') + if self.new_object.get('name') is not None or self.new_object.get('name') is not None: + new_object_params['name'] = self.new_object.get('name') or \ + self.new_object.get('name') if self.new_object.get('networkId') is not None or self.new_object.get('network_id') is not None: new_object_params['networkId'] = self.new_object.get('networkId') or \ self.new_object.get('network_id') @@ -196,10 +196,10 @@ class NetworksFirmwareUpgradesStagedGroups(object): requested_obj = self.new_object obj_params = [ - ("name", "name"), + ("assignedDevices", "assignedDevices"), ("description", "description"), ("isDefault", "isDefault"), - ("assignedDevices", "assignedDevices"), + ("name", "name"), ("networkId", "networkId"), ("groupId", "groupId"), ] diff --git a/ansible_collections/cisco/meraki/plugins/action/networks_floor_plans.py b/ansible_collections/cisco/meraki/plugins/action/networks_floor_plans.py index 0e1a40eec..561919d38 100644 --- a/ansible_collections/cisco/meraki/plugins/action/networks_floor_plans.py +++ b/ansible_collections/cisco/meraki/plugins/action/networks_floor_plans.py @@ -32,13 +32,13 @@ argument_spec = meraki_argument_spec() # Add arguments specific for this module argument_spec.update(dict( state=dict(type="str", default="present", choices=["present", "absent"]), - name=dict(type="str"), - center=dict(type="dict"), bottomLeftCorner=dict(type="dict"), bottomRightCorner=dict(type="dict"), + center=dict(type="dict"), + imageContents=dict(type="str"), + name=dict(type="str"), topLeftCorner=dict(type="dict"), topRightCorner=dict(type="dict"), - imageContents=dict(type="str"), networkId=dict(type="str"), floorPlanId=dict(type="str"), )) @@ -56,13 +56,13 @@ class NetworksFloorPlans(object): def __init__(self, params, meraki): self.meraki = meraki self.new_object = dict( - name=params.get("name"), - center=params.get("center"), bottomLeftCorner=params.get("bottomLeftCorner"), bottomRightCorner=params.get("bottomRightCorner"), + center=params.get("center"), + imageContents=params.get("imageContents"), + name=params.get("name"), topLeftCorner=params.get("topLeftCorner"), topRightCorner=params.get("topRightCorner"), - imageContents=params.get("imageContents"), networkId=params.get("networkId"), floorPlanId=params.get("floorPlanId"), ) @@ -86,27 +86,27 @@ class NetworksFloorPlans(object): def create_params(self): new_object_params = {} - if self.new_object.get('name') is not None or self.new_object.get('name') is not None: - new_object_params['name'] = self.new_object.get('name') or \ - self.new_object.get('name') - if self.new_object.get('center') is not None or self.new_object.get('center') is not None: - new_object_params['center'] = self.new_object.get('center') or \ - self.new_object.get('center') if self.new_object.get('bottomLeftCorner') is not None or self.new_object.get('bottom_left_corner') is not None: new_object_params['bottomLeftCorner'] = self.new_object.get('bottomLeftCorner') or \ self.new_object.get('bottom_left_corner') if self.new_object.get('bottomRightCorner') is not None or self.new_object.get('bottom_right_corner') is not None: new_object_params['bottomRightCorner'] = self.new_object.get('bottomRightCorner') or \ self.new_object.get('bottom_right_corner') + if self.new_object.get('center') is not None or self.new_object.get('center') is not None: + new_object_params['center'] = self.new_object.get('center') or \ + self.new_object.get('center') + if self.new_object.get('imageContents') is not None or self.new_object.get('image_contents') is not None: + new_object_params['imageContents'] = self.new_object.get('imageContents') or \ + self.new_object.get('image_contents') + if self.new_object.get('name') is not None or self.new_object.get('name') is not None: + new_object_params['name'] = self.new_object.get('name') or \ + self.new_object.get('name') if self.new_object.get('topLeftCorner') is not None or self.new_object.get('top_left_corner') is not None: new_object_params['topLeftCorner'] = self.new_object.get('topLeftCorner') or \ self.new_object.get('top_left_corner') if self.new_object.get('topRightCorner') is not None or self.new_object.get('top_right_corner') is not None: new_object_params['topRightCorner'] = self.new_object.get('topRightCorner') or \ self.new_object.get('top_right_corner') - if self.new_object.get('imageContents') is not None or self.new_object.get('image_contents') is not None: - new_object_params['imageContents'] = self.new_object.get('imageContents') or \ - self.new_object.get('image_contents') if self.new_object.get('networkId') is not None or self.new_object.get('network_id') is not None: new_object_params['networkId'] = self.new_object.get('networkId') or \ self.new_object.get('network_id') @@ -124,27 +124,27 @@ class NetworksFloorPlans(object): def update_by_id_params(self): new_object_params = {} - if self.new_object.get('name') is not None or self.new_object.get('name') is not None: - new_object_params['name'] = self.new_object.get('name') or \ - self.new_object.get('name') - if self.new_object.get('center') is not None or self.new_object.get('center') is not None: - new_object_params['center'] = self.new_object.get('center') or \ - self.new_object.get('center') if self.new_object.get('bottomLeftCorner') is not None or self.new_object.get('bottom_left_corner') is not None: new_object_params['bottomLeftCorner'] = self.new_object.get('bottomLeftCorner') or \ self.new_object.get('bottom_left_corner') if self.new_object.get('bottomRightCorner') is not None or self.new_object.get('bottom_right_corner') is not None: new_object_params['bottomRightCorner'] = self.new_object.get('bottomRightCorner') or \ self.new_object.get('bottom_right_corner') + if self.new_object.get('center') is not None or self.new_object.get('center') is not None: + new_object_params['center'] = self.new_object.get('center') or \ + self.new_object.get('center') + if self.new_object.get('imageContents') is not None or self.new_object.get('image_contents') is not None: + new_object_params['imageContents'] = self.new_object.get('imageContents') or \ + self.new_object.get('image_contents') + if self.new_object.get('name') is not None or self.new_object.get('name') is not None: + new_object_params['name'] = self.new_object.get('name') or \ + self.new_object.get('name') if self.new_object.get('topLeftCorner') is not None or self.new_object.get('top_left_corner') is not None: new_object_params['topLeftCorner'] = self.new_object.get('topLeftCorner') or \ self.new_object.get('top_left_corner') if self.new_object.get('topRightCorner') is not None or self.new_object.get('top_right_corner') is not None: new_object_params['topRightCorner'] = self.new_object.get('topRightCorner') or \ self.new_object.get('top_right_corner') - if self.new_object.get('imageContents') is not None or self.new_object.get('image_contents') is not None: - new_object_params['imageContents'] = self.new_object.get('imageContents') or \ - self.new_object.get('image_contents') if self.new_object.get('networkId') is not None or self.new_object.get('network_id') is not None: new_object_params['networkId'] = self.new_object.get('networkId') or \ self.new_object.get('network_id') @@ -222,13 +222,13 @@ class NetworksFloorPlans(object): requested_obj = self.new_object obj_params = [ - ("name", "name"), - ("center", "center"), ("bottomLeftCorner", "bottomLeftCorner"), ("bottomRightCorner", "bottomRightCorner"), + ("center", "center"), + ("imageContents", "imageContents"), + ("name", "name"), ("topLeftCorner", "topLeftCorner"), ("topRightCorner", "topRightCorner"), - ("imageContents", "imageContents"), ("networkId", "networkId"), ("floorPlanId", "floorPlanId"), ] diff --git a/ansible_collections/cisco/meraki/plugins/action/networks_group_policies.py b/ansible_collections/cisco/meraki/plugins/action/networks_group_policies.py index c8f41fc81..749350851 100644 --- a/ansible_collections/cisco/meraki/plugins/action/networks_group_policies.py +++ b/ansible_collections/cisco/meraki/plugins/action/networks_group_policies.py @@ -32,14 +32,14 @@ argument_spec = meraki_argument_spec() # Add arguments specific for this module argument_spec.update(dict( state=dict(type="str", default="present", choices=["present", "absent"]), - name=dict(type="str"), - scheduling=dict(type="dict"), bandwidth=dict(type="dict"), - firewallAndTrafficShaping=dict(type="dict"), + bonjourForwarding=dict(type="dict"), contentFiltering=dict(type="dict"), + firewallAndTrafficShaping=dict(type="dict"), + name=dict(type="str"), + scheduling=dict(type="dict"), splashAuthSettings=dict(type="str"), vlanTagging=dict(type="dict"), - bonjourForwarding=dict(type="dict"), networkId=dict(type="str"), groupPolicyId=dict(type="str"), )) @@ -57,14 +57,14 @@ class NetworksGroupPolicies(object): def __init__(self, params, meraki): self.meraki = meraki self.new_object = dict( - name=params.get("name"), - scheduling=params.get("scheduling"), bandwidth=params.get("bandwidth"), - firewallAndTrafficShaping=params.get("firewallAndTrafficShaping"), + bonjourForwarding=params.get("bonjourForwarding"), contentFiltering=params.get("contentFiltering"), + firewallAndTrafficShaping=params.get("firewallAndTrafficShaping"), + name=params.get("name"), + scheduling=params.get("scheduling"), splashAuthSettings=params.get("splashAuthSettings"), vlanTagging=params.get("vlanTagging"), - bonjourForwarding=params.get("bonjourForwarding"), networkId=params.get("networkId"), groupPolicyId=params.get("groupPolicyId"), ) @@ -88,30 +88,30 @@ class NetworksGroupPolicies(object): def create_params(self): new_object_params = {} - if self.new_object.get('name') is not None or self.new_object.get('name') is not None: - new_object_params['name'] = self.new_object.get('name') or \ - self.new_object.get('name') - if self.new_object.get('scheduling') is not None or self.new_object.get('scheduling') is not None: - new_object_params['scheduling'] = self.new_object.get('scheduling') or \ - self.new_object.get('scheduling') if self.new_object.get('bandwidth') is not None or self.new_object.get('bandwidth') is not None: new_object_params['bandwidth'] = self.new_object.get('bandwidth') or \ self.new_object.get('bandwidth') - if self.new_object.get('firewallAndTrafficShaping') is not None or self.new_object.get('firewall_and_traffic_shaping') is not None: - new_object_params['firewallAndTrafficShaping'] = self.new_object.get('firewallAndTrafficShaping') or \ - self.new_object.get('firewall_and_traffic_shaping') + if self.new_object.get('bonjourForwarding') is not None or self.new_object.get('bonjour_forwarding') is not None: + new_object_params['bonjourForwarding'] = self.new_object.get('bonjourForwarding') or \ + self.new_object.get('bonjour_forwarding') if self.new_object.get('contentFiltering') is not None or self.new_object.get('content_filtering') is not None: new_object_params['contentFiltering'] = self.new_object.get('contentFiltering') or \ self.new_object.get('content_filtering') + if self.new_object.get('firewallAndTrafficShaping') is not None or self.new_object.get('firewall_and_traffic_shaping') is not None: + new_object_params['firewallAndTrafficShaping'] = self.new_object.get('firewallAndTrafficShaping') or \ + self.new_object.get('firewall_and_traffic_shaping') + if self.new_object.get('name') is not None or self.new_object.get('name') is not None: + new_object_params['name'] = self.new_object.get('name') or \ + self.new_object.get('name') + if self.new_object.get('scheduling') is not None or self.new_object.get('scheduling') is not None: + new_object_params['scheduling'] = self.new_object.get('scheduling') or \ + self.new_object.get('scheduling') if self.new_object.get('splashAuthSettings') is not None or self.new_object.get('splash_auth_settings') is not None: new_object_params['splashAuthSettings'] = self.new_object.get('splashAuthSettings') or \ self.new_object.get('splash_auth_settings') if self.new_object.get('vlanTagging') is not None or self.new_object.get('vlan_tagging') is not None: new_object_params['vlanTagging'] = self.new_object.get('vlanTagging') or \ self.new_object.get('vlan_tagging') - if self.new_object.get('bonjourForwarding') is not None or self.new_object.get('bonjour_forwarding') is not None: - new_object_params['bonjourForwarding'] = self.new_object.get('bonjourForwarding') or \ - self.new_object.get('bonjour_forwarding') if self.new_object.get('networkId') is not None or self.new_object.get('network_id') is not None: new_object_params['networkId'] = self.new_object.get('networkId') or \ self.new_object.get('network_id') @@ -129,30 +129,30 @@ class NetworksGroupPolicies(object): def update_by_id_params(self): new_object_params = {} - if self.new_object.get('name') is not None or self.new_object.get('name') is not None: - new_object_params['name'] = self.new_object.get('name') or \ - self.new_object.get('name') - if self.new_object.get('scheduling') is not None or self.new_object.get('scheduling') is not None: - new_object_params['scheduling'] = self.new_object.get('scheduling') or \ - self.new_object.get('scheduling') if self.new_object.get('bandwidth') is not None or self.new_object.get('bandwidth') is not None: new_object_params['bandwidth'] = self.new_object.get('bandwidth') or \ self.new_object.get('bandwidth') - if self.new_object.get('firewallAndTrafficShaping') is not None or self.new_object.get('firewall_and_traffic_shaping') is not None: - new_object_params['firewallAndTrafficShaping'] = self.new_object.get('firewallAndTrafficShaping') or \ - self.new_object.get('firewall_and_traffic_shaping') + if self.new_object.get('bonjourForwarding') is not None or self.new_object.get('bonjour_forwarding') is not None: + new_object_params['bonjourForwarding'] = self.new_object.get('bonjourForwarding') or \ + self.new_object.get('bonjour_forwarding') if self.new_object.get('contentFiltering') is not None or self.new_object.get('content_filtering') is not None: new_object_params['contentFiltering'] = self.new_object.get('contentFiltering') or \ self.new_object.get('content_filtering') + if self.new_object.get('firewallAndTrafficShaping') is not None or self.new_object.get('firewall_and_traffic_shaping') is not None: + new_object_params['firewallAndTrafficShaping'] = self.new_object.get('firewallAndTrafficShaping') or \ + self.new_object.get('firewall_and_traffic_shaping') + if self.new_object.get('name') is not None or self.new_object.get('name') is not None: + new_object_params['name'] = self.new_object.get('name') or \ + self.new_object.get('name') + if self.new_object.get('scheduling') is not None or self.new_object.get('scheduling') is not None: + new_object_params['scheduling'] = self.new_object.get('scheduling') or \ + self.new_object.get('scheduling') if self.new_object.get('splashAuthSettings') is not None or self.new_object.get('splash_auth_settings') is not None: new_object_params['splashAuthSettings'] = self.new_object.get('splashAuthSettings') or \ self.new_object.get('splash_auth_settings') if self.new_object.get('vlanTagging') is not None or self.new_object.get('vlan_tagging') is not None: new_object_params['vlanTagging'] = self.new_object.get('vlanTagging') or \ self.new_object.get('vlan_tagging') - if self.new_object.get('bonjourForwarding') is not None or self.new_object.get('bonjour_forwarding') is not None: - new_object_params['bonjourForwarding'] = self.new_object.get('bonjourForwarding') or \ - self.new_object.get('bonjour_forwarding') if self.new_object.get('networkId') is not None or self.new_object.get('network_id') is not None: new_object_params['networkId'] = self.new_object.get('networkId') or \ self.new_object.get('network_id') @@ -230,14 +230,14 @@ class NetworksGroupPolicies(object): requested_obj = self.new_object obj_params = [ - ("name", "name"), - ("scheduling", "scheduling"), ("bandwidth", "bandwidth"), - ("firewallAndTrafficShaping", "firewallAndTrafficShaping"), + ("bonjourForwarding", "bonjourForwarding"), ("contentFiltering", "contentFiltering"), + ("firewallAndTrafficShaping", "firewallAndTrafficShaping"), + ("name", "name"), + ("scheduling", "scheduling"), ("splashAuthSettings", "splashAuthSettings"), ("vlanTagging", "vlanTagging"), - ("bonjourForwarding", "bonjourForwarding"), ("networkId", "networkId"), ("groupPolicyId", "groupPolicyId"), ] diff --git a/ansible_collections/cisco/meraki/plugins/action/networks_meraki_auth_users.py b/ansible_collections/cisco/meraki/plugins/action/networks_meraki_auth_users.py index 56787c4fd..436947b7c 100644 --- a/ansible_collections/cisco/meraki/plugins/action/networks_meraki_auth_users.py +++ b/ansible_collections/cisco/meraki/plugins/action/networks_meraki_auth_users.py @@ -32,15 +32,16 @@ argument_spec = meraki_argument_spec() # Add arguments specific for this module argument_spec.update(dict( state=dict(type="str", default="present", choices=["present", "absent"]), - email=dict(type="str"), - name=dict(type="str"), - password=dict(type="str"), accountType=dict(type="str"), + authorizations=dict(type="list"), + email=dict(type="str"), emailPasswordToUser=dict(type="bool"), isAdmin=dict(type="bool"), - authorizations=dict(type="list"), + name=dict(type="str"), + password=dict(type="str"), networkId=dict(type="str"), merakiAuthUserId=dict(type="str"), + delete=dict(type="bool"), )) required_if = [ @@ -56,15 +57,16 @@ class NetworksMerakiAuthUsers(object): def __init__(self, params, meraki): self.meraki = meraki self.new_object = dict( - email=params.get("email"), - name=params.get("name"), - password=params.get("password"), accountType=params.get("accountType"), + authorizations=params.get("authorizations"), + email=params.get("email"), emailPasswordToUser=params.get("emailPasswordToUser"), isAdmin=params.get("isAdmin"), - authorizations=params.get("authorizations"), + name=params.get("name"), + password=params.get("password"), networkId=params.get("networkId"), merakiAuthUserId=params.get("merakiAuthUserId"), + delete=params.get("delete"), ) def get_all_params(self, name=None, id=None): @@ -86,25 +88,25 @@ class NetworksMerakiAuthUsers(object): def create_params(self): new_object_params = {} + if self.new_object.get('accountType') is not None or self.new_object.get('account_type') is not None: + new_object_params['accountType'] = self.new_object.get('accountType') or \ + self.new_object.get('account_type') + if self.new_object.get('authorizations') is not None or self.new_object.get('authorizations') is not None: + new_object_params['authorizations'] = self.new_object.get('authorizations') or \ + self.new_object.get('authorizations') if self.new_object.get('email') is not None or self.new_object.get('email') is not None: new_object_params['email'] = self.new_object.get('email') or \ self.new_object.get('email') + if self.new_object.get('emailPasswordToUser') is not None or self.new_object.get('email_password_to_user') is not None: + new_object_params['emailPasswordToUser'] = self.new_object.get('emailPasswordToUser') + if self.new_object.get('isAdmin') is not None or self.new_object.get('is_admin') is not None: + new_object_params['isAdmin'] = self.new_object.get('isAdmin') if self.new_object.get('name') is not None or self.new_object.get('name') is not None: new_object_params['name'] = self.new_object.get('name') or \ self.new_object.get('name') if self.new_object.get('password') is not None or self.new_object.get('password') is not None: new_object_params['password'] = self.new_object.get('password') or \ self.new_object.get('password') - if self.new_object.get('accountType') is not None or self.new_object.get('account_type') is not None: - new_object_params['accountType'] = self.new_object.get('accountType') or \ - self.new_object.get('account_type') - if self.new_object.get('emailPasswordToUser') is not None or self.new_object.get('email_password_to_user') is not None: - new_object_params['emailPasswordToUser'] = self.new_object.get('emailPasswordToUser') - if self.new_object.get('isAdmin') is not None or self.new_object.get('is_admin') is not None: - new_object_params['isAdmin'] = self.new_object.get('isAdmin') - if self.new_object.get('authorizations') is not None or self.new_object.get('authorizations') is not None: - new_object_params['authorizations'] = self.new_object.get('authorizations') or \ - self.new_object.get('authorizations') if self.new_object.get('networkId') is not None or self.new_object.get('network_id') is not None: new_object_params['networkId'] = self.new_object.get('networkId') or \ self.new_object.get('network_id') @@ -112,6 +114,8 @@ class NetworksMerakiAuthUsers(object): def delete_by_id_params(self): new_object_params = {} + if self.new_object.get('delete') is not None or self.new_object.get('delete') is not None: + new_object_params['delete'] = self.new_object.get('delete') if self.new_object.get('networkId') is not None or self.new_object.get('network_id') is not None: new_object_params['networkId'] = self.new_object.get('networkId') or \ self.new_object.get('network_id') @@ -122,17 +126,17 @@ class NetworksMerakiAuthUsers(object): def update_by_id_params(self): new_object_params = {} + if self.new_object.get('authorizations') is not None or self.new_object.get('authorizations') is not None: + new_object_params['authorizations'] = self.new_object.get('authorizations') or \ + self.new_object.get('authorizations') + if self.new_object.get('emailPasswordToUser') is not None or self.new_object.get('email_password_to_user') is not None: + new_object_params['emailPasswordToUser'] = self.new_object.get('emailPasswordToUser') if self.new_object.get('name') is not None or self.new_object.get('name') is not None: new_object_params['name'] = self.new_object.get('name') or \ self.new_object.get('name') if self.new_object.get('password') is not None or self.new_object.get('password') is not None: new_object_params['password'] = self.new_object.get('password') or \ self.new_object.get('password') - if self.new_object.get('emailPasswordToUser') is not None or self.new_object.get('email_password_to_user') is not None: - new_object_params['emailPasswordToUser'] = self.new_object.get('emailPasswordToUser') - if self.new_object.get('authorizations') is not None or self.new_object.get('authorizations') is not None: - new_object_params['authorizations'] = self.new_object.get('authorizations') or \ - self.new_object.get('authorizations') if self.new_object.get('networkId') is not None or self.new_object.get('network_id') is not None: new_object_params['networkId'] = self.new_object.get('networkId') or \ self.new_object.get('network_id') @@ -210,14 +214,15 @@ class NetworksMerakiAuthUsers(object): requested_obj = self.new_object obj_params = [ - ("email", "email"), - ("name", "name"), ("accountType", "accountType"), + ("authorizations", "authorizations"), + ("email", "email"), ("emailPasswordToUser", "emailPasswordToUser"), ("isAdmin", "isAdmin"), - ("authorizations", "authorizations"), + ("name", "name"), ("networkId", "networkId"), ("merakiAuthUserId", "merakiAuthUserId"), + ("delete", "delete"), ] # Method 1. Params present in request (Ansible) obj are the same as the current (DNAC) params # If any does not have eq params, it requires update diff --git a/ansible_collections/cisco/meraki/plugins/action/networks_mqtt_brokers.py b/ansible_collections/cisco/meraki/plugins/action/networks_mqtt_brokers.py index 4313ec519..89e45246e 100644 --- a/ansible_collections/cisco/meraki/plugins/action/networks_mqtt_brokers.py +++ b/ansible_collections/cisco/meraki/plugins/action/networks_mqtt_brokers.py @@ -25,11 +25,11 @@ from ansible_collections.cisco.meraki.plugins.plugin_utils.meraki import ( argument_spec = meraki_argument_spec() # Add arguments specific for this module argument_spec.update(dict( - name=dict(type="str"), + authentication=dict(type="dict"), host=dict(type="str"), + name=dict(type="str"), port=dict(type="int"), security=dict(type="dict"), - authentication=dict(type="dict"), networkId=dict(type="str"), )) @@ -69,11 +69,11 @@ class ActionModule(ActionBase): def get_object(self, params): new_object = dict( - name=params.get("name"), + authentication=params.get("authentication"), host=params.get("host"), + name=params.get("name"), port=params.get("port"), security=params.get("security"), - authentication=params.get("authentication"), networkId=params.get("networkId"), ) return new_object diff --git a/ansible_collections/cisco/meraki/plugins/action/networks_netflow.py b/ansible_collections/cisco/meraki/plugins/action/networks_netflow.py index 0360b2792..730f5518b 100644 --- a/ansible_collections/cisco/meraki/plugins/action/networks_netflow.py +++ b/ansible_collections/cisco/meraki/plugins/action/networks_netflow.py @@ -32,11 +32,11 @@ argument_spec = meraki_argument_spec() # Add arguments specific for this module argument_spec.update(dict( state=dict(type="str", default="present", choices=["present"]), - reportingEnabled=dict(type="bool"), collectorIp=dict(type="str"), collectorPort=dict(type="int"), - etaEnabled=dict(type="bool"), etaDstPort=dict(type="int"), + etaEnabled=dict(type="bool"), + reportingEnabled=dict(type="bool"), networkId=dict(type="str"), )) @@ -52,11 +52,11 @@ class NetworksNetflow(object): def __init__(self, params, meraki): self.meraki = meraki self.new_object = dict( - reportingEnabled=params.get("reportingEnabled"), collectorIp=params.get("collectorIp"), collectorPort=params.get("collectorPort"), - etaEnabled=params.get("etaEnabled"), etaDstPort=params.get("etaDstPort"), + etaEnabled=params.get("etaEnabled"), + reportingEnabled=params.get("reportingEnabled"), network_id=params.get("networkId"), ) @@ -69,19 +69,19 @@ class NetworksNetflow(object): def update_all_params(self): new_object_params = {} - if self.new_object.get('reportingEnabled') is not None or self.new_object.get('reporting_enabled') is not None: - new_object_params['reportingEnabled'] = self.new_object.get('reportingEnabled') if self.new_object.get('collectorIp') is not None or self.new_object.get('collector_ip') is not None: new_object_params['collectorIp'] = self.new_object.get('collectorIp') or \ self.new_object.get('collector_ip') if self.new_object.get('collectorPort') is not None or self.new_object.get('collector_port') is not None: new_object_params['collectorPort'] = self.new_object.get('collectorPort') or \ self.new_object.get('collector_port') - if self.new_object.get('etaEnabled') is not None or self.new_object.get('eta_enabled') is not None: - new_object_params['etaEnabled'] = self.new_object.get('etaEnabled') if self.new_object.get('etaDstPort') is not None or self.new_object.get('eta_dst_port') is not None: new_object_params['etaDstPort'] = self.new_object.get('etaDstPort') or \ self.new_object.get('eta_dst_port') + if self.new_object.get('etaEnabled') is not None or self.new_object.get('eta_enabled') is not None: + new_object_params['etaEnabled'] = self.new_object.get('etaEnabled') + if self.new_object.get('reportingEnabled') is not None or self.new_object.get('reporting_enabled') is not None: + new_object_params['reportingEnabled'] = self.new_object.get('reportingEnabled') if self.new_object.get('networkId') is not None or self.new_object.get('network_id') is not None: new_object_params['networkId'] = self.new_object.get('networkId') or \ self.new_object.get('network_id') @@ -138,11 +138,11 @@ class NetworksNetflow(object): requested_obj = self.new_object obj_params = [ - ("reportingEnabled", "reportingEnabled"), ("collectorIp", "collectorIp"), ("collectorPort", "collectorPort"), - ("etaEnabled", "etaEnabled"), ("etaDstPort", "etaDstPort"), + ("etaEnabled", "etaEnabled"), + ("reportingEnabled", "reportingEnabled"), ("networkId", "networkId"), ] # Method 1. Params present in request (Ansible) obj are the same as the current (ISE) params diff --git a/ansible_collections/cisco/meraki/plugins/action/networks_sensor_alerts_profiles.py b/ansible_collections/cisco/meraki/plugins/action/networks_sensor_alerts_profiles.py index 13be65175..bb150c8fd 100644 --- a/ansible_collections/cisco/meraki/plugins/action/networks_sensor_alerts_profiles.py +++ b/ansible_collections/cisco/meraki/plugins/action/networks_sensor_alerts_profiles.py @@ -32,10 +32,10 @@ argument_spec = meraki_argument_spec() # Add arguments specific for this module argument_spec.update(dict( state=dict(type="str", default="present", choices=["present", "absent"]), - name=dict(type="str"), - schedule=dict(type="dict"), conditions=dict(type="list"), + name=dict(type="str"), recipients=dict(type="dict"), + schedule=dict(type="dict"), serials=dict(type="list"), networkId=dict(type="str"), id=dict(type="str"), @@ -54,10 +54,10 @@ class NetworksSensorAlertsProfiles(object): def __init__(self, params, meraki): self.meraki = meraki self.new_object = dict( - name=params.get("name"), - schedule=params.get("schedule"), conditions=params.get("conditions"), + name=params.get("name"), recipients=params.get("recipients"), + schedule=params.get("schedule"), serials=params.get("serials"), networkId=params.get("networkId"), id=params.get("id"), @@ -81,18 +81,18 @@ class NetworksSensorAlertsProfiles(object): def create_params(self): new_object_params = {} - if self.new_object.get('name') is not None or self.new_object.get('name') is not None: - new_object_params['name'] = self.new_object.get('name') or \ - self.new_object.get('name') - if self.new_object.get('schedule') is not None or self.new_object.get('schedule') is not None: - new_object_params['schedule'] = self.new_object.get('schedule') or \ - self.new_object.get('schedule') if self.new_object.get('conditions') is not None or self.new_object.get('conditions') is not None: new_object_params['conditions'] = self.new_object.get('conditions') or \ self.new_object.get('conditions') + if self.new_object.get('name') is not None or self.new_object.get('name') is not None: + new_object_params['name'] = self.new_object.get('name') or \ + self.new_object.get('name') if self.new_object.get('recipients') is not None or self.new_object.get('recipients') is not None: new_object_params['recipients'] = self.new_object.get('recipients') or \ self.new_object.get('recipients') + if self.new_object.get('schedule') is not None or self.new_object.get('schedule') is not None: + new_object_params['schedule'] = self.new_object.get('schedule') or \ + self.new_object.get('schedule') if self.new_object.get('serials') is not None or self.new_object.get('serials') is not None: new_object_params['serials'] = self.new_object.get('serials') or \ self.new_object.get('serials') @@ -113,18 +113,18 @@ class NetworksSensorAlertsProfiles(object): def update_by_id_params(self): new_object_params = {} - if self.new_object.get('name') is not None or self.new_object.get('name') is not None: - new_object_params['name'] = self.new_object.get('name') or \ - self.new_object.get('name') - if self.new_object.get('schedule') is not None or self.new_object.get('schedule') is not None: - new_object_params['schedule'] = self.new_object.get('schedule') or \ - self.new_object.get('schedule') if self.new_object.get('conditions') is not None or self.new_object.get('conditions') is not None: new_object_params['conditions'] = self.new_object.get('conditions') or \ self.new_object.get('conditions') + if self.new_object.get('name') is not None or self.new_object.get('name') is not None: + new_object_params['name'] = self.new_object.get('name') or \ + self.new_object.get('name') if self.new_object.get('recipients') is not None or self.new_object.get('recipients') is not None: new_object_params['recipients'] = self.new_object.get('recipients') or \ self.new_object.get('recipients') + if self.new_object.get('schedule') is not None or self.new_object.get('schedule') is not None: + new_object_params['schedule'] = self.new_object.get('schedule') or \ + self.new_object.get('schedule') if self.new_object.get('serials') is not None or self.new_object.get('serials') is not None: new_object_params['serials'] = self.new_object.get('serials') or \ self.new_object.get('serials') @@ -201,10 +201,10 @@ class NetworksSensorAlertsProfiles(object): requested_obj = self.new_object obj_params = [ - ("name", "name"), - ("schedule", "schedule"), ("conditions", "conditions"), + ("name", "name"), ("recipients", "recipients"), + ("schedule", "schedule"), ("serials", "serials"), ("networkId", "networkId"), ("id", "id"), diff --git a/ansible_collections/cisco/meraki/plugins/action/networks_settings.py b/ansible_collections/cisco/meraki/plugins/action/networks_settings.py index 3827be9c0..26277be99 100644 --- a/ansible_collections/cisco/meraki/plugins/action/networks_settings.py +++ b/ansible_collections/cisco/meraki/plugins/action/networks_settings.py @@ -32,9 +32,10 @@ argument_spec = meraki_argument_spec() # Add arguments specific for this module argument_spec.update(dict( state=dict(type="str", default="present", choices=["present"]), + localStatusPage=dict(type="dict"), localStatusPageEnabled=dict(type="bool"), + namedVlans=dict(type="dict"), remoteStatusPageEnabled=dict(type="bool"), - localStatusPage=dict(type="dict"), securePort=dict(type="dict"), networkId=dict(type="str"), )) @@ -51,9 +52,10 @@ class NetworksSettings(object): def __init__(self, params, meraki): self.meraki = meraki self.new_object = dict( + localStatusPage=params.get("localStatusPage"), localStatusPageEnabled=params.get("localStatusPageEnabled"), + namedVlans=params.get("namedVlans"), remoteStatusPageEnabled=params.get("remoteStatusPageEnabled"), - localStatusPage=params.get("localStatusPage"), securePort=params.get("securePort"), network_id=params.get("networkId"), ) @@ -67,13 +69,16 @@ class NetworksSettings(object): def update_all_params(self): new_object_params = {} + if self.new_object.get('localStatusPage') is not None or self.new_object.get('local_status_page') is not None: + new_object_params['localStatusPage'] = self.new_object.get('localStatusPage') or \ + self.new_object.get('local_status_page') if self.new_object.get('localStatusPageEnabled') is not None or self.new_object.get('local_status_page_enabled') is not None: new_object_params['localStatusPageEnabled'] = self.new_object.get('localStatusPageEnabled') + if self.new_object.get('namedVlans') is not None or self.new_object.get('named_vlans') is not None: + new_object_params['namedVlans'] = self.new_object.get('namedVlans') or \ + self.new_object.get('named_vlans') if self.new_object.get('remoteStatusPageEnabled') is not None or self.new_object.get('remote_status_page_enabled') is not None: new_object_params['remoteStatusPageEnabled'] = self.new_object.get('remoteStatusPageEnabled') - if self.new_object.get('localStatusPage') is not None or self.new_object.get('local_status_page') is not None: - new_object_params['localStatusPage'] = self.new_object.get('localStatusPage') or \ - self.new_object.get('local_status_page') if self.new_object.get('securePort') is not None or self.new_object.get('secure_port') is not None: new_object_params['securePort'] = self.new_object.get('securePort') or \ self.new_object.get('secure_port') @@ -133,9 +138,10 @@ class NetworksSettings(object): requested_obj = self.new_object obj_params = [ + ("localStatusPage", "localStatusPage"), ("localStatusPageEnabled", "localStatusPageEnabled"), + ("namedVlans", "namedVlans"), ("remoteStatusPageEnabled", "remoteStatusPageEnabled"), - ("localStatusPage", "localStatusPage"), ("securePort", "securePort"), ("networkId", "networkId"), ] diff --git a/ansible_collections/cisco/meraki/plugins/action/networks_sm_devices_checkin.py b/ansible_collections/cisco/meraki/plugins/action/networks_sm_devices_checkin.py index 8695838b5..ba46b4121 100644 --- a/ansible_collections/cisco/meraki/plugins/action/networks_sm_devices_checkin.py +++ b/ansible_collections/cisco/meraki/plugins/action/networks_sm_devices_checkin.py @@ -25,10 +25,10 @@ from ansible_collections.cisco.meraki.plugins.plugin_utils.meraki import ( argument_spec = meraki_argument_spec() # Add arguments specific for this module argument_spec.update(dict( - wifiMacs=dict(type="list"), ids=dict(type="list"), - serials=dict(type="list"), scope=dict(type="list"), + serials=dict(type="list"), + wifiMacs=dict(type="list"), networkId=dict(type="str"), )) @@ -68,10 +68,10 @@ class ActionModule(ActionBase): def get_object(self, params): new_object = dict( - wifiMacs=params.get("wifiMacs"), ids=params.get("ids"), - serials=params.get("serials"), scope=params.get("scope"), + serials=params.get("serials"), + wifiMacs=params.get("wifiMacs"), networkId=params.get("networkId"), ) return new_object diff --git a/ansible_collections/cisco/meraki/plugins/action/networks_sm_devices_fields.py b/ansible_collections/cisco/meraki/plugins/action/networks_sm_devices_fields.py index 6d9bda4c7..7d7ada596 100644 --- a/ansible_collections/cisco/meraki/plugins/action/networks_sm_devices_fields.py +++ b/ansible_collections/cisco/meraki/plugins/action/networks_sm_devices_fields.py @@ -25,10 +25,10 @@ from ansible_collections.cisco.meraki.plugins.plugin_utils.meraki import ( argument_spec = meraki_argument_spec() # Add arguments specific for this module argument_spec.update(dict( - wifiMac=dict(type="str"), + deviceFields=dict(type="dict"), id=dict(type="str"), serial=dict(type="str"), - deviceFields=dict(type="dict"), + wifiMac=dict(type="str"), networkId=dict(type="str"), )) @@ -68,10 +68,10 @@ class ActionModule(ActionBase): def get_object(self, params): new_object = dict( - wifiMac=params.get("wifiMac"), + deviceFields=params.get("deviceFields"), id=params.get("id"), serial=params.get("serial"), - deviceFields=params.get("deviceFields"), + wifiMac=params.get("wifiMac"), networkId=params.get("networkId"), ) return new_object diff --git a/ansible_collections/cisco/meraki/plugins/action/networks_sm_devices_info.py b/ansible_collections/cisco/meraki/plugins/action/networks_sm_devices_info.py index c37f3cc07..e186502cd 100644 --- a/ansible_collections/cisco/meraki/plugins/action/networks_sm_devices_info.py +++ b/ansible_collections/cisco/meraki/plugins/action/networks_sm_devices_info.py @@ -30,6 +30,8 @@ argument_spec.update(dict( wifiMacs=dict(type="list"), serials=dict(type="list"), ids=dict(type="list"), + uuids=dict(type="list"), + systemTypes=dict(type="list"), scope=dict(type="list"), perPage=dict(type="int"), total_pages=dict(type="int"), @@ -89,6 +91,12 @@ class ActionModule(ActionBase): if params.get("ids") is not None: new_object["ids"] = params.get( "ids") + if params.get("uuids") is not None: + new_object["uuids"] = params.get( + "uuids") + if params.get("systemTypes") is not None: + new_object["systemTypes"] = params.get( + "systemTypes") if params.get("scope") is not None: new_object["scope"] = params.get( "scope") diff --git a/ansible_collections/cisco/meraki/plugins/action/networks_sm_devices_install_apps.py b/ansible_collections/cisco/meraki/plugins/action/networks_sm_devices_install_apps.py new file mode 100644 index 000000000..5dfbe018f --- /dev/null +++ b/ansible_collections/cisco/meraki/plugins/action/networks_sm_devices_install_apps.py @@ -0,0 +1,93 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +# Copyright (c) 2021, Cisco Systems +# 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 +from ansible.plugins.action import ActionBase +try: + from ansible_collections.ansible.utils.plugins.module_utils.common.argspec_validate import ( + AnsibleArgSpecValidator, + ) +except ImportError: + ANSIBLE_UTILS_IS_INSTALLED = False +else: + ANSIBLE_UTILS_IS_INSTALLED = True +from ansible.errors import AnsibleActionFail +from ansible_collections.cisco.meraki.plugins.plugin_utils.meraki import ( + MERAKI, + meraki_argument_spec, +) + +# Get common arguements specification +argument_spec = meraki_argument_spec() +# Add arguments specific for this module +argument_spec.update(dict( + appIds=dict(type="list"), + force=dict(type="bool"), + networkId=dict(type="str"), + deviceId=dict(type="str"), +)) + +required_if = [] +required_one_of = [] +mutually_exclusive = [] +required_together = [] + + +class ActionModule(ActionBase): + def __init__(self, *args, **kwargs): + if not ANSIBLE_UTILS_IS_INSTALLED: + raise AnsibleActionFail( + "ansible.utils is not installed. Execute 'ansible-galaxy collection install ansible.utils'") + super(ActionModule, self).__init__(*args, **kwargs) + self._supports_async = False + self._supports_check_mode = False + self._result = None + + # Checks the supplied parameters against the argument spec for this module + def _check_argspec(self): + aav = AnsibleArgSpecValidator( + data=self._task.args, + schema=dict(argument_spec=argument_spec), + schema_format="argspec", + schema_conditionals=dict( + required_if=required_if, + required_one_of=required_one_of, + mutually_exclusive=mutually_exclusive, + required_together=required_together, + ), + name=self._task.action, + ) + valid, errors, self._task.args = aav.validate() + if not valid: + raise AnsibleActionFail(errors) + + def get_object(self, params): + new_object = dict( + appIds=params.get("appIds"), + force=params.get("force"), + networkId=params.get("networkId"), + deviceId=params.get("deviceId"), + ) + return new_object + + def run(self, tmp=None, task_vars=None): + self._task.diff = False + self._result = super(ActionModule, self).run(tmp, task_vars) + self._result["changed"] = False + self._check_argspec() + + meraki = MERAKI(params=self._task.args) + + response = meraki.exec_meraki( + family="sm", + function='installNetworkSmDeviceApps', + op_modifies=True, + params=self.get_object(self._task.args), + ) + self._result.update(dict(meraki_response=response)) + self._result.update(meraki.exit_json()) + return self._result diff --git a/ansible_collections/cisco/meraki/plugins/action/networks_sm_devices_lock.py b/ansible_collections/cisco/meraki/plugins/action/networks_sm_devices_lock.py index c846a4dde..8f851fe0a 100644 --- a/ansible_collections/cisco/meraki/plugins/action/networks_sm_devices_lock.py +++ b/ansible_collections/cisco/meraki/plugins/action/networks_sm_devices_lock.py @@ -25,11 +25,11 @@ from ansible_collections.cisco.meraki.plugins.plugin_utils.meraki import ( argument_spec = meraki_argument_spec() # Add arguments specific for this module argument_spec.update(dict( - wifiMacs=dict(type="list"), ids=dict(type="list"), - serials=dict(type="list"), - scope=dict(type="list"), pin=dict(type="int"), + scope=dict(type="list"), + serials=dict(type="list"), + wifiMacs=dict(type="list"), networkId=dict(type="str"), )) @@ -69,11 +69,11 @@ class ActionModule(ActionBase): def get_object(self, params): new_object = dict( - wifiMacs=params.get("wifiMacs"), ids=params.get("ids"), - serials=params.get("serials"), - scope=params.get("scope"), pin=params.get("pin"), + scope=params.get("scope"), + serials=params.get("serials"), + wifiMacs=params.get("wifiMacs"), networkId=params.get("networkId"), ) return new_object diff --git a/ansible_collections/cisco/meraki/plugins/action/networks_sm_devices_modify_tags.py b/ansible_collections/cisco/meraki/plugins/action/networks_sm_devices_modify_tags.py index ea771b977..27f47614e 100644 --- a/ansible_collections/cisco/meraki/plugins/action/networks_sm_devices_modify_tags.py +++ b/ansible_collections/cisco/meraki/plugins/action/networks_sm_devices_modify_tags.py @@ -25,12 +25,12 @@ from ansible_collections.cisco.meraki.plugins.plugin_utils.meraki import ( argument_spec = meraki_argument_spec() # Add arguments specific for this module argument_spec.update(dict( - wifiMacs=dict(type="list"), ids=dict(type="list"), - serials=dict(type="list"), scope=dict(type="list"), + serials=dict(type="list"), tags=dict(type="list"), updateAction=dict(type="str"), + wifiMacs=dict(type="list"), networkId=dict(type="str"), )) @@ -70,12 +70,12 @@ class ActionModule(ActionBase): def get_object(self, params): new_object = dict( - wifiMacs=params.get("wifiMacs"), ids=params.get("ids"), - serials=params.get("serials"), scope=params.get("scope"), + serials=params.get("serials"), tags=params.get("tags"), updateAction=params.get("updateAction"), + wifiMacs=params.get("wifiMacs"), networkId=params.get("networkId"), ) return new_object diff --git a/ansible_collections/cisco/meraki/plugins/action/networks_sm_devices_move.py b/ansible_collections/cisco/meraki/plugins/action/networks_sm_devices_move.py index 5ed4b5d65..384f3abf0 100644 --- a/ansible_collections/cisco/meraki/plugins/action/networks_sm_devices_move.py +++ b/ansible_collections/cisco/meraki/plugins/action/networks_sm_devices_move.py @@ -25,11 +25,11 @@ from ansible_collections.cisco.meraki.plugins.plugin_utils.meraki import ( argument_spec = meraki_argument_spec() # Add arguments specific for this module argument_spec.update(dict( - wifiMacs=dict(type="list"), ids=dict(type="list"), - serials=dict(type="list"), - scope=dict(type="list"), newNetwork=dict(type="str"), + scope=dict(type="list"), + serials=dict(type="list"), + wifiMacs=dict(type="list"), networkId=dict(type="str"), )) @@ -69,11 +69,11 @@ class ActionModule(ActionBase): def get_object(self, params): new_object = dict( - wifiMacs=params.get("wifiMacs"), ids=params.get("ids"), - serials=params.get("serials"), - scope=params.get("scope"), newNetwork=params.get("newNetwork"), + scope=params.get("scope"), + serials=params.get("serials"), + wifiMacs=params.get("wifiMacs"), networkId=params.get("networkId"), ) return new_object diff --git a/ansible_collections/cisco/meraki/plugins/action/networks_sm_devices_reboot.py b/ansible_collections/cisco/meraki/plugins/action/networks_sm_devices_reboot.py new file mode 100644 index 000000000..16e825308 --- /dev/null +++ b/ansible_collections/cisco/meraki/plugins/action/networks_sm_devices_reboot.py @@ -0,0 +1,103 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +# Copyright (c) 2021, Cisco Systems +# 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 +from ansible.plugins.action import ActionBase +try: + from ansible_collections.ansible.utils.plugins.module_utils.common.argspec_validate import ( + AnsibleArgSpecValidator, + ) +except ImportError: + ANSIBLE_UTILS_IS_INSTALLED = False +else: + ANSIBLE_UTILS_IS_INSTALLED = True +from ansible.errors import AnsibleActionFail +from ansible_collections.cisco.meraki.plugins.plugin_utils.meraki import ( + MERAKI, + meraki_argument_spec, +) + +# Get common arguements specification +argument_spec = meraki_argument_spec() +# Add arguments specific for this module +argument_spec.update(dict( + ids=dict(type="list"), + kextPaths=dict(type="list"), + notifyUser=dict(type="bool"), + rebuildKernelCache=dict(type="bool"), + requestRequiresNetworkTether=dict(type="bool"), + scope=dict(type="list"), + serials=dict(type="list"), + wifiMacs=dict(type="list"), + networkId=dict(type="str"), +)) + +required_if = [] +required_one_of = [] +mutually_exclusive = [] +required_together = [] + + +class ActionModule(ActionBase): + def __init__(self, *args, **kwargs): + if not ANSIBLE_UTILS_IS_INSTALLED: + raise AnsibleActionFail( + "ansible.utils is not installed. Execute 'ansible-galaxy collection install ansible.utils'") + super(ActionModule, self).__init__(*args, **kwargs) + self._supports_async = False + self._supports_check_mode = False + self._result = None + + # Checks the supplied parameters against the argument spec for this module + def _check_argspec(self): + aav = AnsibleArgSpecValidator( + data=self._task.args, + schema=dict(argument_spec=argument_spec), + schema_format="argspec", + schema_conditionals=dict( + required_if=required_if, + required_one_of=required_one_of, + mutually_exclusive=mutually_exclusive, + required_together=required_together, + ), + name=self._task.action, + ) + valid, errors, self._task.args = aav.validate() + if not valid: + raise AnsibleActionFail(errors) + + def get_object(self, params): + new_object = dict( + ids=params.get("ids"), + kextPaths=params.get("kextPaths"), + notifyUser=params.get("notifyUser"), + rebuildKernelCache=params.get("rebuildKernelCache"), + requestRequiresNetworkTether=params.get("requestRequiresNetworkTether"), + scope=params.get("scope"), + serials=params.get("serials"), + wifiMacs=params.get("wifiMacs"), + networkId=params.get("networkId"), + ) + return new_object + + def run(self, tmp=None, task_vars=None): + self._task.diff = False + self._result = super(ActionModule, self).run(tmp, task_vars) + self._result["changed"] = False + self._check_argspec() + + meraki = MERAKI(params=self._task.args) + + response = meraki.exec_meraki( + family="sm", + function='rebootNetworkSmDevices', + op_modifies=True, + params=self.get_object(self._task.args), + ) + self._result.update(dict(meraki_response=response)) + self._result.update(meraki.exit_json()) + return self._result diff --git a/ansible_collections/cisco/meraki/plugins/action/networks_sm_devices_shutdown.py b/ansible_collections/cisco/meraki/plugins/action/networks_sm_devices_shutdown.py new file mode 100644 index 000000000..fb184208c --- /dev/null +++ b/ansible_collections/cisco/meraki/plugins/action/networks_sm_devices_shutdown.py @@ -0,0 +1,95 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +# Copyright (c) 2021, Cisco Systems +# 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 +from ansible.plugins.action import ActionBase +try: + from ansible_collections.ansible.utils.plugins.module_utils.common.argspec_validate import ( + AnsibleArgSpecValidator, + ) +except ImportError: + ANSIBLE_UTILS_IS_INSTALLED = False +else: + ANSIBLE_UTILS_IS_INSTALLED = True +from ansible.errors import AnsibleActionFail +from ansible_collections.cisco.meraki.plugins.plugin_utils.meraki import ( + MERAKI, + meraki_argument_spec, +) + +# Get common arguements specification +argument_spec = meraki_argument_spec() +# Add arguments specific for this module +argument_spec.update(dict( + ids=dict(type="list"), + scope=dict(type="list"), + serials=dict(type="list"), + wifiMacs=dict(type="list"), + networkId=dict(type="str"), +)) + +required_if = [] +required_one_of = [] +mutually_exclusive = [] +required_together = [] + + +class ActionModule(ActionBase): + def __init__(self, *args, **kwargs): + if not ANSIBLE_UTILS_IS_INSTALLED: + raise AnsibleActionFail( + "ansible.utils is not installed. Execute 'ansible-galaxy collection install ansible.utils'") + super(ActionModule, self).__init__(*args, **kwargs) + self._supports_async = False + self._supports_check_mode = False + self._result = None + + # Checks the supplied parameters against the argument spec for this module + def _check_argspec(self): + aav = AnsibleArgSpecValidator( + data=self._task.args, + schema=dict(argument_spec=argument_spec), + schema_format="argspec", + schema_conditionals=dict( + required_if=required_if, + required_one_of=required_one_of, + mutually_exclusive=mutually_exclusive, + required_together=required_together, + ), + name=self._task.action, + ) + valid, errors, self._task.args = aav.validate() + if not valid: + raise AnsibleActionFail(errors) + + def get_object(self, params): + new_object = dict( + ids=params.get("ids"), + scope=params.get("scope"), + serials=params.get("serials"), + wifiMacs=params.get("wifiMacs"), + networkId=params.get("networkId"), + ) + return new_object + + def run(self, tmp=None, task_vars=None): + self._task.diff = False + self._result = super(ActionModule, self).run(tmp, task_vars) + self._result["changed"] = False + self._check_argspec() + + meraki = MERAKI(params=self._task.args) + + response = meraki.exec_meraki( + family="sm", + function='shutdownNetworkSmDevices', + op_modifies=True, + params=self.get_object(self._task.args), + ) + self._result.update(dict(meraki_response=response)) + self._result.update(meraki.exit_json()) + return self._result diff --git a/ansible_collections/cisco/meraki/plugins/action/networks_sm_devices_uninstall_apps.py b/ansible_collections/cisco/meraki/plugins/action/networks_sm_devices_uninstall_apps.py new file mode 100644 index 000000000..056734402 --- /dev/null +++ b/ansible_collections/cisco/meraki/plugins/action/networks_sm_devices_uninstall_apps.py @@ -0,0 +1,91 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +# Copyright (c) 2021, Cisco Systems +# 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 +from ansible.plugins.action import ActionBase +try: + from ansible_collections.ansible.utils.plugins.module_utils.common.argspec_validate import ( + AnsibleArgSpecValidator, + ) +except ImportError: + ANSIBLE_UTILS_IS_INSTALLED = False +else: + ANSIBLE_UTILS_IS_INSTALLED = True +from ansible.errors import AnsibleActionFail +from ansible_collections.cisco.meraki.plugins.plugin_utils.meraki import ( + MERAKI, + meraki_argument_spec, +) + +# Get common arguements specification +argument_spec = meraki_argument_spec() +# Add arguments specific for this module +argument_spec.update(dict( + appIds=dict(type="list"), + networkId=dict(type="str"), + deviceId=dict(type="str"), +)) + +required_if = [] +required_one_of = [] +mutually_exclusive = [] +required_together = [] + + +class ActionModule(ActionBase): + def __init__(self, *args, **kwargs): + if not ANSIBLE_UTILS_IS_INSTALLED: + raise AnsibleActionFail( + "ansible.utils is not installed. Execute 'ansible-galaxy collection install ansible.utils'") + super(ActionModule, self).__init__(*args, **kwargs) + self._supports_async = False + self._supports_check_mode = False + self._result = None + + # Checks the supplied parameters against the argument spec for this module + def _check_argspec(self): + aav = AnsibleArgSpecValidator( + data=self._task.args, + schema=dict(argument_spec=argument_spec), + schema_format="argspec", + schema_conditionals=dict( + required_if=required_if, + required_one_of=required_one_of, + mutually_exclusive=mutually_exclusive, + required_together=required_together, + ), + name=self._task.action, + ) + valid, errors, self._task.args = aav.validate() + if not valid: + raise AnsibleActionFail(errors) + + def get_object(self, params): + new_object = dict( + appIds=params.get("appIds"), + networkId=params.get("networkId"), + deviceId=params.get("deviceId"), + ) + return new_object + + def run(self, tmp=None, task_vars=None): + self._task.diff = False + self._result = super(ActionModule, self).run(tmp, task_vars) + self._result["changed"] = False + self._check_argspec() + + meraki = MERAKI(params=self._task.args) + + response = meraki.exec_meraki( + family="sm", + function='uninstallNetworkSmDeviceApps', + op_modifies=True, + params=self.get_object(self._task.args), + ) + self._result.update(dict(meraki_response=response)) + self._result.update(meraki.exit_json()) + return self._result diff --git a/ansible_collections/cisco/meraki/plugins/action/networks_sm_devices_wipe.py b/ansible_collections/cisco/meraki/plugins/action/networks_sm_devices_wipe.py index 1b20cad81..ca334bd8c 100644 --- a/ansible_collections/cisco/meraki/plugins/action/networks_sm_devices_wipe.py +++ b/ansible_collections/cisco/meraki/plugins/action/networks_sm_devices_wipe.py @@ -25,10 +25,10 @@ from ansible_collections.cisco.meraki.plugins.plugin_utils.meraki import ( argument_spec = meraki_argument_spec() # Add arguments specific for this module argument_spec.update(dict( - wifiMac=dict(type="str"), id=dict(type="str"), - serial=dict(type="str"), pin=dict(type="int"), + serial=dict(type="str"), + wifiMac=dict(type="str"), networkId=dict(type="str"), )) @@ -68,10 +68,10 @@ class ActionModule(ActionBase): def get_object(self, params): new_object = dict( - wifiMac=params.get("wifiMac"), id=params.get("id"), - serial=params.get("serial"), pin=params.get("pin"), + serial=params.get("serial"), + wifiMac=params.get("wifiMac"), networkId=params.get("networkId"), ) return new_object diff --git a/ansible_collections/cisco/meraki/plugins/action/networks_sm_profiles_info.py b/ansible_collections/cisco/meraki/plugins/action/networks_sm_profiles_info.py index 44ab17a59..d834af8b9 100644 --- a/ansible_collections/cisco/meraki/plugins/action/networks_sm_profiles_info.py +++ b/ansible_collections/cisco/meraki/plugins/action/networks_sm_profiles_info.py @@ -26,6 +26,7 @@ argument_spec = meraki_argument_spec() # Add arguments specific for this module argument_spec.update(dict( networkId=dict(type="str"), + payloadTypes=dict(type="list"), )) required_if = [] @@ -67,6 +68,9 @@ class ActionModule(ActionBase): if params.get("networkId") is not None: new_object["networkId"] = params.get( "networkId") + if params.get("payloadTypes") is not None: + new_object["payloadTypes"] = params.get( + "payloadTypes") return new_object diff --git a/ansible_collections/cisco/meraki/plugins/action/networks_switch_access_policies.py b/ansible_collections/cisco/meraki/plugins/action/networks_switch_access_policies.py index a56a7f0dd..aef2813a9 100644 --- a/ansible_collections/cisco/meraki/plugins/action/networks_switch_access_policies.py +++ b/ansible_collections/cisco/meraki/plugins/action/networks_switch_access_policies.py @@ -32,23 +32,23 @@ argument_spec = meraki_argument_spec() # Add arguments specific for this module argument_spec.update(dict( state=dict(type="str", default="present", choices=["present", "absent"]), + accessPolicyType=dict(type="str"), + dot1x=dict(type="dict"), + guestPortBouncing=dict(type="bool"), + guestVlanId=dict(type="int"), + hostMode=dict(type="str"), + increaseAccessSpeed=dict(type="bool"), name=dict(type="str"), - radiusServers=dict(type="list"), radius=dict(type="dict"), - guestPortBouncing=dict(type="bool"), - radiusTestingEnabled=dict(type="bool"), - radiusCoaSupportEnabled=dict(type="bool"), radiusAccountingEnabled=dict(type="bool"), radiusAccountingServers=dict(type="list"), + radiusCoaSupportEnabled=dict(type="bool"), radiusGroupAttribute=dict(type="str"), - hostMode=dict(type="str"), - accessPolicyType=dict(type="str"), - increaseAccessSpeed=dict(type="bool"), - guestVlanId=dict(type="int"), - dot1x=dict(type="dict"), - voiceVlanClients=dict(type="bool"), + radiusServers=dict(type="list"), + radiusTestingEnabled=dict(type="bool"), urlRedirectWalledGardenEnabled=dict(type="bool"), urlRedirectWalledGardenRanges=dict(type="list"), + voiceVlanClients=dict(type="bool"), networkId=dict(type="str"), accessPolicyNumber=dict(type="str"), )) @@ -66,25 +66,23 @@ class NetworksSwitchAccessPolicies(object): def __init__(self, params, meraki): self.meraki = meraki self.new_object = dict( + accessPolicyType=params.get("accessPolicyType"), + dot1x=params.get("dot1x"), + guestPortBouncing=params.get("guestPortBouncing"), + guestVlanId=params.get("guestVlanId"), + hostMode=params.get("hostMode"), + increaseAccessSpeed=params.get("increaseAccessSpeed"), name=params.get("name"), - radiusServers=params.get("radiusServers"), radius=params.get("radius"), - guestPortBouncing=params.get("guestPortBouncing"), - radiusTestingEnabled=params.get("radiusTestingEnabled"), - radiusCoaSupportEnabled=params.get("radiusCoaSupportEnabled"), radiusAccountingEnabled=params.get("radiusAccountingEnabled"), radiusAccountingServers=params.get("radiusAccountingServers"), + radiusCoaSupportEnabled=params.get("radiusCoaSupportEnabled"), radiusGroupAttribute=params.get("radiusGroupAttribute"), - hostMode=params.get("hostMode"), - accessPolicyType=params.get("accessPolicyType"), - increaseAccessSpeed=params.get("increaseAccessSpeed"), - guestVlanId=params.get("guestVlanId"), - dot1x=params.get("dot1x"), + radiusServers=params.get("radiusServers"), + radiusTestingEnabled=params.get("radiusTestingEnabled"), + urlRedirectWalledGardenEnabled=params.get("urlRedirectWalledGardenEnabled"), + urlRedirectWalledGardenRanges=params.get("urlRedirectWalledGardenRanges"), voiceVlanClients=params.get("voiceVlanClients"), - urlRedirectWalledGardenEnabled=params.get( - "urlRedirectWalledGardenEnabled"), - urlRedirectWalledGardenRanges=params.get( - "urlRedirectWalledGardenRanges"), networkId=params.get("networkId"), accessPolicyNumber=params.get("accessPolicyNumber"), ) @@ -108,57 +106,50 @@ class NetworksSwitchAccessPolicies(object): def create_params(self): new_object_params = {} + if self.new_object.get('accessPolicyType') is not None or self.new_object.get('access_policy_type') is not None: + new_object_params['accessPolicyType'] = self.new_object.get('accessPolicyType') or \ + self.new_object.get('access_policy_type') + if self.new_object.get('dot1x') is not None or self.new_object.get('dot1x') is not None: + new_object_params['dot1x'] = self.new_object.get('dot1x') or \ + self.new_object.get('dot1x') + if self.new_object.get('guestPortBouncing') is not None or self.new_object.get('guest_port_bouncing') is not None: + new_object_params['guestPortBouncing'] = self.new_object.get('guestPortBouncing') + if self.new_object.get('guestVlanId') is not None or self.new_object.get('guest_vlan_id') is not None: + new_object_params['guestVlanId'] = self.new_object.get('guestVlanId') or \ + self.new_object.get('guest_vlan_id') + if self.new_object.get('hostMode') is not None or self.new_object.get('host_mode') is not None: + new_object_params['hostMode'] = self.new_object.get('hostMode') or \ + self.new_object.get('host_mode') + if self.new_object.get('increaseAccessSpeed') is not None or self.new_object.get('increase_access_speed') is not None: + new_object_params['increaseAccessSpeed'] = self.new_object.get('increaseAccessSpeed') if self.new_object.get('name') is not None or self.new_object.get('name') is not None: new_object_params['name'] = self.new_object.get('name') or \ self.new_object.get('name') - if self.new_object.get('radiusServers') is not None or self.new_object.get('radius_servers') is not None: - new_object_params['radiusServers'] = self.new_object.get('radiusServers') or \ - self.new_object.get('radius_servers') if self.new_object.get('radius') is not None or self.new_object.get('radius') is not None: new_object_params['radius'] = self.new_object.get('radius') or \ self.new_object.get('radius') - if self.new_object.get('guestPortBouncing') is not None or self.new_object.get('guest_port_bouncing') is not None: - new_object_params['guestPortBouncing'] = self.new_object.get( - 'guestPortBouncing') - if self.new_object.get('radiusTestingEnabled') is not None or self.new_object.get('radius_testing_enabled') is not None: - new_object_params['radiusTestingEnabled'] = self.new_object.get( - 'radiusTestingEnabled') - if self.new_object.get('radiusCoaSupportEnabled') is not None or self.new_object.get('radius_coa_support_enabled') is not None: - new_object_params['radiusCoaSupportEnabled'] = self.new_object.get( - 'radiusCoaSupportEnabled') if self.new_object.get('radiusAccountingEnabled') is not None or self.new_object.get('radius_accounting_enabled') is not None: - new_object_params['radiusAccountingEnabled'] = self.new_object.get( - 'radiusAccountingEnabled') + new_object_params['radiusAccountingEnabled'] = self.new_object.get('radiusAccountingEnabled') if self.new_object.get('radiusAccountingServers') is not None or self.new_object.get('radius_accounting_servers') is not None: new_object_params['radiusAccountingServers'] = self.new_object.get('radiusAccountingServers') or \ self.new_object.get('radius_accounting_servers') + if self.new_object.get('radiusCoaSupportEnabled') is not None or self.new_object.get('radius_coa_support_enabled') is not None: + new_object_params['radiusCoaSupportEnabled'] = self.new_object.get('radiusCoaSupportEnabled') if self.new_object.get('radiusGroupAttribute') is not None or self.new_object.get('radius_group_attribute') is not None: new_object_params['radiusGroupAttribute'] = self.new_object.get('radiusGroupAttribute') or \ self.new_object.get('radius_group_attribute') - if self.new_object.get('hostMode') is not None or self.new_object.get('host_mode') is not None: - new_object_params['hostMode'] = self.new_object.get('hostMode') or \ - self.new_object.get('host_mode') - if self.new_object.get('accessPolicyType') is not None or self.new_object.get('access_policy_type') is not None: - new_object_params['accessPolicyType'] = self.new_object.get('accessPolicyType') or \ - self.new_object.get('access_policy_type') - if self.new_object.get('increaseAccessSpeed') is not None or self.new_object.get('increase_access_speed') is not None: - new_object_params['increaseAccessSpeed'] = self.new_object.get( - 'increaseAccessSpeed') - if self.new_object.get('guestVlanId') is not None or self.new_object.get('guest_vlan_id') is not None: - new_object_params['guestVlanId'] = self.new_object.get('guestVlanId') or \ - self.new_object.get('guest_vlan_id') - if self.new_object.get('dot1x') is not None or self.new_object.get('dot1x') is not None: - new_object_params['dot1x'] = self.new_object.get('dot1x') or \ - self.new_object.get('dot1x') - if self.new_object.get('voiceVlanClients') is not None or self.new_object.get('voice_vlan_clients') is not None: - new_object_params['voiceVlanClients'] = self.new_object.get( - 'voiceVlanClients') + if self.new_object.get('radiusServers') is not None or self.new_object.get('radius_servers') is not None: + new_object_params['radiusServers'] = self.new_object.get('radiusServers') or \ + self.new_object.get('radius_servers') + if self.new_object.get('radiusTestingEnabled') is not None or self.new_object.get('radius_testing_enabled') is not None: + new_object_params['radiusTestingEnabled'] = self.new_object.get('radiusTestingEnabled') if self.new_object.get('urlRedirectWalledGardenEnabled') is not None or self.new_object.get('url_redirect_walled_garden_enabled') is not None: - new_object_params['urlRedirectWalledGardenEnabled'] = self.new_object.get( - 'urlRedirectWalledGardenEnabled') + new_object_params['urlRedirectWalledGardenEnabled'] = self.new_object.get('urlRedirectWalledGardenEnabled') if self.new_object.get('urlRedirectWalledGardenRanges') is not None or self.new_object.get('url_redirect_walled_garden_ranges') is not None: new_object_params['urlRedirectWalledGardenRanges'] = self.new_object.get('urlRedirectWalledGardenRanges') or \ self.new_object.get('url_redirect_walled_garden_ranges') + if self.new_object.get('voiceVlanClients') is not None or self.new_object.get('voice_vlan_clients') is not None: + new_object_params['voiceVlanClients'] = self.new_object.get('voiceVlanClients') if self.new_object.get('networkId') is not None or self.new_object.get('network_id') is not None: new_object_params['networkId'] = self.new_object.get('networkId') or \ self.new_object.get('network_id') @@ -176,57 +167,50 @@ class NetworksSwitchAccessPolicies(object): def update_by_id_params(self): new_object_params = {} + if self.new_object.get('accessPolicyType') is not None or self.new_object.get('access_policy_type') is not None: + new_object_params['accessPolicyType'] = self.new_object.get('accessPolicyType') or \ + self.new_object.get('access_policy_type') + if self.new_object.get('dot1x') is not None or self.new_object.get('dot1x') is not None: + new_object_params['dot1x'] = self.new_object.get('dot1x') or \ + self.new_object.get('dot1x') + if self.new_object.get('guestPortBouncing') is not None or self.new_object.get('guest_port_bouncing') is not None: + new_object_params['guestPortBouncing'] = self.new_object.get('guestPortBouncing') + if self.new_object.get('guestVlanId') is not None or self.new_object.get('guest_vlan_id') is not None: + new_object_params['guestVlanId'] = self.new_object.get('guestVlanId') or \ + self.new_object.get('guest_vlan_id') + if self.new_object.get('hostMode') is not None or self.new_object.get('host_mode') is not None: + new_object_params['hostMode'] = self.new_object.get('hostMode') or \ + self.new_object.get('host_mode') + if self.new_object.get('increaseAccessSpeed') is not None or self.new_object.get('increase_access_speed') is not None: + new_object_params['increaseAccessSpeed'] = self.new_object.get('increaseAccessSpeed') if self.new_object.get('name') is not None or self.new_object.get('name') is not None: new_object_params['name'] = self.new_object.get('name') or \ self.new_object.get('name') - if self.new_object.get('radiusServers') is not None or self.new_object.get('radius_servers') is not None: - new_object_params['radiusServers'] = self.new_object.get('radiusServers') or \ - self.new_object.get('radius_servers') if self.new_object.get('radius') is not None or self.new_object.get('radius') is not None: new_object_params['radius'] = self.new_object.get('radius') or \ self.new_object.get('radius') - if self.new_object.get('guestPortBouncing') is not None or self.new_object.get('guest_port_bouncing') is not None: - new_object_params['guestPortBouncing'] = self.new_object.get( - 'guestPortBouncing') - if self.new_object.get('radiusTestingEnabled') is not None or self.new_object.get('radius_testing_enabled') is not None: - new_object_params['radiusTestingEnabled'] = self.new_object.get( - 'radiusTestingEnabled') - if self.new_object.get('radiusCoaSupportEnabled') is not None or self.new_object.get('radius_coa_support_enabled') is not None: - new_object_params['radiusCoaSupportEnabled'] = self.new_object.get( - 'radiusCoaSupportEnabled') if self.new_object.get('radiusAccountingEnabled') is not None or self.new_object.get('radius_accounting_enabled') is not None: - new_object_params['radiusAccountingEnabled'] = self.new_object.get( - 'radiusAccountingEnabled') + new_object_params['radiusAccountingEnabled'] = self.new_object.get('radiusAccountingEnabled') if self.new_object.get('radiusAccountingServers') is not None or self.new_object.get('radius_accounting_servers') is not None: new_object_params['radiusAccountingServers'] = self.new_object.get('radiusAccountingServers') or \ self.new_object.get('radius_accounting_servers') + if self.new_object.get('radiusCoaSupportEnabled') is not None or self.new_object.get('radius_coa_support_enabled') is not None: + new_object_params['radiusCoaSupportEnabled'] = self.new_object.get('radiusCoaSupportEnabled') if self.new_object.get('radiusGroupAttribute') is not None or self.new_object.get('radius_group_attribute') is not None: new_object_params['radiusGroupAttribute'] = self.new_object.get('radiusGroupAttribute') or \ self.new_object.get('radius_group_attribute') - if self.new_object.get('hostMode') is not None or self.new_object.get('host_mode') is not None: - new_object_params['hostMode'] = self.new_object.get('hostMode') or \ - self.new_object.get('host_mode') - if self.new_object.get('accessPolicyType') is not None or self.new_object.get('access_policy_type') is not None: - new_object_params['accessPolicyType'] = self.new_object.get('accessPolicyType') or \ - self.new_object.get('access_policy_type') - if self.new_object.get('increaseAccessSpeed') is not None or self.new_object.get('increase_access_speed') is not None: - new_object_params['increaseAccessSpeed'] = self.new_object.get( - 'increaseAccessSpeed') - if self.new_object.get('guestVlanId') is not None or self.new_object.get('guest_vlan_id') is not None: - new_object_params['guestVlanId'] = self.new_object.get('guestVlanId') or \ - self.new_object.get('guest_vlan_id') - if self.new_object.get('dot1x') is not None or self.new_object.get('dot1x') is not None: - new_object_params['dot1x'] = self.new_object.get('dot1x') or \ - self.new_object.get('dot1x') - if self.new_object.get('voiceVlanClients') is not None or self.new_object.get('voice_vlan_clients') is not None: - new_object_params['voiceVlanClients'] = self.new_object.get( - 'voiceVlanClients') + if self.new_object.get('radiusServers') is not None or self.new_object.get('radius_servers') is not None: + new_object_params['radiusServers'] = self.new_object.get('radiusServers') or \ + self.new_object.get('radius_servers') + if self.new_object.get('radiusTestingEnabled') is not None or self.new_object.get('radius_testing_enabled') is not None: + new_object_params['radiusTestingEnabled'] = self.new_object.get('radiusTestingEnabled') if self.new_object.get('urlRedirectWalledGardenEnabled') is not None or self.new_object.get('url_redirect_walled_garden_enabled') is not None: - new_object_params['urlRedirectWalledGardenEnabled'] = self.new_object.get( - 'urlRedirectWalledGardenEnabled') + new_object_params['urlRedirectWalledGardenEnabled'] = self.new_object.get('urlRedirectWalledGardenEnabled') if self.new_object.get('urlRedirectWalledGardenRanges') is not None or self.new_object.get('url_redirect_walled_garden_ranges') is not None: new_object_params['urlRedirectWalledGardenRanges'] = self.new_object.get('urlRedirectWalledGardenRanges') or \ self.new_object.get('url_redirect_walled_garden_ranges') + if self.new_object.get('voiceVlanClients') is not None or self.new_object.get('voice_vlan_clients') is not None: + new_object_params['voiceVlanClients'] = self.new_object.get('voiceVlanClients') if self.new_object.get('networkId') is not None or self.new_object.get('network_id') is not None: new_object_params['networkId'] = self.new_object.get('networkId') or \ self.new_object.get('network_id') @@ -304,23 +288,23 @@ class NetworksSwitchAccessPolicies(object): requested_obj = self.new_object obj_params = [ + ("accessPolicyType", "accessPolicyType"), + ("dot1x", "dot1x"), + ("guestPortBouncing", "guestPortBouncing"), + ("guestVlanId", "guestVlanId"), + ("hostMode", "hostMode"), + ("increaseAccessSpeed", "increaseAccessSpeed"), ("name", "name"), - ("radiusServers", "radiusServers"), ("radius", "radius"), - ("guestPortBouncing", "guestPortBouncing"), - ("radiusTestingEnabled", "radiusTestingEnabled"), - ("radiusCoaSupportEnabled", "radiusCoaSupportEnabled"), ("radiusAccountingEnabled", "radiusAccountingEnabled"), ("radiusAccountingServers", "radiusAccountingServers"), + ("radiusCoaSupportEnabled", "radiusCoaSupportEnabled"), ("radiusGroupAttribute", "radiusGroupAttribute"), - ("hostMode", "hostMode"), - ("accessPolicyType", "accessPolicyType"), - ("increaseAccessSpeed", "increaseAccessSpeed"), - ("guestVlanId", "guestVlanId"), - ("dot1x", "dot1x"), - ("voiceVlanClients", "voiceVlanClients"), + ("radiusServers", "radiusServers"), + ("radiusTestingEnabled", "radiusTestingEnabled"), ("urlRedirectWalledGardenEnabled", "urlRedirectWalledGardenEnabled"), ("urlRedirectWalledGardenRanges", "urlRedirectWalledGardenRanges"), + ("voiceVlanClients", "voiceVlanClients"), ("networkId", "networkId"), ("accessPolicyNumber", "accessPolicyNumber"), ] diff --git a/ansible_collections/cisco/meraki/plugins/action/networks_switch_alternate_management_interface.py b/ansible_collections/cisco/meraki/plugins/action/networks_switch_alternate_management_interface.py index 7fd38d4f3..02d8d2c0c 100644 --- a/ansible_collections/cisco/meraki/plugins/action/networks_switch_alternate_management_interface.py +++ b/ansible_collections/cisco/meraki/plugins/action/networks_switch_alternate_management_interface.py @@ -33,9 +33,9 @@ argument_spec = meraki_argument_spec() argument_spec.update(dict( state=dict(type="str", default="present", choices=["present"]), enabled=dict(type="bool"), - vlanId=dict(type="int"), protocols=dict(type="list"), switches=dict(type="list"), + vlanId=dict(type="int"), networkId=dict(type="str"), )) @@ -52,9 +52,9 @@ class NetworksSwitchAlternateManagementInterface(object): self.meraki = meraki self.new_object = dict( enabled=params.get("enabled"), - vlanId=params.get("vlanId"), protocols=params.get("protocols"), switches=params.get("switches"), + vlanId=params.get("vlanId"), network_id=params.get("networkId"), ) @@ -69,15 +69,15 @@ class NetworksSwitchAlternateManagementInterface(object): new_object_params = {} if self.new_object.get('enabled') is not None or self.new_object.get('enabled') is not None: new_object_params['enabled'] = self.new_object.get('enabled') - if self.new_object.get('vlanId') is not None or self.new_object.get('vlan_id') is not None: - new_object_params['vlanId'] = self.new_object.get('vlanId') or \ - self.new_object.get('vlan_id') if self.new_object.get('protocols') is not None or self.new_object.get('protocols') is not None: new_object_params['protocols'] = self.new_object.get('protocols') or \ self.new_object.get('protocols') if self.new_object.get('switches') is not None or self.new_object.get('switches') is not None: new_object_params['switches'] = self.new_object.get('switches') or \ self.new_object.get('switches') + if self.new_object.get('vlanId') is not None or self.new_object.get('vlan_id') is not None: + new_object_params['vlanId'] = self.new_object.get('vlanId') or \ + self.new_object.get('vlan_id') if self.new_object.get('networkId') is not None or self.new_object.get('network_id') is not None: new_object_params['networkId'] = self.new_object.get('networkId') or \ self.new_object.get('network_id') @@ -135,9 +135,9 @@ class NetworksSwitchAlternateManagementInterface(object): obj_params = [ ("enabled", "enabled"), - ("vlanId", "vlanId"), ("protocols", "protocols"), ("switches", "switches"), + ("vlanId", "vlanId"), ("networkId", "networkId"), ] # Method 1. Params present in request (Ansible) obj are the same as the current (ISE) params diff --git a/ansible_collections/cisco/meraki/plugins/action/networks_switch_dhcp_server_policy.py b/ansible_collections/cisco/meraki/plugins/action/networks_switch_dhcp_server_policy.py index 70dae83da..4e3434058 100644 --- a/ansible_collections/cisco/meraki/plugins/action/networks_switch_dhcp_server_policy.py +++ b/ansible_collections/cisco/meraki/plugins/action/networks_switch_dhcp_server_policy.py @@ -33,10 +33,10 @@ argument_spec = meraki_argument_spec() argument_spec.update(dict( state=dict(type="str", default="present", choices=["present"]), alerts=dict(type="dict"), - defaultPolicy=dict(type="str"), allowedServers=dict(type="list"), - blockedServers=dict(type="list"), arpInspection=dict(type="dict"), + blockedServers=dict(type="list"), + defaultPolicy=dict(type="str"), networkId=dict(type="str"), )) @@ -53,10 +53,10 @@ class NetworksSwitchDhcpServerPolicy(object): self.meraki = meraki self.new_object = dict( alerts=params.get("alerts"), - defaultPolicy=params.get("defaultPolicy"), allowedServers=params.get("allowedServers"), - blockedServers=params.get("blockedServers"), arpInspection=params.get("arpInspection"), + blockedServers=params.get("blockedServers"), + defaultPolicy=params.get("defaultPolicy"), network_id=params.get("networkId"), ) @@ -72,18 +72,18 @@ class NetworksSwitchDhcpServerPolicy(object): if self.new_object.get('alerts') is not None or self.new_object.get('alerts') is not None: new_object_params['alerts'] = self.new_object.get('alerts') or \ self.new_object.get('alerts') - if self.new_object.get('defaultPolicy') is not None or self.new_object.get('default_policy') is not None: - new_object_params['defaultPolicy'] = self.new_object.get('defaultPolicy') or \ - self.new_object.get('default_policy') if self.new_object.get('allowedServers') is not None or self.new_object.get('allowed_servers') is not None: new_object_params['allowedServers'] = self.new_object.get('allowedServers') or \ self.new_object.get('allowed_servers') - if self.new_object.get('blockedServers') is not None or self.new_object.get('blocked_servers') is not None: - new_object_params['blockedServers'] = self.new_object.get('blockedServers') or \ - self.new_object.get('blocked_servers') if self.new_object.get('arpInspection') is not None or self.new_object.get('arp_inspection') is not None: new_object_params['arpInspection'] = self.new_object.get('arpInspection') or \ self.new_object.get('arp_inspection') + if self.new_object.get('blockedServers') is not None or self.new_object.get('blocked_servers') is not None: + new_object_params['blockedServers'] = self.new_object.get('blockedServers') or \ + self.new_object.get('blocked_servers') + if self.new_object.get('defaultPolicy') is not None or self.new_object.get('default_policy') is not None: + new_object_params['defaultPolicy'] = self.new_object.get('defaultPolicy') or \ + self.new_object.get('default_policy') if self.new_object.get('networkId') is not None or self.new_object.get('network_id') is not None: new_object_params['networkId'] = self.new_object.get('networkId') or \ self.new_object.get('network_id') @@ -141,10 +141,10 @@ class NetworksSwitchDhcpServerPolicy(object): obj_params = [ ("alerts", "alerts"), - ("defaultPolicy", "defaultPolicy"), ("allowedServers", "allowedServers"), - ("blockedServers", "blockedServers"), ("arpInspection", "arpInspection"), + ("blockedServers", "blockedServers"), + ("defaultPolicy", "defaultPolicy"), ("networkId", "networkId"), ] # Method 1. Params present in request (Ansible) obj are the same as the current (ISE) params diff --git a/ansible_collections/cisco/meraki/plugins/action/networks_switch_dhcp_server_policy_arp_inspection_trusted_servers.py b/ansible_collections/cisco/meraki/plugins/action/networks_switch_dhcp_server_policy_arp_inspection_trusted_servers.py index d0bd4b120..e6110049d 100644 --- a/ansible_collections/cisco/meraki/plugins/action/networks_switch_dhcp_server_policy_arp_inspection_trusted_servers.py +++ b/ansible_collections/cisco/meraki/plugins/action/networks_switch_dhcp_server_policy_arp_inspection_trusted_servers.py @@ -32,9 +32,9 @@ argument_spec = meraki_argument_spec() # Add arguments specific for this module argument_spec.update(dict( state=dict(type="str", default="present", choices=["present", "absent"]), + ipv4=dict(type="dict"), mac=dict(type="str"), vlan=dict(type="int"), - ipv4=dict(type="dict"), networkId=dict(type="str"), trustedServerId=dict(type="str"), )) @@ -52,9 +52,9 @@ class NetworksSwitchDhcpServerPolicyArpInspectionTrustedServers(object): def __init__(self, params, meraki): self.meraki = meraki self.new_object = dict( + ipv4=params.get("ipv4"), mac=params.get("mac"), vlan=params.get("vlan"), - ipv4=params.get("ipv4"), networkId=params.get("networkId"), trustedServerId=params.get("trustedServerId"), ) @@ -78,15 +78,15 @@ class NetworksSwitchDhcpServerPolicyArpInspectionTrustedServers(object): def create_params(self): new_object_params = {} + if self.new_object.get('ipv4') is not None or self.new_object.get('ipv4') is not None: + new_object_params['ipv4'] = self.new_object.get('ipv4') or \ + self.new_object.get('ipv4') if self.new_object.get('mac') is not None or self.new_object.get('mac') is not None: new_object_params['mac'] = self.new_object.get('mac') or \ self.new_object.get('mac') if self.new_object.get('vlan') is not None or self.new_object.get('vlan') is not None: new_object_params['vlan'] = self.new_object.get('vlan') or \ self.new_object.get('vlan') - if self.new_object.get('ipv4') is not None or self.new_object.get('ipv4') is not None: - new_object_params['ipv4'] = self.new_object.get('ipv4') or \ - self.new_object.get('ipv4') if self.new_object.get('networkId') is not None or self.new_object.get('network_id') is not None: new_object_params['networkId'] = self.new_object.get('networkId') or \ self.new_object.get('network_id') @@ -104,15 +104,15 @@ class NetworksSwitchDhcpServerPolicyArpInspectionTrustedServers(object): def update_by_id_params(self): new_object_params = {} + if self.new_object.get('ipv4') is not None or self.new_object.get('ipv4') is not None: + new_object_params['ipv4'] = self.new_object.get('ipv4') or \ + self.new_object.get('ipv4') if self.new_object.get('mac') is not None or self.new_object.get('mac') is not None: new_object_params['mac'] = self.new_object.get('mac') or \ self.new_object.get('mac') if self.new_object.get('vlan') is not None or self.new_object.get('vlan') is not None: new_object_params['vlan'] = self.new_object.get('vlan') or \ self.new_object.get('vlan') - if self.new_object.get('ipv4') is not None or self.new_object.get('ipv4') is not None: - new_object_params['ipv4'] = self.new_object.get('ipv4') or \ - self.new_object.get('ipv4') if self.new_object.get('networkId') is not None or self.new_object.get('network_id') is not None: new_object_params['networkId'] = self.new_object.get('networkId') or \ self.new_object.get('network_id') @@ -189,9 +189,9 @@ class NetworksSwitchDhcpServerPolicyArpInspectionTrustedServers(object): requested_obj = self.new_object obj_params = [ + ("ipv4", "ipv4"), ("mac", "mac"), ("vlan", "vlan"), - ("ipv4", "ipv4"), ("networkId", "networkId"), ("trustedServerId", "trustedServerId"), ] diff --git a/ansible_collections/cisco/meraki/plugins/action/networks_switch_qos_rules_order.py b/ansible_collections/cisco/meraki/plugins/action/networks_switch_qos_rules_order.py index 33841d11c..430d78211 100644 --- a/ansible_collections/cisco/meraki/plugins/action/networks_switch_qos_rules_order.py +++ b/ansible_collections/cisco/meraki/plugins/action/networks_switch_qos_rules_order.py @@ -32,13 +32,13 @@ argument_spec = meraki_argument_spec() # Add arguments specific for this module argument_spec.update(dict( state=dict(type="str", default="present", choices=["present", "absent"]), - vlan=dict(type="int"), + dscp=dict(type="int"), + dstPort=dict(type="int"), + dstPortRange=dict(type="str"), protocol=dict(type="str"), srcPort=dict(type="int"), srcPortRange=dict(type="str"), - dstPort=dict(type="int"), - dstPortRange=dict(type="str"), - dscp=dict(type="int"), + vlan=dict(type="int"), networkId=dict(type="str"), qosRuleId=dict(type="str"), )) @@ -56,13 +56,13 @@ class NetworksSwitchQosRulesOrder(object): def __init__(self, params, meraki): self.meraki = meraki self.new_object = dict( - vlan=params.get("vlan"), + dscp=params.get("dscp"), + dstPort=params.get("dstPort"), + dstPortRange=params.get("dstPortRange"), protocol=params.get("protocol"), srcPort=params.get("srcPort"), srcPortRange=params.get("srcPortRange"), - dstPort=params.get("dstPort"), - dstPortRange=params.get("dstPortRange"), - dscp=params.get("dscp"), + vlan=params.get("vlan"), networkId=params.get("networkId"), qosRuleId=params.get("qosRuleId"), ) @@ -86,9 +86,15 @@ class NetworksSwitchQosRulesOrder(object): def create_params(self): new_object_params = {} - if self.new_object.get('vlan') is not None or self.new_object.get('vlan') is not None: - new_object_params['vlan'] = self.new_object.get('vlan') or \ - self.new_object.get('vlan') + if self.new_object.get('dscp') is not None or self.new_object.get('dscp') is not None: + new_object_params['dscp'] = self.new_object.get('dscp') or \ + self.new_object.get('dscp') + if self.new_object.get('dstPort') is not None or self.new_object.get('dst_port') is not None: + new_object_params['dstPort'] = self.new_object.get('dstPort') or \ + self.new_object.get('dst_port') + if self.new_object.get('dstPortRange') is not None or self.new_object.get('dst_port_range') is not None: + new_object_params['dstPortRange'] = self.new_object.get('dstPortRange') or \ + self.new_object.get('dst_port_range') if self.new_object.get('protocol') is not None or self.new_object.get('protocol') is not None: new_object_params['protocol'] = self.new_object.get('protocol') or \ self.new_object.get('protocol') @@ -98,15 +104,9 @@ class NetworksSwitchQosRulesOrder(object): if self.new_object.get('srcPortRange') is not None or self.new_object.get('src_port_range') is not None: new_object_params['srcPortRange'] = self.new_object.get('srcPortRange') or \ self.new_object.get('src_port_range') - if self.new_object.get('dstPort') is not None or self.new_object.get('dst_port') is not None: - new_object_params['dstPort'] = self.new_object.get('dstPort') or \ - self.new_object.get('dst_port') - if self.new_object.get('dstPortRange') is not None or self.new_object.get('dst_port_range') is not None: - new_object_params['dstPortRange'] = self.new_object.get('dstPortRange') or \ - self.new_object.get('dst_port_range') - if self.new_object.get('dscp') is not None or self.new_object.get('dscp') is not None: - new_object_params['dscp'] = self.new_object.get('dscp') or \ - self.new_object.get('dscp') + if self.new_object.get('vlan') is not None or self.new_object.get('vlan') is not None: + new_object_params['vlan'] = self.new_object.get('vlan') or \ + self.new_object.get('vlan') if self.new_object.get('networkId') is not None or self.new_object.get('network_id') is not None: new_object_params['networkId'] = self.new_object.get('networkId') or \ self.new_object.get('network_id') @@ -124,9 +124,15 @@ class NetworksSwitchQosRulesOrder(object): def update_by_id_params(self): new_object_params = {} - if self.new_object.get('vlan') is not None or self.new_object.get('vlan') is not None: - new_object_params['vlan'] = self.new_object.get('vlan') or \ - self.new_object.get('vlan') + if self.new_object.get('dscp') is not None or self.new_object.get('dscp') is not None: + new_object_params['dscp'] = self.new_object.get('dscp') or \ + self.new_object.get('dscp') + if self.new_object.get('dstPort') is not None or self.new_object.get('dst_port') is not None: + new_object_params['dstPort'] = self.new_object.get('dstPort') or \ + self.new_object.get('dst_port') + if self.new_object.get('dstPortRange') is not None or self.new_object.get('dst_port_range') is not None: + new_object_params['dstPortRange'] = self.new_object.get('dstPortRange') or \ + self.new_object.get('dst_port_range') if self.new_object.get('protocol') is not None or self.new_object.get('protocol') is not None: new_object_params['protocol'] = self.new_object.get('protocol') or \ self.new_object.get('protocol') @@ -136,15 +142,9 @@ class NetworksSwitchQosRulesOrder(object): if self.new_object.get('srcPortRange') is not None or self.new_object.get('src_port_range') is not None: new_object_params['srcPortRange'] = self.new_object.get('srcPortRange') or \ self.new_object.get('src_port_range') - if self.new_object.get('dstPort') is not None or self.new_object.get('dst_port') is not None: - new_object_params['dstPort'] = self.new_object.get('dstPort') or \ - self.new_object.get('dst_port') - if self.new_object.get('dstPortRange') is not None or self.new_object.get('dst_port_range') is not None: - new_object_params['dstPortRange'] = self.new_object.get('dstPortRange') or \ - self.new_object.get('dst_port_range') - if self.new_object.get('dscp') is not None or self.new_object.get('dscp') is not None: - new_object_params['dscp'] = self.new_object.get('dscp') or \ - self.new_object.get('dscp') + if self.new_object.get('vlan') is not None or self.new_object.get('vlan') is not None: + new_object_params['vlan'] = self.new_object.get('vlan') or \ + self.new_object.get('vlan') if self.new_object.get('networkId') is not None or self.new_object.get('network_id') is not None: new_object_params['networkId'] = self.new_object.get('networkId') or \ self.new_object.get('network_id') @@ -222,13 +222,13 @@ class NetworksSwitchQosRulesOrder(object): requested_obj = self.new_object obj_params = [ - ("vlan", "vlan"), + ("dscp", "dscp"), + ("dstPort", "dstPort"), + ("dstPortRange", "dstPortRange"), ("protocol", "protocol"), ("srcPort", "srcPort"), ("srcPortRange", "srcPortRange"), - ("dstPort", "dstPort"), - ("dstPortRange", "dstPortRange"), - ("dscp", "dscp"), + ("vlan", "vlan"), ("networkId", "networkId"), ("qosRuleId", "qosRuleId"), ] diff --git a/ansible_collections/cisco/meraki/plugins/action/networks_switch_routing_ospf.py b/ansible_collections/cisco/meraki/plugins/action/networks_switch_routing_ospf.py index ec0eed0ee..aa72b735c 100644 --- a/ansible_collections/cisco/meraki/plugins/action/networks_switch_routing_ospf.py +++ b/ansible_collections/cisco/meraki/plugins/action/networks_switch_routing_ospf.py @@ -32,13 +32,13 @@ argument_spec = meraki_argument_spec() # Add arguments specific for this module argument_spec.update(dict( state=dict(type="str", default="present", choices=["present"]), + areas=dict(type="list"), + deadTimerInSeconds=dict(type="int"), enabled=dict(type="bool"), helloTimerInSeconds=dict(type="int"), - deadTimerInSeconds=dict(type="int"), - areas=dict(type="list"), - v3=dict(type="dict"), md5AuthenticationEnabled=dict(type="bool"), md5AuthenticationKey=dict(type="dict"), + v3=dict(type="dict"), networkId=dict(type="str"), )) @@ -54,13 +54,13 @@ class NetworksSwitchRoutingOspf(object): def __init__(self, params, meraki): self.meraki = meraki self.new_object = dict( + areas=params.get("areas"), + deadTimerInSeconds=params.get("deadTimerInSeconds"), enabled=params.get("enabled"), helloTimerInSeconds=params.get("helloTimerInSeconds"), - deadTimerInSeconds=params.get("deadTimerInSeconds"), - areas=params.get("areas"), - v3=params.get("v3"), md5AuthenticationEnabled=params.get("md5AuthenticationEnabled"), md5AuthenticationKey=params.get("md5AuthenticationKey"), + v3=params.get("v3"), network_id=params.get("networkId"), ) @@ -73,25 +73,25 @@ class NetworksSwitchRoutingOspf(object): def update_all_params(self): new_object_params = {} + if self.new_object.get('areas') is not None or self.new_object.get('areas') is not None: + new_object_params['areas'] = self.new_object.get('areas') or \ + self.new_object.get('areas') + if self.new_object.get('deadTimerInSeconds') is not None or self.new_object.get('dead_timer_in_seconds') is not None: + new_object_params['deadTimerInSeconds'] = self.new_object.get('deadTimerInSeconds') or \ + self.new_object.get('dead_timer_in_seconds') if self.new_object.get('enabled') is not None or self.new_object.get('enabled') is not None: new_object_params['enabled'] = self.new_object.get('enabled') if self.new_object.get('helloTimerInSeconds') is not None or self.new_object.get('hello_timer_in_seconds') is not None: new_object_params['helloTimerInSeconds'] = self.new_object.get('helloTimerInSeconds') or \ self.new_object.get('hello_timer_in_seconds') - if self.new_object.get('deadTimerInSeconds') is not None or self.new_object.get('dead_timer_in_seconds') is not None: - new_object_params['deadTimerInSeconds'] = self.new_object.get('deadTimerInSeconds') or \ - self.new_object.get('dead_timer_in_seconds') - if self.new_object.get('areas') is not None or self.new_object.get('areas') is not None: - new_object_params['areas'] = self.new_object.get('areas') or \ - self.new_object.get('areas') - if self.new_object.get('v3') is not None or self.new_object.get('v3') is not None: - new_object_params['v3'] = self.new_object.get('v3') or \ - self.new_object.get('v3') if self.new_object.get('md5AuthenticationEnabled') is not None or self.new_object.get('md5_authentication_enabled') is not None: new_object_params['md5AuthenticationEnabled'] = self.new_object.get('md5AuthenticationEnabled') if self.new_object.get('md5AuthenticationKey') is not None or self.new_object.get('md5_authentication_key') is not None: new_object_params['md5AuthenticationKey'] = self.new_object.get('md5AuthenticationKey') or \ self.new_object.get('md5_authentication_key') + if self.new_object.get('v3') is not None or self.new_object.get('v3') is not None: + new_object_params['v3'] = self.new_object.get('v3') or \ + self.new_object.get('v3') if self.new_object.get('networkId') is not None or self.new_object.get('network_id') is not None: new_object_params['networkId'] = self.new_object.get('networkId') or \ self.new_object.get('network_id') @@ -148,13 +148,13 @@ class NetworksSwitchRoutingOspf(object): requested_obj = self.new_object obj_params = [ + ("areas", "areas"), + ("deadTimerInSeconds", "deadTimerInSeconds"), ("enabled", "enabled"), ("helloTimerInSeconds", "helloTimerInSeconds"), - ("deadTimerInSeconds", "deadTimerInSeconds"), - ("areas", "areas"), - ("v3", "v3"), ("md5AuthenticationEnabled", "md5AuthenticationEnabled"), ("md5AuthenticationKey", "md5AuthenticationKey"), + ("v3", "v3"), ("networkId", "networkId"), ] # Method 1. Params present in request (Ansible) obj are the same as the current (ISE) params diff --git a/ansible_collections/cisco/meraki/plugins/action/networks_switch_settings.py b/ansible_collections/cisco/meraki/plugins/action/networks_switch_settings.py index 65ae85bab..66664b957 100644 --- a/ansible_collections/cisco/meraki/plugins/action/networks_switch_settings.py +++ b/ansible_collections/cisco/meraki/plugins/action/networks_switch_settings.py @@ -32,9 +32,11 @@ argument_spec = meraki_argument_spec() # Add arguments specific for this module argument_spec.update(dict( state=dict(type="str", default="present", choices=["present"]), - vlan=dict(type="int"), - useCombinedPower=dict(type="bool"), + macBlocklist=dict(type="dict"), powerExceptions=dict(type="list"), + uplinkClientSampling=dict(type="dict"), + useCombinedPower=dict(type="bool"), + vlan=dict(type="int"), networkId=dict(type="str"), )) @@ -50,9 +52,11 @@ class NetworksSwitchSettings(object): def __init__(self, params, meraki): self.meraki = meraki self.new_object = dict( - vlan=params.get("vlan"), - useCombinedPower=params.get("useCombinedPower"), + macBlocklist=params.get("macBlocklist"), powerExceptions=params.get("powerExceptions"), + uplinkClientSampling=params.get("uplinkClientSampling"), + useCombinedPower=params.get("useCombinedPower"), + vlan=params.get("vlan"), network_id=params.get("networkId"), ) @@ -65,14 +69,20 @@ class NetworksSwitchSettings(object): def update_all_params(self): new_object_params = {} - if self.new_object.get('vlan') is not None or self.new_object.get('vlan') is not None: - new_object_params['vlan'] = self.new_object.get('vlan') or \ - self.new_object.get('vlan') - if self.new_object.get('useCombinedPower') is not None or self.new_object.get('use_combined_power') is not None: - new_object_params['useCombinedPower'] = self.new_object.get('useCombinedPower') + if self.new_object.get('macBlocklist') is not None or self.new_object.get('mac_blocklist') is not None: + new_object_params['macBlocklist'] = self.new_object.get('macBlocklist') or \ + self.new_object.get('mac_blocklist') if self.new_object.get('powerExceptions') is not None or self.new_object.get('power_exceptions') is not None: new_object_params['powerExceptions'] = self.new_object.get('powerExceptions') or \ self.new_object.get('power_exceptions') + if self.new_object.get('uplinkClientSampling') is not None or self.new_object.get('uplink_client_sampling') is not None: + new_object_params['uplinkClientSampling'] = self.new_object.get('uplinkClientSampling') or \ + self.new_object.get('uplink_client_sampling') + if self.new_object.get('useCombinedPower') is not None or self.new_object.get('use_combined_power') is not None: + new_object_params['useCombinedPower'] = self.new_object.get('useCombinedPower') + if self.new_object.get('vlan') is not None or self.new_object.get('vlan') is not None: + new_object_params['vlan'] = self.new_object.get('vlan') or \ + self.new_object.get('vlan') if self.new_object.get('networkId') is not None or self.new_object.get('network_id') is not None: new_object_params['networkId'] = self.new_object.get('networkId') or \ self.new_object.get('network_id') @@ -129,9 +139,11 @@ class NetworksSwitchSettings(object): requested_obj = self.new_object obj_params = [ - ("vlan", "vlan"), - ("useCombinedPower", "useCombinedPower"), + ("macBlocklist", "macBlocklist"), ("powerExceptions", "powerExceptions"), + ("uplinkClientSampling", "uplinkClientSampling"), + ("useCombinedPower", "useCombinedPower"), + ("vlan", "vlan"), ("networkId", "networkId"), ] # Method 1. Params present in request (Ansible) obj are the same as the current (ISE) params diff --git a/ansible_collections/cisco/meraki/plugins/action/networks_switch_stacks_routing_interfaces.py b/ansible_collections/cisco/meraki/plugins/action/networks_switch_stacks_routing_interfaces.py index 948b77458..e126bce26 100644 --- a/ansible_collections/cisco/meraki/plugins/action/networks_switch_stacks_routing_interfaces.py +++ b/ansible_collections/cisco/meraki/plugins/action/networks_switch_stacks_routing_interfaces.py @@ -32,14 +32,14 @@ argument_spec = meraki_argument_spec() # Add arguments specific for this module argument_spec.update(dict( state=dict(type="str", default="present", choices=["present", "absent"]), - name=dict(type="str"), - subnet=dict(type="str"), + defaultGateway=dict(type="str"), interfaceIp=dict(type="str"), + ipv6=dict(type="dict"), multicastRouting=dict(type="str"), - vlanId=dict(type="int"), - defaultGateway=dict(type="str"), + name=dict(type="str"), ospfSettings=dict(type="dict"), - ipv6=dict(type="dict"), + subnet=dict(type="str"), + vlanId=dict(type="int"), networkId=dict(type="str"), switchStackId=dict(type="str"), interfaceId=dict(type="str"), @@ -58,14 +58,14 @@ class NetworksSwitchStacksRoutingInterfaces(object): def __init__(self, params, meraki): self.meraki = meraki self.new_object = dict( - name=params.get("name"), - subnet=params.get("subnet"), + defaultGateway=params.get("defaultGateway"), interfaceIp=params.get("interfaceIp"), + ipv6=params.get("ipv6"), multicastRouting=params.get("multicastRouting"), - vlanId=params.get("vlanId"), - defaultGateway=params.get("defaultGateway"), + name=params.get("name"), ospfSettings=params.get("ospfSettings"), - ipv6=params.get("ipv6"), + subnet=params.get("subnet"), + vlanId=params.get("vlanId"), networkId=params.get("networkId"), switchStackId=params.get("switchStackId"), interfaceId=params.get("interfaceId"), @@ -96,30 +96,30 @@ class NetworksSwitchStacksRoutingInterfaces(object): def create_params(self): new_object_params = {} - if self.new_object.get('name') is not None or self.new_object.get('name') is not None: - new_object_params['name'] = self.new_object.get('name') or \ - self.new_object.get('name') - if self.new_object.get('subnet') is not None or self.new_object.get('subnet') is not None: - new_object_params['subnet'] = self.new_object.get('subnet') or \ - self.new_object.get('subnet') + if self.new_object.get('defaultGateway') is not None or self.new_object.get('default_gateway') is not None: + new_object_params['defaultGateway'] = self.new_object.get('defaultGateway') or \ + self.new_object.get('default_gateway') if self.new_object.get('interfaceIp') is not None or self.new_object.get('interface_ip') is not None: new_object_params['interfaceIp'] = self.new_object.get('interfaceIp') or \ self.new_object.get('interface_ip') + if self.new_object.get('ipv6') is not None or self.new_object.get('ipv6') is not None: + new_object_params['ipv6'] = self.new_object.get('ipv6') or \ + self.new_object.get('ipv6') if self.new_object.get('multicastRouting') is not None or self.new_object.get('multicast_routing') is not None: new_object_params['multicastRouting'] = self.new_object.get('multicastRouting') or \ self.new_object.get('multicast_routing') - if self.new_object.get('vlanId') is not None or self.new_object.get('vlan_id') is not None: - new_object_params['vlanId'] = self.new_object.get('vlanId') or \ - self.new_object.get('vlan_id') - if self.new_object.get('defaultGateway') is not None or self.new_object.get('default_gateway') is not None: - new_object_params['defaultGateway'] = self.new_object.get('defaultGateway') or \ - self.new_object.get('default_gateway') + if self.new_object.get('name') is not None or self.new_object.get('name') is not None: + new_object_params['name'] = self.new_object.get('name') or \ + self.new_object.get('name') if self.new_object.get('ospfSettings') is not None or self.new_object.get('ospf_settings') is not None: new_object_params['ospfSettings'] = self.new_object.get('ospfSettings') or \ self.new_object.get('ospf_settings') - if self.new_object.get('ipv6') is not None or self.new_object.get('ipv6') is not None: - new_object_params['ipv6'] = self.new_object.get('ipv6') or \ - self.new_object.get('ipv6') + if self.new_object.get('subnet') is not None or self.new_object.get('subnet') is not None: + new_object_params['subnet'] = self.new_object.get('subnet') or \ + self.new_object.get('subnet') + if self.new_object.get('vlanId') is not None or self.new_object.get('vlan_id') is not None: + new_object_params['vlanId'] = self.new_object.get('vlanId') or \ + self.new_object.get('vlan_id') if self.new_object.get('networkId') is not None or self.new_object.get('network_id') is not None: new_object_params['networkId'] = self.new_object.get('networkId') or \ self.new_object.get('network_id') @@ -143,30 +143,30 @@ class NetworksSwitchStacksRoutingInterfaces(object): def update_by_id_params(self): new_object_params = {} - if self.new_object.get('name') is not None or self.new_object.get('name') is not None: - new_object_params['name'] = self.new_object.get('name') or \ - self.new_object.get('name') - if self.new_object.get('subnet') is not None or self.new_object.get('subnet') is not None: - new_object_params['subnet'] = self.new_object.get('subnet') or \ - self.new_object.get('subnet') + if self.new_object.get('defaultGateway') is not None or self.new_object.get('default_gateway') is not None: + new_object_params['defaultGateway'] = self.new_object.get('defaultGateway') or \ + self.new_object.get('default_gateway') if self.new_object.get('interfaceIp') is not None or self.new_object.get('interface_ip') is not None: new_object_params['interfaceIp'] = self.new_object.get('interfaceIp') or \ self.new_object.get('interface_ip') + if self.new_object.get('ipv6') is not None or self.new_object.get('ipv6') is not None: + new_object_params['ipv6'] = self.new_object.get('ipv6') or \ + self.new_object.get('ipv6') if self.new_object.get('multicastRouting') is not None or self.new_object.get('multicast_routing') is not None: new_object_params['multicastRouting'] = self.new_object.get('multicastRouting') or \ self.new_object.get('multicast_routing') - if self.new_object.get('vlanId') is not None or self.new_object.get('vlan_id') is not None: - new_object_params['vlanId'] = self.new_object.get('vlanId') or \ - self.new_object.get('vlan_id') - if self.new_object.get('defaultGateway') is not None or self.new_object.get('default_gateway') is not None: - new_object_params['defaultGateway'] = self.new_object.get('defaultGateway') or \ - self.new_object.get('default_gateway') + if self.new_object.get('name') is not None or self.new_object.get('name') is not None: + new_object_params['name'] = self.new_object.get('name') or \ + self.new_object.get('name') if self.new_object.get('ospfSettings') is not None or self.new_object.get('ospf_settings') is not None: new_object_params['ospfSettings'] = self.new_object.get('ospfSettings') or \ self.new_object.get('ospf_settings') - if self.new_object.get('ipv6') is not None or self.new_object.get('ipv6') is not None: - new_object_params['ipv6'] = self.new_object.get('ipv6') or \ - self.new_object.get('ipv6') + if self.new_object.get('subnet') is not None or self.new_object.get('subnet') is not None: + new_object_params['subnet'] = self.new_object.get('subnet') or \ + self.new_object.get('subnet') + if self.new_object.get('vlanId') is not None or self.new_object.get('vlan_id') is not None: + new_object_params['vlanId'] = self.new_object.get('vlanId') or \ + self.new_object.get('vlan_id') if self.new_object.get('networkId') is not None or self.new_object.get('network_id') is not None: new_object_params['networkId'] = self.new_object.get('networkId') or \ self.new_object.get('network_id') @@ -247,14 +247,14 @@ class NetworksSwitchStacksRoutingInterfaces(object): requested_obj = self.new_object obj_params = [ - ("name", "name"), - ("subnet", "subnet"), + ("defaultGateway", "defaultGateway"), ("interfaceIp", "interfaceIp"), + ("ipv6", "ipv6"), ("multicastRouting", "multicastRouting"), - ("vlanId", "vlanId"), - ("defaultGateway", "defaultGateway"), + ("name", "name"), ("ospfSettings", "ospfSettings"), - ("ipv6", "ipv6"), + ("subnet", "subnet"), + ("vlanId", "vlanId"), ("networkId", "networkId"), ("switchStackId", "switchStackId"), ("interfaceId", "interfaceId"), diff --git a/ansible_collections/cisco/meraki/plugins/action/networks_switch_stacks_routing_interfaces_dhcp.py b/ansible_collections/cisco/meraki/plugins/action/networks_switch_stacks_routing_interfaces_dhcp.py index 0127666a5..e1addc98e 100644 --- a/ansible_collections/cisco/meraki/plugins/action/networks_switch_stacks_routing_interfaces_dhcp.py +++ b/ansible_collections/cisco/meraki/plugins/action/networks_switch_stacks_routing_interfaces_dhcp.py @@ -32,17 +32,17 @@ argument_spec = meraki_argument_spec() # Add arguments specific for this module argument_spec.update(dict( state=dict(type="str", default="present", choices=["present"]), + bootFileName=dict(type="str"), + bootNextServer=dict(type="str"), + bootOptionsEnabled=dict(type="bool"), + dhcpLeaseTime=dict(type="str"), dhcpMode=dict(type="str"), + dhcpOptions=dict(type="list"), dhcpRelayServerIps=dict(type="list"), - dhcpLeaseTime=dict(type="str"), - dnsNameserversOption=dict(type="str"), dnsCustomNameservers=dict(type="list"), - bootOptionsEnabled=dict(type="bool"), - bootNextServer=dict(type="str"), - bootFileName=dict(type="str"), - dhcpOptions=dict(type="list"), - reservedIpRanges=dict(type="list"), + dnsNameserversOption=dict(type="str"), fixedIpAssignments=dict(type="list"), + reservedIpRanges=dict(type="list"), networkId=dict(type="str"), switchStackId=dict(type="str"), interfaceId=dict(type="str"), @@ -60,17 +60,17 @@ class NetworksSwitchStacksRoutingInterfacesDhcp(object): def __init__(self, params, meraki): self.meraki = meraki self.new_object = dict( + bootFileName=params.get("bootFileName"), + bootNextServer=params.get("bootNextServer"), + bootOptionsEnabled=params.get("bootOptionsEnabled"), + dhcpLeaseTime=params.get("dhcpLeaseTime"), dhcpMode=params.get("dhcpMode"), + dhcpOptions=params.get("dhcpOptions"), dhcpRelayServerIps=params.get("dhcpRelayServerIps"), - dhcpLeaseTime=params.get("dhcpLeaseTime"), - dnsNameserversOption=params.get("dnsNameserversOption"), dnsCustomNameservers=params.get("dnsCustomNameservers"), - bootOptionsEnabled=params.get("bootOptionsEnabled"), - bootNextServer=params.get("bootNextServer"), - bootFileName=params.get("bootFileName"), - dhcpOptions=params.get("dhcpOptions"), - reservedIpRanges=params.get("reservedIpRanges"), + dnsNameserversOption=params.get("dnsNameserversOption"), fixedIpAssignments=params.get("fixedIpAssignments"), + reservedIpRanges=params.get("reservedIpRanges"), network_id=params.get("networkId"), switch_stack_id=params.get("switchStackId"), interface_id=params.get("interfaceId"), @@ -91,38 +91,38 @@ class NetworksSwitchStacksRoutingInterfacesDhcp(object): def update_all_params(self): new_object_params = {} + if self.new_object.get('bootFileName') is not None or self.new_object.get('boot_file_name') is not None: + new_object_params['bootFileName'] = self.new_object.get('bootFileName') or \ + self.new_object.get('boot_file_name') + if self.new_object.get('bootNextServer') is not None or self.new_object.get('boot_next_server') is not None: + new_object_params['bootNextServer'] = self.new_object.get('bootNextServer') or \ + self.new_object.get('boot_next_server') + if self.new_object.get('bootOptionsEnabled') is not None or self.new_object.get('boot_options_enabled') is not None: + new_object_params['bootOptionsEnabled'] = self.new_object.get('bootOptionsEnabled') + if self.new_object.get('dhcpLeaseTime') is not None or self.new_object.get('dhcp_lease_time') is not None: + new_object_params['dhcpLeaseTime'] = self.new_object.get('dhcpLeaseTime') or \ + self.new_object.get('dhcp_lease_time') if self.new_object.get('dhcpMode') is not None or self.new_object.get('dhcp_mode') is not None: new_object_params['dhcpMode'] = self.new_object.get('dhcpMode') or \ self.new_object.get('dhcp_mode') + if self.new_object.get('dhcpOptions') is not None or self.new_object.get('dhcp_options') is not None: + new_object_params['dhcpOptions'] = self.new_object.get('dhcpOptions') or \ + self.new_object.get('dhcp_options') if self.new_object.get('dhcpRelayServerIps') is not None or self.new_object.get('dhcp_relay_server_ips') is not None: new_object_params['dhcpRelayServerIps'] = self.new_object.get('dhcpRelayServerIps') or \ self.new_object.get('dhcp_relay_server_ips') - if self.new_object.get('dhcpLeaseTime') is not None or self.new_object.get('dhcp_lease_time') is not None: - new_object_params['dhcpLeaseTime'] = self.new_object.get('dhcpLeaseTime') or \ - self.new_object.get('dhcp_lease_time') - if self.new_object.get('dnsNameserversOption') is not None or self.new_object.get('dns_nameservers_option') is not None: - new_object_params['dnsNameserversOption'] = self.new_object.get('dnsNameserversOption') or \ - self.new_object.get('dns_nameservers_option') if self.new_object.get('dnsCustomNameservers') is not None or self.new_object.get('dns_custom_nameservers') is not None: new_object_params['dnsCustomNameservers'] = self.new_object.get('dnsCustomNameservers') or \ self.new_object.get('dns_custom_nameservers') - if self.new_object.get('bootOptionsEnabled') is not None or self.new_object.get('boot_options_enabled') is not None: - new_object_params['bootOptionsEnabled'] = self.new_object.get('bootOptionsEnabled') - if self.new_object.get('bootNextServer') is not None or self.new_object.get('boot_next_server') is not None: - new_object_params['bootNextServer'] = self.new_object.get('bootNextServer') or \ - self.new_object.get('boot_next_server') - if self.new_object.get('bootFileName') is not None or self.new_object.get('boot_file_name') is not None: - new_object_params['bootFileName'] = self.new_object.get('bootFileName') or \ - self.new_object.get('boot_file_name') - if self.new_object.get('dhcpOptions') is not None or self.new_object.get('dhcp_options') is not None: - new_object_params['dhcpOptions'] = self.new_object.get('dhcpOptions') or \ - self.new_object.get('dhcp_options') - if self.new_object.get('reservedIpRanges') is not None or self.new_object.get('reserved_ip_ranges') is not None: - new_object_params['reservedIpRanges'] = self.new_object.get('reservedIpRanges') or \ - self.new_object.get('reserved_ip_ranges') + if self.new_object.get('dnsNameserversOption') is not None or self.new_object.get('dns_nameservers_option') is not None: + new_object_params['dnsNameserversOption'] = self.new_object.get('dnsNameserversOption') or \ + self.new_object.get('dns_nameservers_option') if self.new_object.get('fixedIpAssignments') is not None or self.new_object.get('fixed_ip_assignments') is not None: new_object_params['fixedIpAssignments'] = self.new_object.get('fixedIpAssignments') or \ self.new_object.get('fixed_ip_assignments') + if self.new_object.get('reservedIpRanges') is not None or self.new_object.get('reserved_ip_ranges') is not None: + new_object_params['reservedIpRanges'] = self.new_object.get('reservedIpRanges') or \ + self.new_object.get('reserved_ip_ranges') if self.new_object.get('networkId') is not None or self.new_object.get('network_id') is not None: new_object_params['networkId'] = self.new_object.get('networkId') or \ self.new_object.get('network_id') @@ -185,17 +185,17 @@ class NetworksSwitchStacksRoutingInterfacesDhcp(object): requested_obj = self.new_object obj_params = [ + ("bootFileName", "bootFileName"), + ("bootNextServer", "bootNextServer"), + ("bootOptionsEnabled", "bootOptionsEnabled"), + ("dhcpLeaseTime", "dhcpLeaseTime"), ("dhcpMode", "dhcpMode"), + ("dhcpOptions", "dhcpOptions"), ("dhcpRelayServerIps", "dhcpRelayServerIps"), - ("dhcpLeaseTime", "dhcpLeaseTime"), - ("dnsNameserversOption", "dnsNameserversOption"), ("dnsCustomNameservers", "dnsCustomNameservers"), - ("bootOptionsEnabled", "bootOptionsEnabled"), - ("bootNextServer", "bootNextServer"), - ("bootFileName", "bootFileName"), - ("dhcpOptions", "dhcpOptions"), - ("reservedIpRanges", "reservedIpRanges"), + ("dnsNameserversOption", "dnsNameserversOption"), ("fixedIpAssignments", "fixedIpAssignments"), + ("reservedIpRanges", "reservedIpRanges"), ("networkId", "networkId"), ("switchStackId", "switchStackId"), ("interfaceId", "interfaceId"), diff --git a/ansible_collections/cisco/meraki/plugins/action/networks_switch_stacks_routing_static_routes.py b/ansible_collections/cisco/meraki/plugins/action/networks_switch_stacks_routing_static_routes.py index 1ac473570..88d04e931 100644 --- a/ansible_collections/cisco/meraki/plugins/action/networks_switch_stacks_routing_static_routes.py +++ b/ansible_collections/cisco/meraki/plugins/action/networks_switch_stacks_routing_static_routes.py @@ -32,11 +32,11 @@ argument_spec = meraki_argument_spec() # Add arguments specific for this module argument_spec.update(dict( state=dict(type="str", default="present", choices=["present", "absent"]), + advertiseViaOspfEnabled=dict(type="bool"), name=dict(type="str"), - subnet=dict(type="str"), nextHopIp=dict(type="str"), - advertiseViaOspfEnabled=dict(type="bool"), preferOverOspfRoutesEnabled=dict(type="bool"), + subnet=dict(type="str"), networkId=dict(type="str"), switchStackId=dict(type="str"), staticRouteId=dict(type="str"), @@ -55,11 +55,11 @@ class NetworksSwitchStacksRoutingStaticRoutes(object): def __init__(self, params, meraki): self.meraki = meraki self.new_object = dict( + advertiseViaOspfEnabled=params.get("advertiseViaOspfEnabled"), name=params.get("name"), - subnet=params.get("subnet"), nextHopIp=params.get("nextHopIp"), - advertiseViaOspfEnabled=params.get("advertiseViaOspfEnabled"), preferOverOspfRoutesEnabled=params.get("preferOverOspfRoutesEnabled"), + subnet=params.get("subnet"), networkId=params.get("networkId"), switchStackId=params.get("switchStackId"), staticRouteId=params.get("staticRouteId"), @@ -90,19 +90,19 @@ class NetworksSwitchStacksRoutingStaticRoutes(object): def create_params(self): new_object_params = {} + if self.new_object.get('advertiseViaOspfEnabled') is not None or self.new_object.get('advertise_via_ospf_enabled') is not None: + new_object_params['advertiseViaOspfEnabled'] = self.new_object.get('advertiseViaOspfEnabled') if self.new_object.get('name') is not None or self.new_object.get('name') is not None: new_object_params['name'] = self.new_object.get('name') or \ self.new_object.get('name') - if self.new_object.get('subnet') is not None or self.new_object.get('subnet') is not None: - new_object_params['subnet'] = self.new_object.get('subnet') or \ - self.new_object.get('subnet') if self.new_object.get('nextHopIp') is not None or self.new_object.get('next_hop_ip') is not None: new_object_params['nextHopIp'] = self.new_object.get('nextHopIp') or \ self.new_object.get('next_hop_ip') - if self.new_object.get('advertiseViaOspfEnabled') is not None or self.new_object.get('advertise_via_ospf_enabled') is not None: - new_object_params['advertiseViaOspfEnabled'] = self.new_object.get('advertiseViaOspfEnabled') if self.new_object.get('preferOverOspfRoutesEnabled') is not None or self.new_object.get('prefer_over_ospf_routes_enabled') is not None: new_object_params['preferOverOspfRoutesEnabled'] = self.new_object.get('preferOverOspfRoutesEnabled') + if self.new_object.get('subnet') is not None or self.new_object.get('subnet') is not None: + new_object_params['subnet'] = self.new_object.get('subnet') or \ + self.new_object.get('subnet') if self.new_object.get('networkId') is not None or self.new_object.get('network_id') is not None: new_object_params['networkId'] = self.new_object.get('networkId') or \ self.new_object.get('network_id') @@ -126,19 +126,19 @@ class NetworksSwitchStacksRoutingStaticRoutes(object): def update_by_id_params(self): new_object_params = {} + if self.new_object.get('advertiseViaOspfEnabled') is not None or self.new_object.get('advertise_via_ospf_enabled') is not None: + new_object_params['advertiseViaOspfEnabled'] = self.new_object.get('advertiseViaOspfEnabled') if self.new_object.get('name') is not None or self.new_object.get('name') is not None: new_object_params['name'] = self.new_object.get('name') or \ self.new_object.get('name') - if self.new_object.get('subnet') is not None or self.new_object.get('subnet') is not None: - new_object_params['subnet'] = self.new_object.get('subnet') or \ - self.new_object.get('subnet') if self.new_object.get('nextHopIp') is not None or self.new_object.get('next_hop_ip') is not None: new_object_params['nextHopIp'] = self.new_object.get('nextHopIp') or \ self.new_object.get('next_hop_ip') - if self.new_object.get('advertiseViaOspfEnabled') is not None or self.new_object.get('advertise_via_ospf_enabled') is not None: - new_object_params['advertiseViaOspfEnabled'] = self.new_object.get('advertiseViaOspfEnabled') if self.new_object.get('preferOverOspfRoutesEnabled') is not None or self.new_object.get('prefer_over_ospf_routes_enabled') is not None: new_object_params['preferOverOspfRoutesEnabled'] = self.new_object.get('preferOverOspfRoutesEnabled') + if self.new_object.get('subnet') is not None or self.new_object.get('subnet') is not None: + new_object_params['subnet'] = self.new_object.get('subnet') or \ + self.new_object.get('subnet') if self.new_object.get('networkId') is not None or self.new_object.get('network_id') is not None: new_object_params['networkId'] = self.new_object.get('networkId') or \ self.new_object.get('network_id') @@ -219,11 +219,11 @@ class NetworksSwitchStacksRoutingStaticRoutes(object): requested_obj = self.new_object obj_params = [ + ("advertiseViaOspfEnabled", "advertiseViaOspfEnabled"), ("name", "name"), - ("subnet", "subnet"), ("nextHopIp", "nextHopIp"), - ("advertiseViaOspfEnabled", "advertiseViaOspfEnabled"), ("preferOverOspfRoutesEnabled", "preferOverOspfRoutesEnabled"), + ("subnet", "subnet"), ("networkId", "networkId"), ("switchStackId", "switchStackId"), ("staticRouteId", "staticRouteId"), diff --git a/ansible_collections/cisco/meraki/plugins/action/networks_traffic_analysis.py b/ansible_collections/cisco/meraki/plugins/action/networks_traffic_analysis.py index eb815e34c..3a0362321 100644 --- a/ansible_collections/cisco/meraki/plugins/action/networks_traffic_analysis.py +++ b/ansible_collections/cisco/meraki/plugins/action/networks_traffic_analysis.py @@ -32,8 +32,8 @@ argument_spec = meraki_argument_spec() # Add arguments specific for this module argument_spec.update(dict( state=dict(type="str", default="present", choices=["present"]), - mode=dict(type="str"), customPieChartItems=dict(type="list"), + mode=dict(type="str"), networkId=dict(type="str"), )) @@ -49,8 +49,8 @@ class NetworksTrafficAnalysis(object): def __init__(self, params, meraki): self.meraki = meraki self.new_object = dict( - mode=params.get("mode"), customPieChartItems=params.get("customPieChartItems"), + mode=params.get("mode"), network_id=params.get("networkId"), ) @@ -63,12 +63,12 @@ class NetworksTrafficAnalysis(object): def update_all_params(self): new_object_params = {} - if self.new_object.get('mode') is not None or self.new_object.get('mode') is not None: - new_object_params['mode'] = self.new_object.get('mode') or \ - self.new_object.get('mode') if self.new_object.get('customPieChartItems') is not None or self.new_object.get('custom_pie_chart_items') is not None: new_object_params['customPieChartItems'] = self.new_object.get('customPieChartItems') or \ self.new_object.get('custom_pie_chart_items') + if self.new_object.get('mode') is not None or self.new_object.get('mode') is not None: + new_object_params['mode'] = self.new_object.get('mode') or \ + self.new_object.get('mode') if self.new_object.get('networkId') is not None or self.new_object.get('network_id') is not None: new_object_params['networkId'] = self.new_object.get('networkId') or \ self.new_object.get('network_id') @@ -125,8 +125,8 @@ class NetworksTrafficAnalysis(object): requested_obj = self.new_object obj_params = [ - ("mode", "mode"), ("customPieChartItems", "customPieChartItems"), + ("mode", "mode"), ("networkId", "networkId"), ] # Method 1. Params present in request (Ansible) obj are the same as the current (ISE) params diff --git a/ansible_collections/cisco/meraki/plugins/action/networks_vlan_profiles.py b/ansible_collections/cisco/meraki/plugins/action/networks_vlan_profiles.py new file mode 100644 index 000000000..c92346bea --- /dev/null +++ b/ansible_collections/cisco/meraki/plugins/action/networks_vlan_profiles.py @@ -0,0 +1,260 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +# Copyright (c) 2021, Cisco Systems +# 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 +from ansible.plugins.action import ActionBase +try: + from ansible_collections.ansible.utils.plugins.module_utils.common.argspec_validate import ( + AnsibleArgSpecValidator, + ) +except ImportError: + ANSIBLE_UTILS_IS_INSTALLED = False +else: + ANSIBLE_UTILS_IS_INSTALLED = True +from ansible.errors import AnsibleActionFail +from ansible_collections.cisco.meraki.plugins.plugin_utils.meraki import ( + MERAKI, + meraki_argument_spec, + meraki_compare_equality, + get_dict_result, +) +from ansible_collections.cisco.meraki.plugins.plugin_utils.exceptions import ( + InconsistentParameters, +) + +# Get common arguments specification +argument_spec = meraki_argument_spec() +# Add arguments specific for this module +argument_spec.update(dict( + state=dict(type="str", default="present", choices=["present", "absent"]), + name=dict(type="str"), + vlanGroups=dict(type="list"), + vlanNames=dict(type="list"), + networkId=dict(type="str"), + iname=dict(type="str"), +)) + +required_if = [ + ("state", "present", ["iname", "name", "networkId"], True), + ("state", "absent", ["iname", "name", "networkId"], True), +] +required_one_of = [] +mutually_exclusive = [] +required_together = [] + + +class NetworksVlanProfiles(object): + def __init__(self, params, meraki): + self.meraki = meraki + self.new_object = dict( + name=params.get("name"), + vlanGroups=params.get("vlanGroups"), + vlanNames=params.get("vlanNames"), + network_id=params.get("networkId"), + iname=params.get("iname"), + ) + + def delete_by_name_params(self): + new_object_params = {} + if self.new_object.get('networkId') is not None or self.new_object.get('network_id') is not None: + new_object_params['networkId'] = self.new_object.get('networkId') or \ + self.new_object.get('network_id') + if self.new_object.get('iname') is not None or self.new_object.get('iname') is not None: + new_object_params['iname'] = self.new_object.get('iname') or \ + self.new_object.get('iname') + return new_object_params + + def update_by_name_params(self): + new_object_params = {} + if self.new_object.get('name') is not None or self.new_object.get('name') is not None: + new_object_params['name'] = self.new_object.get('name') or \ + self.new_object.get('name') + if self.new_object.get('vlanGroups') is not None or self.new_object.get('vlan_groups') is not None: + new_object_params['vlanGroups'] = self.new_object.get('vlanGroups') or \ + self.new_object.get('vlan_groups') + if self.new_object.get('vlanNames') is not None or self.new_object.get('vlan_names') is not None: + new_object_params['vlanNames'] = self.new_object.get('vlanNames') or \ + self.new_object.get('vlan_names') + if self.new_object.get('networkId') is not None or self.new_object.get('network_id') is not None: + new_object_params['networkId'] = self.new_object.get('networkId') or \ + self.new_object.get('network_id') + if self.new_object.get('iname') is not None or self.new_object.get('iname') is not None: + new_object_params['iname'] = self.new_object.get('iname') or \ + self.new_object.get('iname') + return new_object_params + + def get_object_by_name(self, name): + result = None + try: + items = self.meraki.exec_meraki( + family="networks", + function="getNetworkVlanProfile", + params={"iname": name} + ) + if isinstance(items, dict): + if 'response' in items: + items = items.get('response') + result = get_dict_result(items, 'iname', name) + except Exception: + result = None + return result + + def get_object_by_id(self, id): + result = None + # NOTE: Does not have a get by id method or it is in another action + return result + + def exists(self): + prev_obj = None + id_exists = False + name_exists = False + o_id = self.new_object.get("networkId") or self.new_object.get("network_id") + name = self.new_object.get("name") + name = name or self.new_object.get("iname") + if o_id: + prev_obj = self.get_object_by_name(o_id) + id_exists = prev_obj is not None and isinstance(prev_obj, dict) + if not id_exists and name: + prev_obj = self.get_object_by_name(name) + name_exists = prev_obj is not None and isinstance(prev_obj, dict) + if id_exists: + _name = prev_obj.get("name") + _name = _name or prev_obj.get("iname") + if _name: + self.new_object.update(dict(iname=_name)) + if name_exists: + _id = prev_obj.get("id") + if id_exists and name_exists and o_id != _id: + raise InconsistentParameters( + "The 'id' and 'name' params don't refer to the same object") + if _id: + self.new_object.update(dict(id=_id)) + it_exists = prev_obj is not None and isinstance(prev_obj, dict) + return (it_exists, prev_obj) + + def requires_update(self, current_obj): + requested_obj = self.new_object + + obj_params = [ + ("name", "name"), + ("vlanGroups", "vlanGroups"), + ("vlanNames", "vlanNames"), + ("networkId", "networkId"), + ("iname", "iname"), + ] + # Method 1. Params present in request (Ansible) obj are the same as the current (ISE) params + # If any does not have eq params, it requires update + return any(not meraki_compare_equality(current_obj.get(meraki_param), + requested_obj.get(ansible_param)) + for (meraki_param, ansible_param) in obj_params) + + def update(self): + id = self.new_object.get("id") + name = self.new_object.get("name") + name = name or self.new_object.get("iname") + result = None + if not name: + prev_obj_id = self.get_object_by_id(id) + name_ = None + if prev_obj_id: + name_ = prev_obj_id.get("name") + name_ = name_ or prev_obj_id.get("iname") + if name_: + self.new_object.update(dict(iname=name_)) + result = self.meraki.exec_meraki( + family="networks", + function="updateNetworkVlanProfile", + params=self.update_by_name_params(), + op_modifies=True, + ) + return result + + def delete(self): + id = self.new_object.get("id") + name = self.new_object.get("name") + name = name or self.new_object.get("iname") + result = None + if not name: + prev_obj_id = self.get_object_by_id(id) + name_ = None + if prev_obj_id: + name_ = prev_obj_id.get("name") + name_ = name_ or prev_obj_id.get("iname") + if name_: + self.new_object.update(dict(iname=name_)) + result = self.meraki.exec_meraki( + family="networks", + function="deleteNetworkVlanProfile", + params=self.delete_by_name_params(), + ) + return result + + +class ActionModule(ActionBase): + def __init__(self, *args, **kwargs): + if not ANSIBLE_UTILS_IS_INSTALLED: + raise AnsibleActionFail( + "ansible.utils is not installed. Execute 'ansible-galaxy collection install ansible.utils'") + super(ActionModule, self).__init__(*args, **kwargs) + self._supports_async = False + self._supports_check_mode = False + self._result = None + + # Checks the supplied parameters against the argument spec for this module + def _check_argspec(self): + aav = AnsibleArgSpecValidator( + data=self._task.args, + schema=dict(argument_spec=argument_spec), + schema_format="argspec", + schema_conditionals=dict( + required_if=required_if, + required_one_of=required_one_of, + mutually_exclusive=mutually_exclusive, + required_together=required_together, + ), + name=self._task.action, + ) + valid, errors, self._task.args = aav.validate() + if not valid: + raise AnsibleActionFail(errors) + + def run(self, tmp=None, task_vars=None): + self._task.diff = False + self._result = super(ActionModule, self).run(tmp, task_vars) + self._result["changed"] = False + self._check_argspec() + + meraki = MERAKI(self._task.args) + obj = NetworksVlanProfiles(self._task.args, meraki) + + state = self._task.args.get("state") + + response = None + if state == "present": + (obj_exists, prev_obj) = obj.exists() + if obj_exists: + if obj.requires_update(prev_obj): + response = obj.update() + meraki.object_updated() + else: + response = prev_obj + meraki.object_already_present() + else: + meraki.fail_json( + "Object does not exists, plugin only has update") + elif state == "absent": + (obj_exists, prev_obj) = obj.exists() + if obj_exists: + response = obj.delete() + meraki.object_deleted() + else: + meraki.object_already_absent() + + self._result.update(dict(meraki_response=response)) + self._result.update(meraki.exit_json()) + return self._result diff --git a/ansible_collections/cisco/meraki/plugins/action/networks_vlan_profiles_assignments_by_device_info.py b/ansible_collections/cisco/meraki/plugins/action/networks_vlan_profiles_assignments_by_device_info.py new file mode 100644 index 000000000..2e386c0ab --- /dev/null +++ b/ansible_collections/cisco/meraki/plugins/action/networks_vlan_profiles_assignments_by_device_info.py @@ -0,0 +1,120 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +# Copyright (c) 2021, Cisco Systems +# 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 +from ansible.plugins.action import ActionBase +try: + from ansible_collections.ansible.utils.plugins.module_utils.common.argspec_validate import ( + AnsibleArgSpecValidator, + ) +except ImportError: + ANSIBLE_UTILS_IS_INSTALLED = False +else: + ANSIBLE_UTILS_IS_INSTALLED = True +from ansible.errors import AnsibleActionFail +from ansible_collections.cisco.meraki.plugins.plugin_utils.meraki import ( + MERAKI, + meraki_argument_spec, +) + +# Get common arguments specification +argument_spec = meraki_argument_spec() +# Add arguments specific for this module +argument_spec.update(dict( + networkId=dict(type="str"), + perPage=dict(type="int"), + total_pages=dict(type="int"), + direction=dict(type="str"), + startingAfter=dict(type="str"), + endingBefore=dict(type="str"), + serials=dict(type="list"), + productTypes=dict(type="list"), + stackIds=dict(type="list"), +)) + +required_if = [] +required_one_of = [] +mutually_exclusive = [] +required_together = [] + + +class ActionModule(ActionBase): + def __init__(self, *args, **kwargs): + if not ANSIBLE_UTILS_IS_INSTALLED: + raise AnsibleActionFail( + "ansible.utils is not installed. Execute 'ansible-galaxy collection install ansible.utils'") + super(ActionModule, self).__init__(*args, **kwargs) + self._supports_async = False + self._supports_check_mode = True + self._result = None + + # Checks the supplied parameters against the argument spec for this module + def _check_argspec(self): + aav = AnsibleArgSpecValidator( + data=self._task.args, + schema=dict(argument_spec=argument_spec), + schema_format="argspec", + schema_conditionals=dict( + required_if=required_if, + required_one_of=required_one_of, + mutually_exclusive=mutually_exclusive, + required_together=required_together, + ), + name=self._task.action, + ) + valid, errors, self._task.args = aav.validate() + if not valid: + raise AnsibleActionFail(errors) + + def get_all(self, params): + new_object = {} + if params.get("networkId") is not None: + new_object["networkId"] = params.get( + "networkId") + if params.get("perPage") is not None: + new_object["perPage"] = params.get( + "perPage") + new_object['total_pages'] = params.get( + "total_pages") or 1 + new_object['direction'] = params.get( + "direction") or "next" + if params.get("startingAfter") is not None: + new_object["startingAfter"] = params.get( + "startingAfter") + if params.get("endingBefore") is not None: + new_object["endingBefore"] = params.get( + "endingBefore") + if params.get("serials") is not None: + new_object["serials"] = params.get( + "serials") + if params.get("productTypes") is not None: + new_object["productTypes"] = params.get( + "productTypes") + if params.get("stackIds") is not None: + new_object["stackIds"] = params.get( + "stackIds") + + return new_object + + def run(self, tmp=None, task_vars=None): + self._task.diff = False + self._result = super(ActionModule, self).run(tmp, task_vars) + self._result["changed"] = False + self._check_argspec() + + self._result.update(dict(meraki_response={})) + + meraki = MERAKI(params=self._task.args) + + response = meraki.exec_meraki( + family="networks", + function='getNetworkVlanProfilesAssignmentsByDevice', + params=self.get_all(self._task.args), + ) + self._result.update(dict(meraki_response=response)) + self._result.update(meraki.exit_json()) + return self._result diff --git a/ansible_collections/cisco/meraki/plugins/action/networks_vlan_profiles_assignments_reassign.py b/ansible_collections/cisco/meraki/plugins/action/networks_vlan_profiles_assignments_reassign.py new file mode 100644 index 000000000..96cb0a3a1 --- /dev/null +++ b/ansible_collections/cisco/meraki/plugins/action/networks_vlan_profiles_assignments_reassign.py @@ -0,0 +1,93 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +# Copyright (c) 2021, Cisco Systems +# 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 +from ansible.plugins.action import ActionBase +try: + from ansible_collections.ansible.utils.plugins.module_utils.common.argspec_validate import ( + AnsibleArgSpecValidator, + ) +except ImportError: + ANSIBLE_UTILS_IS_INSTALLED = False +else: + ANSIBLE_UTILS_IS_INSTALLED = True +from ansible.errors import AnsibleActionFail +from ansible_collections.cisco.meraki.plugins.plugin_utils.meraki import ( + MERAKI, + meraki_argument_spec, +) + +# Get common arguements specification +argument_spec = meraki_argument_spec() +# Add arguments specific for this module +argument_spec.update(dict( + serials=dict(type="list"), + stackIds=dict(type="list"), + vlanProfile=dict(type="dict"), + networkId=dict(type="str"), +)) + +required_if = [] +required_one_of = [] +mutually_exclusive = [] +required_together = [] + + +class ActionModule(ActionBase): + def __init__(self, *args, **kwargs): + if not ANSIBLE_UTILS_IS_INSTALLED: + raise AnsibleActionFail( + "ansible.utils is not installed. Execute 'ansible-galaxy collection install ansible.utils'") + super(ActionModule, self).__init__(*args, **kwargs) + self._supports_async = False + self._supports_check_mode = False + self._result = None + + # Checks the supplied parameters against the argument spec for this module + def _check_argspec(self): + aav = AnsibleArgSpecValidator( + data=self._task.args, + schema=dict(argument_spec=argument_spec), + schema_format="argspec", + schema_conditionals=dict( + required_if=required_if, + required_one_of=required_one_of, + mutually_exclusive=mutually_exclusive, + required_together=required_together, + ), + name=self._task.action, + ) + valid, errors, self._task.args = aav.validate() + if not valid: + raise AnsibleActionFail(errors) + + def get_object(self, params): + new_object = dict( + serials=params.get("serials"), + stackIds=params.get("stackIds"), + vlanProfile=params.get("vlanProfile"), + networkId=params.get("networkId"), + ) + return new_object + + def run(self, tmp=None, task_vars=None): + self._task.diff = False + self._result = super(ActionModule, self).run(tmp, task_vars) + self._result["changed"] = False + self._check_argspec() + + meraki = MERAKI(params=self._task.args) + + response = meraki.exec_meraki( + family="networks", + function='reassignNetworkVlanProfilesAssignments', + op_modifies=True, + params=self.get_object(self._task.args), + ) + self._result.update(dict(meraki_response=response)) + self._result.update(meraki.exit_json()) + return self._result diff --git a/ansible_collections/cisco/meraki/plugins/action/networks_vlan_profiles_info.py b/ansible_collections/cisco/meraki/plugins/action/networks_vlan_profiles_info.py new file mode 100644 index 000000000..74fa01c03 --- /dev/null +++ b/ansible_collections/cisco/meraki/plugins/action/networks_vlan_profiles_info.py @@ -0,0 +1,92 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +# Copyright (c) 2021, Cisco Systems +# 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 +from ansible.plugins.action import ActionBase +try: + from ansible_collections.ansible.utils.plugins.module_utils.common.argspec_validate import ( + AnsibleArgSpecValidator, + ) +except ImportError: + ANSIBLE_UTILS_IS_INSTALLED = False +else: + ANSIBLE_UTILS_IS_INSTALLED = True +from ansible.errors import AnsibleActionFail +from ansible_collections.cisco.meraki.plugins.plugin_utils.meraki import ( + MERAKI, + meraki_argument_spec, +) + +# Get common arguments specification +argument_spec = meraki_argument_spec() +# Add arguments specific for this module +argument_spec.update(dict( + networkId=dict(type="str"), + iname=dict(type="str"), +)) + +required_if = [] +required_one_of = [] +mutually_exclusive = [] +required_together = [] + + +class ActionModule(ActionBase): + def __init__(self, *args, **kwargs): + if not ANSIBLE_UTILS_IS_INSTALLED: + raise AnsibleActionFail( + "ansible.utils is not installed. Execute 'ansible-galaxy collection install ansible.utils'") + super(ActionModule, self).__init__(*args, **kwargs) + self._supports_async = False + self._supports_check_mode = True + self._result = None + + # Checks the supplied parameters against the argument spec for this module + def _check_argspec(self): + aav = AnsibleArgSpecValidator( + data=self._task.args, + schema=dict(argument_spec=argument_spec), + schema_format="argspec", + schema_conditionals=dict( + required_if=required_if, + required_one_of=required_one_of, + mutually_exclusive=mutually_exclusive, + required_together=required_together, + ), + name=self._task.action, + ) + valid, errors, self._task.args = aav.validate() + if not valid: + raise AnsibleActionFail(errors) + + def run(self, tmp=None, task_vars=None): + self._task.diff = False + self._result = super(ActionModule, self).run(tmp, task_vars) + self._result["changed"] = False + self._check_argspec() + + self._result.update(dict(meraki_response={})) + + meraki = MERAKI(params=self._task.args) + + name = self._task.args.get("iname") + if name: + response = meraki.exec_meraki( + family="networks", + function='getNetworkVlanProfile', + params=self.get_object(self._task.args), + ) + self._result.update(dict(meraki_response=response)) + self._result.update(meraki.exit_json()) + return self._result + if not name: + # NOTE: Does not have a get all method or it is in another action + response = None + meraki.object_modify_result(changed=False, result="Module does not have get all, check arguments of module") + self._result.update(dict(meraki_response=response)) + self._result.update(meraki.exit_json()) + return self._result diff --git a/ansible_collections/cisco/meraki/plugins/action/networks_webhooks_http_servers.py b/ansible_collections/cisco/meraki/plugins/action/networks_webhooks_http_servers.py index ef9a6d29d..a893960f6 100644 --- a/ansible_collections/cisco/meraki/plugins/action/networks_webhooks_http_servers.py +++ b/ansible_collections/cisco/meraki/plugins/action/networks_webhooks_http_servers.py @@ -33,9 +33,9 @@ argument_spec = meraki_argument_spec() argument_spec.update(dict( state=dict(type="str", default="present", choices=["present", "absent"]), name=dict(type="str"), - url=dict(type="str"), - sharedSecret=dict(type="str"), payloadTemplate=dict(type="dict"), + sharedSecret=dict(type="str"), + url=dict(type="str"), networkId=dict(type="str"), httpServerId=dict(type="str"), )) @@ -54,9 +54,9 @@ class NetworksWebhooksHttpServers(object): self.meraki = meraki self.new_object = dict( name=params.get("name"), - url=params.get("url"), - sharedSecret=params.get("sharedSecret"), payloadTemplate=params.get("payloadTemplate"), + sharedSecret=params.get("sharedSecret"), + url=params.get("url"), networkId=params.get("networkId"), httpServerId=params.get("httpServerId"), ) @@ -83,15 +83,15 @@ class NetworksWebhooksHttpServers(object): if self.new_object.get('name') is not None or self.new_object.get('name') is not None: new_object_params['name'] = self.new_object.get('name') or \ self.new_object.get('name') - if self.new_object.get('url') is not None or self.new_object.get('url') is not None: - new_object_params['url'] = self.new_object.get('url') or \ - self.new_object.get('url') - if self.new_object.get('sharedSecret') is not None or self.new_object.get('shared_secret') is not None: - new_object_params['sharedSecret'] = self.new_object.get('sharedSecret') or \ - self.new_object.get('shared_secret') if self.new_object.get('payloadTemplate') is not None or self.new_object.get('payload_template') is not None: new_object_params['payloadTemplate'] = self.new_object.get('payloadTemplate') or \ self.new_object.get('payload_template') + if self.new_object.get('sharedSecret') is not None or self.new_object.get('shared_secret') is not None: + new_object_params['sharedSecret'] = self.new_object.get('sharedSecret') or \ + self.new_object.get('shared_secret') + if self.new_object.get('url') is not None or self.new_object.get('url') is not None: + new_object_params['url'] = self.new_object.get('url') or \ + self.new_object.get('url') if self.new_object.get('networkId') is not None or self.new_object.get('network_id') is not None: new_object_params['networkId'] = self.new_object.get('networkId') or \ self.new_object.get('network_id') @@ -112,12 +112,12 @@ class NetworksWebhooksHttpServers(object): if self.new_object.get('name') is not None or self.new_object.get('name') is not None: new_object_params['name'] = self.new_object.get('name') or \ self.new_object.get('name') - if self.new_object.get('sharedSecret') is not None or self.new_object.get('shared_secret') is not None: - new_object_params['sharedSecret'] = self.new_object.get('sharedSecret') or \ - self.new_object.get('shared_secret') if self.new_object.get('payloadTemplate') is not None or self.new_object.get('payload_template') is not None: new_object_params['payloadTemplate'] = self.new_object.get('payloadTemplate') or \ self.new_object.get('payload_template') + if self.new_object.get('sharedSecret') is not None or self.new_object.get('shared_secret') is not None: + new_object_params['sharedSecret'] = self.new_object.get('sharedSecret') or \ + self.new_object.get('shared_secret') if self.new_object.get('networkId') is not None or self.new_object.get('network_id') is not None: new_object_params['networkId'] = self.new_object.get('networkId') or \ self.new_object.get('network_id') @@ -196,9 +196,9 @@ class NetworksWebhooksHttpServers(object): obj_params = [ ("name", "name"), - ("url", "url"), - ("sharedSecret", "sharedSecret"), ("payloadTemplate", "payloadTemplate"), + ("sharedSecret", "sharedSecret"), + ("url", "url"), ("networkId", "networkId"), ("httpServerId", "httpServerId"), ] diff --git a/ansible_collections/cisco/meraki/plugins/action/networks_webhooks_payload_templates.py b/ansible_collections/cisco/meraki/plugins/action/networks_webhooks_payload_templates.py index 335a112bc..9f1b32936 100644 --- a/ansible_collections/cisco/meraki/plugins/action/networks_webhooks_payload_templates.py +++ b/ansible_collections/cisco/meraki/plugins/action/networks_webhooks_payload_templates.py @@ -32,11 +32,11 @@ argument_spec = meraki_argument_spec() # Add arguments specific for this module argument_spec.update(dict( state=dict(type="str", default="present", choices=["present", "absent"]), - name=dict(type="str"), body=dict(type="str"), - headers=dict(type="list"), bodyFile=dict(type="str"), + headers=dict(type="list"), headersFile=dict(type="str"), + name=dict(type="str"), networkId=dict(type="str"), payloadTemplateId=dict(type="str"), )) @@ -54,11 +54,11 @@ class NetworksWebhooksPayloadTemplates(object): def __init__(self, params, meraki): self.meraki = meraki self.new_object = dict( - name=params.get("name"), body=params.get("body"), - headers=params.get("headers"), bodyFile=params.get("bodyFile"), + headers=params.get("headers"), headersFile=params.get("headersFile"), + name=params.get("name"), networkId=params.get("networkId"), payloadTemplateId=params.get("payloadTemplateId"), ) @@ -82,21 +82,21 @@ class NetworksWebhooksPayloadTemplates(object): def create_params(self): new_object_params = {} - if self.new_object.get('name') is not None or self.new_object.get('name') is not None: - new_object_params['name'] = self.new_object.get('name') or \ - self.new_object.get('name') if self.new_object.get('body') is not None or self.new_object.get('body') is not None: new_object_params['body'] = self.new_object.get('body') or \ self.new_object.get('body') - if self.new_object.get('headers') is not None or self.new_object.get('headers') is not None: - new_object_params['headers'] = self.new_object.get('headers') or \ - self.new_object.get('headers') if self.new_object.get('bodyFile') is not None or self.new_object.get('body_file') is not None: new_object_params['bodyFile'] = self.new_object.get('bodyFile') or \ self.new_object.get('body_file') + if self.new_object.get('headers') is not None or self.new_object.get('headers') is not None: + new_object_params['headers'] = self.new_object.get('headers') or \ + self.new_object.get('headers') if self.new_object.get('headersFile') is not None or self.new_object.get('headers_file') is not None: new_object_params['headersFile'] = self.new_object.get('headersFile') or \ self.new_object.get('headers_file') + if self.new_object.get('name') is not None or self.new_object.get('name') is not None: + new_object_params['name'] = self.new_object.get('name') or \ + self.new_object.get('name') if self.new_object.get('networkId') is not None or self.new_object.get('network_id') is not None: new_object_params['networkId'] = self.new_object.get('networkId') or \ self.new_object.get('network_id') @@ -114,21 +114,21 @@ class NetworksWebhooksPayloadTemplates(object): def update_by_id_params(self): new_object_params = {} - if self.new_object.get('name') is not None or self.new_object.get('name') is not None: - new_object_params['name'] = self.new_object.get('name') or \ - self.new_object.get('name') if self.new_object.get('body') is not None or self.new_object.get('body') is not None: new_object_params['body'] = self.new_object.get('body') or \ self.new_object.get('body') - if self.new_object.get('headers') is not None or self.new_object.get('headers') is not None: - new_object_params['headers'] = self.new_object.get('headers') or \ - self.new_object.get('headers') if self.new_object.get('bodyFile') is not None or self.new_object.get('body_file') is not None: new_object_params['bodyFile'] = self.new_object.get('bodyFile') or \ self.new_object.get('body_file') + if self.new_object.get('headers') is not None or self.new_object.get('headers') is not None: + new_object_params['headers'] = self.new_object.get('headers') or \ + self.new_object.get('headers') if self.new_object.get('headersFile') is not None or self.new_object.get('headers_file') is not None: new_object_params['headersFile'] = self.new_object.get('headersFile') or \ self.new_object.get('headers_file') + if self.new_object.get('name') is not None or self.new_object.get('name') is not None: + new_object_params['name'] = self.new_object.get('name') or \ + self.new_object.get('name') if self.new_object.get('networkId') is not None or self.new_object.get('network_id') is not None: new_object_params['networkId'] = self.new_object.get('networkId') or \ self.new_object.get('network_id') @@ -206,11 +206,11 @@ class NetworksWebhooksPayloadTemplates(object): requested_obj = self.new_object obj_params = [ - ("name", "name"), ("body", "body"), - ("headers", "headers"), ("bodyFile", "bodyFile"), + ("headers", "headers"), ("headersFile", "headersFile"), + ("name", "name"), ("networkId", "networkId"), ("payloadTemplateId", "payloadTemplateId"), ] diff --git a/ansible_collections/cisco/meraki/plugins/action/networks_wireless_alternate_management_interface.py b/ansible_collections/cisco/meraki/plugins/action/networks_wireless_alternate_management_interface.py index 899d9f264..f21ab1696 100644 --- a/ansible_collections/cisco/meraki/plugins/action/networks_wireless_alternate_management_interface.py +++ b/ansible_collections/cisco/meraki/plugins/action/networks_wireless_alternate_management_interface.py @@ -32,10 +32,10 @@ argument_spec = meraki_argument_spec() # Add arguments specific for this module argument_spec.update(dict( state=dict(type="str", default="present", choices=["present"]), + accessPoints=dict(type="list"), enabled=dict(type="bool"), - vlanId=dict(type="int"), protocols=dict(type="list"), - accessPoints=dict(type="list"), + vlanId=dict(type="int"), networkId=dict(type="str"), )) @@ -51,10 +51,10 @@ class NetworksWirelessAlternateManagementInterface(object): def __init__(self, params, meraki): self.meraki = meraki self.new_object = dict( + accessPoints=params.get("accessPoints"), enabled=params.get("enabled"), - vlanId=params.get("vlanId"), protocols=params.get("protocols"), - accessPoints=params.get("accessPoints"), + vlanId=params.get("vlanId"), network_id=params.get("networkId"), ) @@ -67,17 +67,17 @@ class NetworksWirelessAlternateManagementInterface(object): def update_all_params(self): new_object_params = {} + if self.new_object.get('accessPoints') is not None or self.new_object.get('access_points') is not None: + new_object_params['accessPoints'] = self.new_object.get('accessPoints') or \ + self.new_object.get('access_points') if self.new_object.get('enabled') is not None or self.new_object.get('enabled') is not None: new_object_params['enabled'] = self.new_object.get('enabled') - if self.new_object.get('vlanId') is not None or self.new_object.get('vlan_id') is not None: - new_object_params['vlanId'] = self.new_object.get('vlanId') or \ - self.new_object.get('vlan_id') if self.new_object.get('protocols') is not None or self.new_object.get('protocols') is not None: new_object_params['protocols'] = self.new_object.get('protocols') or \ self.new_object.get('protocols') - if self.new_object.get('accessPoints') is not None or self.new_object.get('access_points') is not None: - new_object_params['accessPoints'] = self.new_object.get('accessPoints') or \ - self.new_object.get('access_points') + if self.new_object.get('vlanId') is not None or self.new_object.get('vlan_id') is not None: + new_object_params['vlanId'] = self.new_object.get('vlanId') or \ + self.new_object.get('vlan_id') if self.new_object.get('networkId') is not None or self.new_object.get('network_id') is not None: new_object_params['networkId'] = self.new_object.get('networkId') or \ self.new_object.get('network_id') @@ -134,10 +134,10 @@ class NetworksWirelessAlternateManagementInterface(object): requested_obj = self.new_object obj_params = [ + ("accessPoints", "accessPoints"), ("enabled", "enabled"), - ("vlanId", "vlanId"), ("protocols", "protocols"), - ("accessPoints", "accessPoints"), + ("vlanId", "vlanId"), ("networkId", "networkId"), ] # Method 1. Params present in request (Ansible) obj are the same as the current (ISE) params diff --git a/ansible_collections/cisco/meraki/plugins/action/networks_wireless_bluetooth_settings.py b/ansible_collections/cisco/meraki/plugins/action/networks_wireless_bluetooth_settings.py index 59f9f6c75..ea730674c 100644 --- a/ansible_collections/cisco/meraki/plugins/action/networks_wireless_bluetooth_settings.py +++ b/ansible_collections/cisco/meraki/plugins/action/networks_wireless_bluetooth_settings.py @@ -32,12 +32,12 @@ argument_spec = meraki_argument_spec() # Add arguments specific for this module argument_spec.update(dict( state=dict(type="str", default="present", choices=["present"]), - scanningEnabled=dict(type="bool"), advertisingEnabled=dict(type="bool"), - uuid=dict(type="str"), - majorMinorAssignmentMode=dict(type="str"), major=dict(type="int"), + majorMinorAssignmentMode=dict(type="str"), minor=dict(type="int"), + scanningEnabled=dict(type="bool"), + uuid=dict(type="str"), networkId=dict(type="str"), )) @@ -53,12 +53,12 @@ class NetworksWirelessBluetoothSettings(object): def __init__(self, params, meraki): self.meraki = meraki self.new_object = dict( - scanningEnabled=params.get("scanningEnabled"), advertisingEnabled=params.get("advertisingEnabled"), - uuid=params.get("uuid"), - majorMinorAssignmentMode=params.get("majorMinorAssignmentMode"), major=params.get("major"), + majorMinorAssignmentMode=params.get("majorMinorAssignmentMode"), minor=params.get("minor"), + scanningEnabled=params.get("scanningEnabled"), + uuid=params.get("uuid"), network_id=params.get("networkId"), ) @@ -71,22 +71,22 @@ class NetworksWirelessBluetoothSettings(object): def update_all_params(self): new_object_params = {} - if self.new_object.get('scanningEnabled') is not None or self.new_object.get('scanning_enabled') is not None: - new_object_params['scanningEnabled'] = self.new_object.get('scanningEnabled') if self.new_object.get('advertisingEnabled') is not None or self.new_object.get('advertising_enabled') is not None: new_object_params['advertisingEnabled'] = self.new_object.get('advertisingEnabled') - if self.new_object.get('uuid') is not None or self.new_object.get('uuid') is not None: - new_object_params['uuid'] = self.new_object.get('uuid') or \ - self.new_object.get('uuid') - if self.new_object.get('majorMinorAssignmentMode') is not None or self.new_object.get('major_minor_assignment_mode') is not None: - new_object_params['majorMinorAssignmentMode'] = self.new_object.get('majorMinorAssignmentMode') or \ - self.new_object.get('major_minor_assignment_mode') if self.new_object.get('major') is not None or self.new_object.get('major') is not None: new_object_params['major'] = self.new_object.get('major') or \ self.new_object.get('major') + if self.new_object.get('majorMinorAssignmentMode') is not None or self.new_object.get('major_minor_assignment_mode') is not None: + new_object_params['majorMinorAssignmentMode'] = self.new_object.get('majorMinorAssignmentMode') or \ + self.new_object.get('major_minor_assignment_mode') if self.new_object.get('minor') is not None or self.new_object.get('minor') is not None: new_object_params['minor'] = self.new_object.get('minor') or \ self.new_object.get('minor') + if self.new_object.get('scanningEnabled') is not None or self.new_object.get('scanning_enabled') is not None: + new_object_params['scanningEnabled'] = self.new_object.get('scanningEnabled') + if self.new_object.get('uuid') is not None or self.new_object.get('uuid') is not None: + new_object_params['uuid'] = self.new_object.get('uuid') or \ + self.new_object.get('uuid') if self.new_object.get('networkId') is not None or self.new_object.get('network_id') is not None: new_object_params['networkId'] = self.new_object.get('networkId') or \ self.new_object.get('network_id') @@ -143,12 +143,12 @@ class NetworksWirelessBluetoothSettings(object): requested_obj = self.new_object obj_params = [ - ("scanningEnabled", "scanningEnabled"), ("advertisingEnabled", "advertisingEnabled"), - ("uuid", "uuid"), - ("majorMinorAssignmentMode", "majorMinorAssignmentMode"), ("major", "major"), + ("majorMinorAssignmentMode", "majorMinorAssignmentMode"), ("minor", "minor"), + ("scanningEnabled", "scanningEnabled"), + ("uuid", "uuid"), ("networkId", "networkId"), ] # Method 1. Params present in request (Ansible) obj are the same as the current (ISE) params diff --git a/ansible_collections/cisco/meraki/plugins/action/networks_wireless_ethernet_ports_profiles.py b/ansible_collections/cisco/meraki/plugins/action/networks_wireless_ethernet_ports_profiles.py new file mode 100644 index 000000000..fc95256a5 --- /dev/null +++ b/ansible_collections/cisco/meraki/plugins/action/networks_wireless_ethernet_ports_profiles.py @@ -0,0 +1,270 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +# Copyright (c) 2021, Cisco Systems +# 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 +from ansible.plugins.action import ActionBase +try: + from ansible_collections.ansible.utils.plugins.module_utils.common.argspec_validate import ( + AnsibleArgSpecValidator, + ) +except ImportError: + ANSIBLE_UTILS_IS_INSTALLED = False +else: + ANSIBLE_UTILS_IS_INSTALLED = True +from ansible.errors import AnsibleActionFail +from ansible_collections.cisco.meraki.plugins.plugin_utils.meraki import ( + MERAKI, + meraki_argument_spec, + meraki_compare_equality, +) +from ansible_collections.cisco.meraki.plugins.plugin_utils.exceptions import ( + InconsistentParameters, +) + +# Get common arguments specification +argument_spec = meraki_argument_spec() +# Add arguments specific for this module +argument_spec.update(dict( + state=dict(type="str", default="present", choices=["present", "absent"]), + name=dict(type="str"), + ports=dict(type="list"), + usbPorts=dict(type="list"), + networkId=dict(type="str"), + profileId=dict(type="str"), +)) + +required_if = [ + ("state", "present", ["name", "networkId", "profileId"], True), + ("state", "absent", ["name", "networkId", "profileId"], True), +] +required_one_of = [] +mutually_exclusive = [] +required_together = [] + + +class NetworksWirelessEthernetPortsProfiles(object): + def __init__(self, params, meraki): + self.meraki = meraki + self.new_object = dict( + name=params.get("name"), + ports=params.get("ports"), + usbPorts=params.get("usbPorts"), + network_id=params.get("networkId"), + profile_id=params.get("profileId"), + ) + + def get_params_by_id(self, name=None, id=None): + new_object_params = {} + if self.new_object.get('networkId') is not None or self.new_object.get('network_id') is not None: + new_object_params['networkId'] = self.new_object.get('networkId') or \ + self.new_object.get('network_id') + if self.new_object.get('profileId') is not None or self.new_object.get('profile_id') is not None: + new_object_params['profileId'] = self.new_object.get('profileId') or \ + self.new_object.get('profile_id') + return new_object_params + + def delete_by_id_params(self): + new_object_params = {} + if self.new_object.get('networkId') is not None or self.new_object.get('network_id') is not None: + new_object_params['networkId'] = self.new_object.get('networkId') or \ + self.new_object.get('network_id') + if self.new_object.get('profileId') is not None or self.new_object.get('profile_id') is not None: + new_object_params['profileId'] = self.new_object.get('profileId') or \ + self.new_object.get('profile_id') + return new_object_params + + def update_by_id_params(self): + new_object_params = {} + if self.new_object.get('name') is not None or self.new_object.get('name') is not None: + new_object_params['name'] = self.new_object.get('name') or \ + self.new_object.get('name') + if self.new_object.get('ports') is not None or self.new_object.get('ports') is not None: + new_object_params['ports'] = self.new_object.get('ports') or \ + self.new_object.get('ports') + if self.new_object.get('usbPorts') is not None or self.new_object.get('usb_ports') is not None: + new_object_params['usbPorts'] = self.new_object.get('usbPorts') or \ + self.new_object.get('usb_ports') + if self.new_object.get('networkId') is not None or self.new_object.get('network_id') is not None: + new_object_params['networkId'] = self.new_object.get('networkId') or \ + self.new_object.get('network_id') + if self.new_object.get('profileId') is not None or self.new_object.get('profile_id') is not None: + new_object_params['profileId'] = self.new_object.get('profileId') or \ + self.new_object.get('profile_id') + return new_object_params + + def get_object_by_name(self, name): + result = None + # NOTE: Does not have a get by name and get all + return result + + def get_object_by_id(self, id): + result = None + try: + items = self.meraki.exec_meraki( + family="wireless", + function="getNetworkWirelessEthernetPortsProfile", + params=self.get_params_by_id() + ) + if isinstance(items, dict): + if 'response' in items: + items = items.get('response') + result = items + except Exception as e: + print("Error: ", e) + result = None + return result + + def exists(self): + prev_obj = None + id_exists = False + name_exists = False + o_id = self.new_object.get("networkId") or self.new_object.get("network_id") + o_id = o_id or self.new_object.get( + "profile_id") or self.new_object.get("profileId") + name = self.new_object.get("name") + if o_id: + prev_obj = self.get_object_by_id(o_id) + id_exists = prev_obj is not None and isinstance(prev_obj, dict) + if not id_exists and name: + prev_obj = self.get_object_by_name(name) + name_exists = prev_obj is not None and isinstance(prev_obj, dict) + if name_exists: + _id = prev_obj.get("id") + _id = _id or prev_obj.get("profileId") + if id_exists and name_exists and o_id != _id: + raise InconsistentParameters( + "The 'id' and 'name' params don't refer to the same object") + if _id: + self.new_object.update(dict(id=_id)) + self.new_object.update(dict(profileId=_id)) + if _id: + prev_obj = self.get_object_by_id(_id) + it_exists = prev_obj is not None and isinstance(prev_obj, dict) + return (it_exists, prev_obj) + + def requires_update(self, current_obj): + requested_obj = self.new_object + + obj_params = [ + ("name", "name"), + ("ports", "ports"), + ("usbPorts", "usbPorts"), + ("networkId", "networkId"), + ("profileId", "profileId"), + ] + # Method 1. Params present in request (Ansible) obj are the same as the current (ISE) params + # If any does not have eq params, it requires update + return any(not meraki_compare_equality(current_obj.get(meraki_param), + requested_obj.get(ansible_param)) + for (meraki_param, ansible_param) in obj_params) + + def update(self): + id = self.new_object.get("id") + id = id or self.new_object.get("profileId") + name = self.new_object.get("name") + result = None + if not id: + prev_obj_name = self.get_object_by_name(name) + id_ = None + if prev_obj_name: + id_ = prev_obj_name.get("id") + id_ = id_ or prev_obj_name.get("profileId") + if id_: + self.new_object.update(dict(profileid=id_)) + result = self.meraki.exec_meraki( + family="wireless", + function="updateNetworkWirelessEthernetPortsProfile", + params=self.update_by_id_params(), + op_modifies=True, + ) + return result + + def delete(self): + id = self.new_object.get("id") + id = id or self.new_object.get("profileId") + name = self.new_object.get("name") + result = None + if not id: + prev_obj_name = self.get_object_by_name(name) + id_ = None + if prev_obj_name: + id_ = prev_obj_name.get("id") + id_ = id_ or prev_obj_name.get("profileId") + if id_: + self.new_object.update(dict(profileid=id_)) + result = self.meraki.exec_meraki( + family="wireless", + function="deleteNetworkWirelessEthernetPortsProfile", + params=self.delete_by_id_params(), + ) + return result + + +class ActionModule(ActionBase): + def __init__(self, *args, **kwargs): + if not ANSIBLE_UTILS_IS_INSTALLED: + raise AnsibleActionFail( + "ansible.utils is not installed. Execute 'ansible-galaxy collection install ansible.utils'") + super(ActionModule, self).__init__(*args, **kwargs) + self._supports_async = False + self._supports_check_mode = False + self._result = None + + # Checks the supplied parameters against the argument spec for this module + def _check_argspec(self): + aav = AnsibleArgSpecValidator( + data=self._task.args, + schema=dict(argument_spec=argument_spec), + schema_format="argspec", + schema_conditionals=dict( + required_if=required_if, + required_one_of=required_one_of, + mutually_exclusive=mutually_exclusive, + required_together=required_together, + ), + name=self._task.action, + ) + valid, errors, self._task.args = aav.validate() + if not valid: + raise AnsibleActionFail(errors) + + def run(self, tmp=None, task_vars=None): + self._task.diff = False + self._result = super(ActionModule, self).run(tmp, task_vars) + self._result["changed"] = False + self._check_argspec() + + meraki = MERAKI(self._task.args) + obj = NetworksWirelessEthernetPortsProfiles(self._task.args, meraki) + + state = self._task.args.get("state") + + response = None + if state == "present": + (obj_exists, prev_obj) = obj.exists() + if obj_exists: + if obj.requires_update(prev_obj): + response = obj.update() + meraki.object_updated() + else: + response = prev_obj + meraki.object_already_present() + else: + meraki.fail_json( + "Object does not exists, plugin only has update") + elif state == "absent": + (obj_exists, prev_obj) = obj.exists() + if obj_exists: + response = obj.delete() + meraki.object_deleted() + else: + meraki.object_already_absent() + + self._result.update(dict(meraki_response=response)) + self._result.update(meraki.exit_json()) + return self._result diff --git a/ansible_collections/cisco/meraki/plugins/action/networks_wireless_ethernet_ports_profiles_assign.py b/ansible_collections/cisco/meraki/plugins/action/networks_wireless_ethernet_ports_profiles_assign.py new file mode 100644 index 000000000..8e594fcae --- /dev/null +++ b/ansible_collections/cisco/meraki/plugins/action/networks_wireless_ethernet_ports_profiles_assign.py @@ -0,0 +1,91 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +# Copyright (c) 2021, Cisco Systems +# 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 +from ansible.plugins.action import ActionBase +try: + from ansible_collections.ansible.utils.plugins.module_utils.common.argspec_validate import ( + AnsibleArgSpecValidator, + ) +except ImportError: + ANSIBLE_UTILS_IS_INSTALLED = False +else: + ANSIBLE_UTILS_IS_INSTALLED = True +from ansible.errors import AnsibleActionFail +from ansible_collections.cisco.meraki.plugins.plugin_utils.meraki import ( + MERAKI, + meraki_argument_spec, +) + +# Get common arguements specification +argument_spec = meraki_argument_spec() +# Add arguments specific for this module +argument_spec.update(dict( + profileId=dict(type="str"), + serials=dict(type="list"), + networkId=dict(type="str"), +)) + +required_if = [] +required_one_of = [] +mutually_exclusive = [] +required_together = [] + + +class ActionModule(ActionBase): + def __init__(self, *args, **kwargs): + if not ANSIBLE_UTILS_IS_INSTALLED: + raise AnsibleActionFail( + "ansible.utils is not installed. Execute 'ansible-galaxy collection install ansible.utils'") + super(ActionModule, self).__init__(*args, **kwargs) + self._supports_async = False + self._supports_check_mode = False + self._result = None + + # Checks the supplied parameters against the argument spec for this module + def _check_argspec(self): + aav = AnsibleArgSpecValidator( + data=self._task.args, + schema=dict(argument_spec=argument_spec), + schema_format="argspec", + schema_conditionals=dict( + required_if=required_if, + required_one_of=required_one_of, + mutually_exclusive=mutually_exclusive, + required_together=required_together, + ), + name=self._task.action, + ) + valid, errors, self._task.args = aav.validate() + if not valid: + raise AnsibleActionFail(errors) + + def get_object(self, params): + new_object = dict( + profileId=params.get("profileId"), + serials=params.get("serials"), + networkId=params.get("networkId"), + ) + return new_object + + def run(self, tmp=None, task_vars=None): + self._task.diff = False + self._result = super(ActionModule, self).run(tmp, task_vars) + self._result["changed"] = False + self._check_argspec() + + meraki = MERAKI(params=self._task.args) + + response = meraki.exec_meraki( + family="wireless", + function='assignNetworkWirelessEthernetPortsProfiles', + op_modifies=True, + params=self.get_object(self._task.args), + ) + self._result.update(dict(meraki_response=response)) + self._result.update(meraki.exit_json()) + return self._result diff --git a/ansible_collections/cisco/meraki/plugins/action/networks_wireless_ethernet_ports_profiles_info.py b/ansible_collections/cisco/meraki/plugins/action/networks_wireless_ethernet_ports_profiles_info.py new file mode 100644 index 000000000..1bf4c8dee --- /dev/null +++ b/ansible_collections/cisco/meraki/plugins/action/networks_wireless_ethernet_ports_profiles_info.py @@ -0,0 +1,102 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +# Copyright (c) 2021, Cisco Systems +# 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 +from ansible.plugins.action import ActionBase +try: + from ansible_collections.ansible.utils.plugins.module_utils.common.argspec_validate import ( + AnsibleArgSpecValidator, + ) +except ImportError: + ANSIBLE_UTILS_IS_INSTALLED = False +else: + ANSIBLE_UTILS_IS_INSTALLED = True +from ansible.errors import AnsibleActionFail +from ansible_collections.cisco.meraki.plugins.plugin_utils.meraki import ( + MERAKI, + meraki_argument_spec, +) + +# Get common arguments specification +argument_spec = meraki_argument_spec() +# Add arguments specific for this module +argument_spec.update(dict( + networkId=dict(type="str"), + profileId=dict(type="str"), +)) + +required_if = [] +required_one_of = [] +mutually_exclusive = [] +required_together = [] + + +class ActionModule(ActionBase): + def __init__(self, *args, **kwargs): + if not ANSIBLE_UTILS_IS_INSTALLED: + raise AnsibleActionFail( + "ansible.utils is not installed. Execute 'ansible-galaxy collection install ansible.utils'") + super(ActionModule, self).__init__(*args, **kwargs) + self._supports_async = False + self._supports_check_mode = True + self._result = None + + # Checks the supplied parameters against the argument spec for this module + def _check_argspec(self): + aav = AnsibleArgSpecValidator( + data=self._task.args, + schema=dict(argument_spec=argument_spec), + schema_format="argspec", + schema_conditionals=dict( + required_if=required_if, + required_one_of=required_one_of, + mutually_exclusive=mutually_exclusive, + required_together=required_together, + ), + name=self._task.action, + ) + valid, errors, self._task.args = aav.validate() + if not valid: + raise AnsibleActionFail(errors) + + def get_object(self, params): + new_object = {} + if params.get("networkId") is not None: + new_object["networkId"] = params.get( + "networkId") + if params.get("profileId") is not None: + new_object["profileId"] = params.get( + "profileId") + return new_object + + def run(self, tmp=None, task_vars=None): + self._task.diff = False + self._result = super(ActionModule, self).run(tmp, task_vars) + self._result["changed"] = False + self._check_argspec() + + self._result.update(dict(meraki_response={})) + + meraki = MERAKI(params=self._task.args) + + id = self._task.args.get("profileId") + if id: + response = meraki.exec_meraki( + family="wireless", + function='getNetworkWirelessEthernetPortsProfile', + params=self.get_object(self._task.args), + ) + self._result.update(dict(meraki_response=response)) + self._result.update(meraki.exit_json()) + return self._result + if not id: + # NOTE: Does not have a get all method or it is in another action + response = None + meraki.object_modify_result(changed=False, result="Module does not have get all, check arguments of module") + self._result.update(dict(meraki_response=response)) + self._result.update(meraki.exit_json()) + return self._result diff --git a/ansible_collections/cisco/meraki/plugins/action/networks_wireless_ethernet_ports_profiles_set_default.py b/ansible_collections/cisco/meraki/plugins/action/networks_wireless_ethernet_ports_profiles_set_default.py new file mode 100644 index 000000000..1cccd7aa1 --- /dev/null +++ b/ansible_collections/cisco/meraki/plugins/action/networks_wireless_ethernet_ports_profiles_set_default.py @@ -0,0 +1,89 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +# Copyright (c) 2021, Cisco Systems +# 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 +from ansible.plugins.action import ActionBase +try: + from ansible_collections.ansible.utils.plugins.module_utils.common.argspec_validate import ( + AnsibleArgSpecValidator, + ) +except ImportError: + ANSIBLE_UTILS_IS_INSTALLED = False +else: + ANSIBLE_UTILS_IS_INSTALLED = True +from ansible.errors import AnsibleActionFail +from ansible_collections.cisco.meraki.plugins.plugin_utils.meraki import ( + MERAKI, + meraki_argument_spec, +) + +# Get common arguements specification +argument_spec = meraki_argument_spec() +# Add arguments specific for this module +argument_spec.update(dict( + profileId=dict(type="str"), + networkId=dict(type="str"), +)) + +required_if = [] +required_one_of = [] +mutually_exclusive = [] +required_together = [] + + +class ActionModule(ActionBase): + def __init__(self, *args, **kwargs): + if not ANSIBLE_UTILS_IS_INSTALLED: + raise AnsibleActionFail( + "ansible.utils is not installed. Execute 'ansible-galaxy collection install ansible.utils'") + super(ActionModule, self).__init__(*args, **kwargs) + self._supports_async = False + self._supports_check_mode = False + self._result = None + + # Checks the supplied parameters against the argument spec for this module + def _check_argspec(self): + aav = AnsibleArgSpecValidator( + data=self._task.args, + schema=dict(argument_spec=argument_spec), + schema_format="argspec", + schema_conditionals=dict( + required_if=required_if, + required_one_of=required_one_of, + mutually_exclusive=mutually_exclusive, + required_together=required_together, + ), + name=self._task.action, + ) + valid, errors, self._task.args = aav.validate() + if not valid: + raise AnsibleActionFail(errors) + + def get_object(self, params): + new_object = dict( + profileId=params.get("profileId"), + networkId=params.get("networkId"), + ) + return new_object + + def run(self, tmp=None, task_vars=None): + self._task.diff = False + self._result = super(ActionModule, self).run(tmp, task_vars) + self._result["changed"] = False + self._check_argspec() + + meraki = MERAKI(params=self._task.args) + + response = meraki.exec_meraki( + family="wireless", + function='setNetworkWirelessEthernetPortsProfilesDefault', + op_modifies=True, + params=self.get_object(self._task.args), + ) + self._result.update(dict(meraki_response=response)) + self._result.update(meraki.exit_json()) + return self._result diff --git a/ansible_collections/cisco/meraki/plugins/action/networks_wireless_rf_profiles.py b/ansible_collections/cisco/meraki/plugins/action/networks_wireless_rf_profiles.py index ad3f0d8ec..c4d650c4d 100644 --- a/ansible_collections/cisco/meraki/plugins/action/networks_wireless_rf_profiles.py +++ b/ansible_collections/cisco/meraki/plugins/action/networks_wireless_rf_profiles.py @@ -32,16 +32,17 @@ argument_spec = meraki_argument_spec() # Add arguments specific for this module argument_spec.update(dict( state=dict(type="str", default="present", choices=["present", "absent"]), - name=dict(type="str"), - clientBalancingEnabled=dict(type="bool"), - minBitrateType=dict(type="str"), - bandSelectionType=dict(type="str"), apBandSettings=dict(type="dict"), - twoFourGhzSettings=dict(type="dict"), + bandSelectionType=dict(type="str"), + clientBalancingEnabled=dict(type="bool"), fiveGhzSettings=dict(type="dict"), + flexRadios=dict(type="dict"), + minBitrateType=dict(type="str"), + name=dict(type="str"), + perSsidSettings=dict(type="dict"), sixGhzSettings=dict(type="dict"), transmission=dict(type="dict"), - perSsidSettings=dict(type="dict"), + twoFourGhzSettings=dict(type="dict"), networkId=dict(type="str"), rfProfileId=dict(type="str"), )) @@ -59,16 +60,17 @@ class NetworksWirelessRfProfiles(object): def __init__(self, params, meraki): self.meraki = meraki self.new_object = dict( - name=params.get("name"), - clientBalancingEnabled=params.get("clientBalancingEnabled"), - minBitrateType=params.get("minBitrateType"), - bandSelectionType=params.get("bandSelectionType"), apBandSettings=params.get("apBandSettings"), - twoFourGhzSettings=params.get("twoFourGhzSettings"), + bandSelectionType=params.get("bandSelectionType"), + clientBalancingEnabled=params.get("clientBalancingEnabled"), fiveGhzSettings=params.get("fiveGhzSettings"), + flexRadios=params.get("flexRadios"), + minBitrateType=params.get("minBitrateType"), + name=params.get("name"), + perSsidSettings=params.get("perSsidSettings"), sixGhzSettings=params.get("sixGhzSettings"), transmission=params.get("transmission"), - perSsidSettings=params.get("perSsidSettings"), + twoFourGhzSettings=params.get("twoFourGhzSettings"), networkId=params.get("networkId"), rfProfileId=params.get("rfProfileId"), ) @@ -95,35 +97,38 @@ class NetworksWirelessRfProfiles(object): def create_params(self): new_object_params = {} - if self.new_object.get('name') is not None or self.new_object.get('name') is not None: - new_object_params['name'] = self.new_object.get('name') or \ - self.new_object.get('name') - if self.new_object.get('clientBalancingEnabled') is not None or self.new_object.get('client_balancing_enabled') is not None: - new_object_params['clientBalancingEnabled'] = self.new_object.get('clientBalancingEnabled') - if self.new_object.get('minBitrateType') is not None or self.new_object.get('min_bitrate_type') is not None: - new_object_params['minBitrateType'] = self.new_object.get('minBitrateType') or \ - self.new_object.get('min_bitrate_type') - if self.new_object.get('bandSelectionType') is not None or self.new_object.get('band_selection_type') is not None: - new_object_params['bandSelectionType'] = self.new_object.get('bandSelectionType') or \ - self.new_object.get('band_selection_type') if self.new_object.get('apBandSettings') is not None or self.new_object.get('ap_band_settings') is not None: new_object_params['apBandSettings'] = self.new_object.get('apBandSettings') or \ self.new_object.get('ap_band_settings') - if self.new_object.get('twoFourGhzSettings') is not None or self.new_object.get('two_four_ghz_settings') is not None: - new_object_params['twoFourGhzSettings'] = self.new_object.get('twoFourGhzSettings') or \ - self.new_object.get('two_four_ghz_settings') + if self.new_object.get('bandSelectionType') is not None or self.new_object.get('band_selection_type') is not None: + new_object_params['bandSelectionType'] = self.new_object.get('bandSelectionType') or \ + self.new_object.get('band_selection_type') + if self.new_object.get('clientBalancingEnabled') is not None or self.new_object.get('client_balancing_enabled') is not None: + new_object_params['clientBalancingEnabled'] = self.new_object.get('clientBalancingEnabled') if self.new_object.get('fiveGhzSettings') is not None or self.new_object.get('five_ghz_settings') is not None: new_object_params['fiveGhzSettings'] = self.new_object.get('fiveGhzSettings') or \ self.new_object.get('five_ghz_settings') + if self.new_object.get('flexRadios') is not None or self.new_object.get('flex_radios') is not None: + new_object_params['flexRadios'] = self.new_object.get('flexRadios') or \ + self.new_object.get('flex_radios') + if self.new_object.get('minBitrateType') is not None or self.new_object.get('min_bitrate_type') is not None: + new_object_params['minBitrateType'] = self.new_object.get('minBitrateType') or \ + self.new_object.get('min_bitrate_type') + if self.new_object.get('name') is not None or self.new_object.get('name') is not None: + new_object_params['name'] = self.new_object.get('name') or \ + self.new_object.get('name') + if self.new_object.get('perSsidSettings') is not None or self.new_object.get('per_ssid_settings') is not None: + new_object_params['perSsidSettings'] = self.new_object.get('perSsidSettings') or \ + self.new_object.get('per_ssid_settings') if self.new_object.get('sixGhzSettings') is not None or self.new_object.get('six_ghz_settings') is not None: new_object_params['sixGhzSettings'] = self.new_object.get('sixGhzSettings') or \ self.new_object.get('six_ghz_settings') if self.new_object.get('transmission') is not None or self.new_object.get('transmission') is not None: new_object_params['transmission'] = self.new_object.get('transmission') or \ self.new_object.get('transmission') - if self.new_object.get('perSsidSettings') is not None or self.new_object.get('per_ssid_settings') is not None: - new_object_params['perSsidSettings'] = self.new_object.get('perSsidSettings') or \ - self.new_object.get('per_ssid_settings') + if self.new_object.get('twoFourGhzSettings') is not None or self.new_object.get('two_four_ghz_settings') is not None: + new_object_params['twoFourGhzSettings'] = self.new_object.get('twoFourGhzSettings') or \ + self.new_object.get('two_four_ghz_settings') if self.new_object.get('networkId') is not None or self.new_object.get('network_id') is not None: new_object_params['networkId'] = self.new_object.get('networkId') or \ self.new_object.get('network_id') @@ -141,35 +146,38 @@ class NetworksWirelessRfProfiles(object): def update_by_id_params(self): new_object_params = {} - if self.new_object.get('name') is not None or self.new_object.get('name') is not None: - new_object_params['name'] = self.new_object.get('name') or \ - self.new_object.get('name') - if self.new_object.get('clientBalancingEnabled') is not None or self.new_object.get('client_balancing_enabled') is not None: - new_object_params['clientBalancingEnabled'] = self.new_object.get('clientBalancingEnabled') - if self.new_object.get('minBitrateType') is not None or self.new_object.get('min_bitrate_type') is not None: - new_object_params['minBitrateType'] = self.new_object.get('minBitrateType') or \ - self.new_object.get('min_bitrate_type') - if self.new_object.get('bandSelectionType') is not None or self.new_object.get('band_selection_type') is not None: - new_object_params['bandSelectionType'] = self.new_object.get('bandSelectionType') or \ - self.new_object.get('band_selection_type') if self.new_object.get('apBandSettings') is not None or self.new_object.get('ap_band_settings') is not None: new_object_params['apBandSettings'] = self.new_object.get('apBandSettings') or \ self.new_object.get('ap_band_settings') - if self.new_object.get('twoFourGhzSettings') is not None or self.new_object.get('two_four_ghz_settings') is not None: - new_object_params['twoFourGhzSettings'] = self.new_object.get('twoFourGhzSettings') or \ - self.new_object.get('two_four_ghz_settings') + if self.new_object.get('bandSelectionType') is not None or self.new_object.get('band_selection_type') is not None: + new_object_params['bandSelectionType'] = self.new_object.get('bandSelectionType') or \ + self.new_object.get('band_selection_type') + if self.new_object.get('clientBalancingEnabled') is not None or self.new_object.get('client_balancing_enabled') is not None: + new_object_params['clientBalancingEnabled'] = self.new_object.get('clientBalancingEnabled') if self.new_object.get('fiveGhzSettings') is not None or self.new_object.get('five_ghz_settings') is not None: new_object_params['fiveGhzSettings'] = self.new_object.get('fiveGhzSettings') or \ self.new_object.get('five_ghz_settings') + if self.new_object.get('flexRadios') is not None or self.new_object.get('flex_radios') is not None: + new_object_params['flexRadios'] = self.new_object.get('flexRadios') or \ + self.new_object.get('flex_radios') + if self.new_object.get('minBitrateType') is not None or self.new_object.get('min_bitrate_type') is not None: + new_object_params['minBitrateType'] = self.new_object.get('minBitrateType') or \ + self.new_object.get('min_bitrate_type') + if self.new_object.get('name') is not None or self.new_object.get('name') is not None: + new_object_params['name'] = self.new_object.get('name') or \ + self.new_object.get('name') + if self.new_object.get('perSsidSettings') is not None or self.new_object.get('per_ssid_settings') is not None: + new_object_params['perSsidSettings'] = self.new_object.get('perSsidSettings') or \ + self.new_object.get('per_ssid_settings') if self.new_object.get('sixGhzSettings') is not None or self.new_object.get('six_ghz_settings') is not None: new_object_params['sixGhzSettings'] = self.new_object.get('sixGhzSettings') or \ self.new_object.get('six_ghz_settings') if self.new_object.get('transmission') is not None or self.new_object.get('transmission') is not None: new_object_params['transmission'] = self.new_object.get('transmission') or \ self.new_object.get('transmission') - if self.new_object.get('perSsidSettings') is not None or self.new_object.get('per_ssid_settings') is not None: - new_object_params['perSsidSettings'] = self.new_object.get('perSsidSettings') or \ - self.new_object.get('per_ssid_settings') + if self.new_object.get('twoFourGhzSettings') is not None or self.new_object.get('two_four_ghz_settings') is not None: + new_object_params['twoFourGhzSettings'] = self.new_object.get('twoFourGhzSettings') or \ + self.new_object.get('two_four_ghz_settings') if self.new_object.get('networkId') is not None or self.new_object.get('network_id') is not None: new_object_params['networkId'] = self.new_object.get('networkId') or \ self.new_object.get('network_id') @@ -247,16 +255,17 @@ class NetworksWirelessRfProfiles(object): requested_obj = self.new_object obj_params = [ - ("name", "name"), - ("clientBalancingEnabled", "clientBalancingEnabled"), - ("minBitrateType", "minBitrateType"), - ("bandSelectionType", "bandSelectionType"), ("apBandSettings", "apBandSettings"), - ("twoFourGhzSettings", "twoFourGhzSettings"), + ("bandSelectionType", "bandSelectionType"), + ("clientBalancingEnabled", "clientBalancingEnabled"), ("fiveGhzSettings", "fiveGhzSettings"), + ("flexRadios", "flexRadios"), + ("minBitrateType", "minBitrateType"), + ("name", "name"), + ("perSsidSettings", "perSsidSettings"), ("sixGhzSettings", "sixGhzSettings"), ("transmission", "transmission"), - ("perSsidSettings", "perSsidSettings"), + ("twoFourGhzSettings", "twoFourGhzSettings"), ("networkId", "networkId"), ("rfProfileId", "rfProfileId"), ] diff --git a/ansible_collections/cisco/meraki/plugins/action/networks_wireless_settings.py b/ansible_collections/cisco/meraki/plugins/action/networks_wireless_settings.py index 2a7543475..4fecff005 100644 --- a/ansible_collections/cisco/meraki/plugins/action/networks_wireless_settings.py +++ b/ansible_collections/cisco/meraki/plugins/action/networks_wireless_settings.py @@ -32,11 +32,12 @@ argument_spec = meraki_argument_spec() # Add arguments specific for this module argument_spec.update(dict( state=dict(type="str", default="present", choices=["present"]), - meshingEnabled=dict(type="bool"), ipv6BridgeEnabled=dict(type="bool"), + ledLightsOn=dict(type="bool"), locationAnalyticsEnabled=dict(type="bool"), + meshingEnabled=dict(type="bool"), + namedVlans=dict(type="dict"), upgradeStrategy=dict(type="str"), - ledLightsOn=dict(type="bool"), networkId=dict(type="str"), )) @@ -52,11 +53,12 @@ class NetworksWirelessSettings(object): def __init__(self, params, meraki): self.meraki = meraki self.new_object = dict( - meshingEnabled=params.get("meshingEnabled"), ipv6BridgeEnabled=params.get("ipv6BridgeEnabled"), + ledLightsOn=params.get("ledLightsOn"), locationAnalyticsEnabled=params.get("locationAnalyticsEnabled"), + meshingEnabled=params.get("meshingEnabled"), + namedVlans=params.get("namedVlans"), upgradeStrategy=params.get("upgradeStrategy"), - ledLightsOn=params.get("ledLightsOn"), network_id=params.get("networkId"), ) @@ -69,17 +71,20 @@ class NetworksWirelessSettings(object): def update_all_params(self): new_object_params = {} - if self.new_object.get('meshingEnabled') is not None or self.new_object.get('meshing_enabled') is not None: - new_object_params['meshingEnabled'] = self.new_object.get('meshingEnabled') if self.new_object.get('ipv6BridgeEnabled') is not None or self.new_object.get('ipv6_bridge_enabled') is not None: new_object_params['ipv6BridgeEnabled'] = self.new_object.get('ipv6BridgeEnabled') + if self.new_object.get('ledLightsOn') is not None or self.new_object.get('led_lights_on') is not None: + new_object_params['ledLightsOn'] = self.new_object.get('ledLightsOn') if self.new_object.get('locationAnalyticsEnabled') is not None or self.new_object.get('location_analytics_enabled') is not None: new_object_params['locationAnalyticsEnabled'] = self.new_object.get('locationAnalyticsEnabled') + if self.new_object.get('meshingEnabled') is not None or self.new_object.get('meshing_enabled') is not None: + new_object_params['meshingEnabled'] = self.new_object.get('meshingEnabled') + if self.new_object.get('namedVlans') is not None or self.new_object.get('named_vlans') is not None: + new_object_params['namedVlans'] = self.new_object.get('namedVlans') or \ + self.new_object.get('named_vlans') if self.new_object.get('upgradeStrategy') is not None or self.new_object.get('upgrade_strategy') is not None: new_object_params['upgradeStrategy'] = self.new_object.get('upgradeStrategy') or \ self.new_object.get('upgrade_strategy') - if self.new_object.get('ledLightsOn') is not None or self.new_object.get('led_lights_on') is not None: - new_object_params['ledLightsOn'] = self.new_object.get('ledLightsOn') if self.new_object.get('networkId') is not None or self.new_object.get('network_id') is not None: new_object_params['networkId'] = self.new_object.get('networkId') or \ self.new_object.get('network_id') @@ -136,11 +141,12 @@ class NetworksWirelessSettings(object): requested_obj = self.new_object obj_params = [ - ("meshingEnabled", "meshingEnabled"), ("ipv6BridgeEnabled", "ipv6BridgeEnabled"), + ("ledLightsOn", "ledLightsOn"), ("locationAnalyticsEnabled", "locationAnalyticsEnabled"), + ("meshingEnabled", "meshingEnabled"), + ("namedVlans", "namedVlans"), ("upgradeStrategy", "upgradeStrategy"), - ("ledLightsOn", "ledLightsOn"), ("networkId", "networkId"), ] # Method 1. Params present in request (Ansible) obj are the same as the current (ISE) params diff --git a/ansible_collections/cisco/meraki/plugins/action/networks_wireless_ssids.py b/ansible_collections/cisco/meraki/plugins/action/networks_wireless_ssids.py index eb8affa88..24272855d 100644 --- a/ansible_collections/cisco/meraki/plugins/action/networks_wireless_ssids.py +++ b/ansible_collections/cisco/meraki/plugins/action/networks_wireless_ssids.py @@ -32,64 +32,65 @@ argument_spec = meraki_argument_spec() # Add arguments specific for this module argument_spec.update(dict( state=dict(type="str", default="present", choices=["present"]), - name=dict(type="str"), - enabled=dict(type="bool"), + activeDirectory=dict(type="dict"), + adultContentFilteringEnabled=dict(type="bool"), + apTagsAndVlanIds=dict(type="list"), authMode=dict(type="str"), - enterpriseAdminAccess=dict(type="str"), - encryptionMode=dict(type="str"), - psk=dict(type="str"), - wpaEncryptionMode=dict(type="str"), - dot11w=dict(type="dict"), + availabilityTags=dict(type="list"), + availableOnAllAps=dict(type="bool"), + bandSelection=dict(type="str"), + concentratorNetworkId=dict(type="str"), + defaultVlanId=dict(type="int"), + disassociateClientsOnVpnFailover=dict(type="bool"), + dnsRewrite=dict(type="dict"), dot11r=dict(type="dict"), - splashPage=dict(type="str"), - splashGuestSponsorDomains=dict(type="list"), - oauth=dict(type="dict"), - localRadius=dict(type="dict"), + dot11w=dict(type="dict"), + enabled=dict(type="bool"), + encryptionMode=dict(type="str"), + enterpriseAdminAccess=dict(type="str"), + gre=dict(type="dict"), + ipAssignmentMode=dict(type="str"), + lanIsolationEnabled=dict(type="bool"), ldap=dict(type="dict"), - activeDirectory=dict(type="dict"), - radiusServers=dict(type="list"), - radiusProxyEnabled=dict(type="bool"), - radiusTestingEnabled=dict(type="bool"), - radiusCalledStationId=dict(type="str"), + localRadius=dict(type="dict"), + mandatoryDhcpEnabled=dict(type="bool"), + minBitrate=dict(type="float"), + name=dict(type="str"), + namedVlans=dict(type="dict"), + oauth=dict(type="dict"), + perClientBandwidthLimitDown=dict(type="int"), + perClientBandwidthLimitUp=dict(type="int"), + perSsidBandwidthLimitDown=dict(type="int"), + perSsidBandwidthLimitUp=dict(type="int"), + psk=dict(type="str"), + radiusAccountingEnabled=dict(type="bool"), + radiusAccountingInterimInterval=dict(type="int"), + radiusAccountingServers=dict(type="list"), + radiusAttributeForGroupPolicies=dict(type="str"), radiusAuthenticationNasId=dict(type="str"), - radiusServerTimeout=dict(type="int"), - radiusServerAttemptsLimit=dict(type="int"), - radiusFallbackEnabled=dict(type="bool"), + radiusCalledStationId=dict(type="str"), radiusCoaEnabled=dict(type="bool"), radiusFailoverPolicy=dict(type="str"), + radiusFallbackEnabled=dict(type="bool"), + radiusGuestVlanEnabled=dict(type="bool"), + radiusGuestVlanId=dict(type="int"), radiusLoadBalancingPolicy=dict(type="str"), - radiusAccountingEnabled=dict(type="bool"), - radiusAccountingServers=dict(type="list"), - radiusAccountingInterimInterval=dict(type="int"), - radiusAttributeForGroupPolicies=dict(type="str"), - ipAssignmentMode=dict(type="str"), - useVlanTagging=dict(type="bool"), - concentratorNetworkId=dict(type="str"), + radiusOverride=dict(type="bool"), + radiusProxyEnabled=dict(type="bool"), + radiusServerAttemptsLimit=dict(type="int"), + radiusServerTimeout=dict(type="int"), + radiusServers=dict(type="list"), + radiusTestingEnabled=dict(type="bool"), secondaryConcentratorNetworkId=dict(type="str"), - disassociateClientsOnVpnFailover=dict(type="bool"), + speedBurst=dict(type="dict"), + splashGuestSponsorDomains=dict(type="list"), + splashPage=dict(type="str"), + useVlanTagging=dict(type="bool"), + visible=dict(type="bool"), vlanId=dict(type="int"), - defaultVlanId=dict(type="int"), - apTagsAndVlanIds=dict(type="list"), walledGardenEnabled=dict(type="bool"), walledGardenRanges=dict(type="list"), - gre=dict(type="dict"), - radiusOverride=dict(type="bool"), - radiusGuestVlanEnabled=dict(type="bool"), - radiusGuestVlanId=dict(type="int"), - minBitrate=dict(type="float"), - bandSelection=dict(type="str"), - perClientBandwidthLimitUp=dict(type="int"), - perClientBandwidthLimitDown=dict(type="int"), - perSsidBandwidthLimitUp=dict(type="int"), - perSsidBandwidthLimitDown=dict(type="int"), - lanIsolationEnabled=dict(type="bool"), - visible=dict(type="bool"), - availableOnAllAps=dict(type="bool"), - availabilityTags=dict(type="list"), - mandatoryDhcpEnabled=dict(type="bool"), - adultContentFilteringEnabled=dict(type="bool"), - dnsRewrite=dict(type="dict"), - speedBurst=dict(type="dict"), + wpaEncryptionMode=dict(type="str"), networkId=dict(type="str"), number=dict(type="str"), )) @@ -106,64 +107,65 @@ class NetworksWirelessSsids(object): def __init__(self, params, meraki): self.meraki = meraki self.new_object = dict( - name=params.get("name"), - enabled=params.get("enabled"), + activeDirectory=params.get("activeDirectory"), + adultContentFilteringEnabled=params.get("adultContentFilteringEnabled"), + apTagsAndVlanIds=params.get("apTagsAndVlanIds"), authMode=params.get("authMode"), - enterpriseAdminAccess=params.get("enterpriseAdminAccess"), - encryptionMode=params.get("encryptionMode"), - psk=params.get("psk"), - wpaEncryptionMode=params.get("wpaEncryptionMode"), - dot11w=params.get("dot11w"), + availabilityTags=params.get("availabilityTags"), + availableOnAllAps=params.get("availableOnAllAps"), + bandSelection=params.get("bandSelection"), + concentratorNetworkId=params.get("concentratorNetworkId"), + defaultVlanId=params.get("defaultVlanId"), + disassociateClientsOnVpnFailover=params.get("disassociateClientsOnVpnFailover"), + dnsRewrite=params.get("dnsRewrite"), dot11r=params.get("dot11r"), - splashPage=params.get("splashPage"), - splashGuestSponsorDomains=params.get("splashGuestSponsorDomains"), - oauth=params.get("oauth"), - localRadius=params.get("localRadius"), + dot11w=params.get("dot11w"), + enabled=params.get("enabled"), + encryptionMode=params.get("encryptionMode"), + enterpriseAdminAccess=params.get("enterpriseAdminAccess"), + gre=params.get("gre"), + ipAssignmentMode=params.get("ipAssignmentMode"), + lanIsolationEnabled=params.get("lanIsolationEnabled"), ldap=params.get("ldap"), - activeDirectory=params.get("activeDirectory"), - radiusServers=params.get("radiusServers"), - radiusProxyEnabled=params.get("radiusProxyEnabled"), - radiusTestingEnabled=params.get("radiusTestingEnabled"), - radiusCalledStationId=params.get("radiusCalledStationId"), + localRadius=params.get("localRadius"), + mandatoryDhcpEnabled=params.get("mandatoryDhcpEnabled"), + minBitrate=params.get("minBitrate"), + name=params.get("name"), + namedVlans=params.get("namedVlans"), + oauth=params.get("oauth"), + perClientBandwidthLimitDown=params.get("perClientBandwidthLimitDown"), + perClientBandwidthLimitUp=params.get("perClientBandwidthLimitUp"), + perSsidBandwidthLimitDown=params.get("perSsidBandwidthLimitDown"), + perSsidBandwidthLimitUp=params.get("perSsidBandwidthLimitUp"), + psk=params.get("psk"), + radiusAccountingEnabled=params.get("radiusAccountingEnabled"), + radiusAccountingInterimInterval=params.get("radiusAccountingInterimInterval"), + radiusAccountingServers=params.get("radiusAccountingServers"), + radiusAttributeForGroupPolicies=params.get("radiusAttributeForGroupPolicies"), radiusAuthenticationNasId=params.get("radiusAuthenticationNasId"), - radiusServerTimeout=params.get("radiusServerTimeout"), - radiusServerAttemptsLimit=params.get("radiusServerAttemptsLimit"), - radiusFallbackEnabled=params.get("radiusFallbackEnabled"), + radiusCalledStationId=params.get("radiusCalledStationId"), radiusCoaEnabled=params.get("radiusCoaEnabled"), radiusFailoverPolicy=params.get("radiusFailoverPolicy"), + radiusFallbackEnabled=params.get("radiusFallbackEnabled"), + radiusGuestVlanEnabled=params.get("radiusGuestVlanEnabled"), + radiusGuestVlanId=params.get("radiusGuestVlanId"), radiusLoadBalancingPolicy=params.get("radiusLoadBalancingPolicy"), - radiusAccountingEnabled=params.get("radiusAccountingEnabled"), - radiusAccountingServers=params.get("radiusAccountingServers"), - radiusAccountingInterimInterval=params.get("radiusAccountingInterimInterval"), - radiusAttributeForGroupPolicies=params.get("radiusAttributeForGroupPolicies"), - ipAssignmentMode=params.get("ipAssignmentMode"), - useVlanTagging=params.get("useVlanTagging"), - concentratorNetworkId=params.get("concentratorNetworkId"), + radiusOverride=params.get("radiusOverride"), + radiusProxyEnabled=params.get("radiusProxyEnabled"), + radiusServerAttemptsLimit=params.get("radiusServerAttemptsLimit"), + radiusServerTimeout=params.get("radiusServerTimeout"), + radiusServers=params.get("radiusServers"), + radiusTestingEnabled=params.get("radiusTestingEnabled"), secondaryConcentratorNetworkId=params.get("secondaryConcentratorNetworkId"), - disassociateClientsOnVpnFailover=params.get("disassociateClientsOnVpnFailover"), + speedBurst=params.get("speedBurst"), + splashGuestSponsorDomains=params.get("splashGuestSponsorDomains"), + splashPage=params.get("splashPage"), + useVlanTagging=params.get("useVlanTagging"), + visible=params.get("visible"), vlanId=params.get("vlanId"), - defaultVlanId=params.get("defaultVlanId"), - apTagsAndVlanIds=params.get("apTagsAndVlanIds"), walledGardenEnabled=params.get("walledGardenEnabled"), walledGardenRanges=params.get("walledGardenRanges"), - gre=params.get("gre"), - radiusOverride=params.get("radiusOverride"), - radiusGuestVlanEnabled=params.get("radiusGuestVlanEnabled"), - radiusGuestVlanId=params.get("radiusGuestVlanId"), - minBitrate=params.get("minBitrate"), - bandSelection=params.get("bandSelection"), - perClientBandwidthLimitUp=params.get("perClientBandwidthLimitUp"), - perClientBandwidthLimitDown=params.get("perClientBandwidthLimitDown"), - perSsidBandwidthLimitUp=params.get("perSsidBandwidthLimitUp"), - perSsidBandwidthLimitDown=params.get("perSsidBandwidthLimitDown"), - lanIsolationEnabled=params.get("lanIsolationEnabled"), - visible=params.get("visible"), - availableOnAllAps=params.get("availableOnAllAps"), - availabilityTags=params.get("availabilityTags"), - mandatoryDhcpEnabled=params.get("mandatoryDhcpEnabled"), - adultContentFilteringEnabled=params.get("adultContentFilteringEnabled"), - dnsRewrite=params.get("dnsRewrite"), - speedBurst=params.get("speedBurst"), + wpaEncryptionMode=params.get("wpaEncryptionMode"), network_id=params.get("networkId"), number=params.get("number"), ) @@ -186,164 +188,167 @@ class NetworksWirelessSsids(object): def update_by_id_params(self): new_object_params = {} - if self.new_object.get('name') is not None or self.new_object.get('name') is not None: - new_object_params['name'] = self.new_object.get('name') or \ - self.new_object.get('name') - if self.new_object.get('enabled') is not None or self.new_object.get('enabled') is not None: - new_object_params['enabled'] = self.new_object.get('enabled') + if self.new_object.get('activeDirectory') is not None or self.new_object.get('active_directory') is not None: + new_object_params['activeDirectory'] = self.new_object.get('activeDirectory') or \ + self.new_object.get('active_directory') + if self.new_object.get('adultContentFilteringEnabled') is not None or self.new_object.get('adult_content_filtering_enabled') is not None: + new_object_params['adultContentFilteringEnabled'] = self.new_object.get('adultContentFilteringEnabled') + if self.new_object.get('apTagsAndVlanIds') is not None or self.new_object.get('ap_tags_and_vlan_ids') is not None: + new_object_params['apTagsAndVlanIds'] = self.new_object.get('apTagsAndVlanIds') or \ + self.new_object.get('ap_tags_and_vlan_ids') if self.new_object.get('authMode') is not None or self.new_object.get('auth_mode') is not None: new_object_params['authMode'] = self.new_object.get('authMode') or \ self.new_object.get('auth_mode') - if self.new_object.get('enterpriseAdminAccess') is not None or self.new_object.get('enterprise_admin_access') is not None: - new_object_params['enterpriseAdminAccess'] = self.new_object.get('enterpriseAdminAccess') or \ - self.new_object.get('enterprise_admin_access') - if self.new_object.get('encryptionMode') is not None or self.new_object.get('encryption_mode') is not None: - new_object_params['encryptionMode'] = self.new_object.get('encryptionMode') or \ - self.new_object.get('encryption_mode') - if self.new_object.get('psk') is not None or self.new_object.get('psk') is not None: - new_object_params['psk'] = self.new_object.get('psk') or \ - self.new_object.get('psk') - if self.new_object.get('wpaEncryptionMode') is not None or self.new_object.get('wpa_encryption_mode') is not None: - new_object_params['wpaEncryptionMode'] = self.new_object.get('wpaEncryptionMode') or \ - self.new_object.get('wpa_encryption_mode') - if self.new_object.get('dot11w') is not None or self.new_object.get('dot11w') is not None: - new_object_params['dot11w'] = self.new_object.get('dot11w') or \ - self.new_object.get('dot11w') + if self.new_object.get('availabilityTags') is not None or self.new_object.get('availability_tags') is not None: + new_object_params['availabilityTags'] = self.new_object.get('availabilityTags') or \ + self.new_object.get('availability_tags') + if self.new_object.get('availableOnAllAps') is not None or self.new_object.get('available_on_all_aps') is not None: + new_object_params['availableOnAllAps'] = self.new_object.get('availableOnAllAps') + if self.new_object.get('bandSelection') is not None or self.new_object.get('band_selection') is not None: + new_object_params['bandSelection'] = self.new_object.get('bandSelection') or \ + self.new_object.get('band_selection') + if self.new_object.get('concentratorNetworkId') is not None or self.new_object.get('concentrator_network_id') is not None: + new_object_params['concentratorNetworkId'] = self.new_object.get('concentratorNetworkId') or \ + self.new_object.get('concentrator_network_id') + if self.new_object.get('defaultVlanId') is not None or self.new_object.get('default_vlan_id') is not None: + new_object_params['defaultVlanId'] = self.new_object.get('defaultVlanId') or \ + self.new_object.get('default_vlan_id') + if self.new_object.get('disassociateClientsOnVpnFailover') is not None or self.new_object.get('disassociate_clients_on_vpn_failover') is not None: + new_object_params['disassociateClientsOnVpnFailover'] = self.new_object.get('disassociateClientsOnVpnFailover') + if self.new_object.get('dnsRewrite') is not None or self.new_object.get('dns_rewrite') is not None: + new_object_params['dnsRewrite'] = self.new_object.get('dnsRewrite') or \ + self.new_object.get('dns_rewrite') if self.new_object.get('dot11r') is not None or self.new_object.get('dot11r') is not None: new_object_params['dot11r'] = self.new_object.get('dot11r') or \ self.new_object.get('dot11r') - if self.new_object.get('splashPage') is not None or self.new_object.get('splash_page') is not None: - new_object_params['splashPage'] = self.new_object.get('splashPage') or \ - self.new_object.get('splash_page') - if self.new_object.get('splashGuestSponsorDomains') is not None or self.new_object.get('splash_guest_sponsor_domains') is not None: - new_object_params['splashGuestSponsorDomains'] = self.new_object.get('splashGuestSponsorDomains') or \ - self.new_object.get('splash_guest_sponsor_domains') - if self.new_object.get('oauth') is not None or self.new_object.get('oauth') is not None: - new_object_params['oauth'] = self.new_object.get('oauth') or \ - self.new_object.get('oauth') - if self.new_object.get('localRadius') is not None or self.new_object.get('local_radius') is not None: - new_object_params['localRadius'] = self.new_object.get('localRadius') or \ - self.new_object.get('local_radius') + if self.new_object.get('dot11w') is not None or self.new_object.get('dot11w') is not None: + new_object_params['dot11w'] = self.new_object.get('dot11w') or \ + self.new_object.get('dot11w') + if self.new_object.get('enabled') is not None or self.new_object.get('enabled') is not None: + new_object_params['enabled'] = self.new_object.get('enabled') + if self.new_object.get('encryptionMode') is not None or self.new_object.get('encryption_mode') is not None: + new_object_params['encryptionMode'] = self.new_object.get('encryptionMode') or \ + self.new_object.get('encryption_mode') + if self.new_object.get('enterpriseAdminAccess') is not None or self.new_object.get('enterprise_admin_access') is not None: + new_object_params['enterpriseAdminAccess'] = self.new_object.get('enterpriseAdminAccess') or \ + self.new_object.get('enterprise_admin_access') + if self.new_object.get('gre') is not None or self.new_object.get('gre') is not None: + new_object_params['gre'] = self.new_object.get('gre') or \ + self.new_object.get('gre') + if self.new_object.get('ipAssignmentMode') is not None or self.new_object.get('ip_assignment_mode') is not None: + new_object_params['ipAssignmentMode'] = self.new_object.get('ipAssignmentMode') or \ + self.new_object.get('ip_assignment_mode') + if self.new_object.get('lanIsolationEnabled') is not None or self.new_object.get('lan_isolation_enabled') is not None: + new_object_params['lanIsolationEnabled'] = self.new_object.get('lanIsolationEnabled') if self.new_object.get('ldap') is not None or self.new_object.get('ldap') is not None: new_object_params['ldap'] = self.new_object.get('ldap') or \ self.new_object.get('ldap') - if self.new_object.get('activeDirectory') is not None or self.new_object.get('active_directory') is not None: - new_object_params['activeDirectory'] = self.new_object.get('activeDirectory') or \ - self.new_object.get('active_directory') - if self.new_object.get('radiusServers') is not None or self.new_object.get('radius_servers') is not None: - new_object_params['radiusServers'] = self.new_object.get('radiusServers') or \ - self.new_object.get('radius_servers') - if self.new_object.get('radiusProxyEnabled') is not None or self.new_object.get('radius_proxy_enabled') is not None: - new_object_params['radiusProxyEnabled'] = self.new_object.get('radiusProxyEnabled') - if self.new_object.get('radiusTestingEnabled') is not None or self.new_object.get('radius_testing_enabled') is not None: - new_object_params['radiusTestingEnabled'] = self.new_object.get('radiusTestingEnabled') - if self.new_object.get('radiusCalledStationId') is not None or self.new_object.get('radius_called_station_id') is not None: - new_object_params['radiusCalledStationId'] = self.new_object.get('radiusCalledStationId') or \ - self.new_object.get('radius_called_station_id') + if self.new_object.get('localRadius') is not None or self.new_object.get('local_radius') is not None: + new_object_params['localRadius'] = self.new_object.get('localRadius') or \ + self.new_object.get('local_radius') + if self.new_object.get('mandatoryDhcpEnabled') is not None or self.new_object.get('mandatory_dhcp_enabled') is not None: + new_object_params['mandatoryDhcpEnabled'] = self.new_object.get('mandatoryDhcpEnabled') + if self.new_object.get('minBitrate') is not None or self.new_object.get('min_bitrate') is not None: + new_object_params['minBitrate'] = self.new_object.get('minBitrate') or \ + self.new_object.get('min_bitrate') + if self.new_object.get('name') is not None or self.new_object.get('name') is not None: + new_object_params['name'] = self.new_object.get('name') or \ + self.new_object.get('name') + if self.new_object.get('namedVlans') is not None or self.new_object.get('named_vlans') is not None: + new_object_params['namedVlans'] = self.new_object.get('namedVlans') or \ + self.new_object.get('named_vlans') + if self.new_object.get('oauth') is not None or self.new_object.get('oauth') is not None: + new_object_params['oauth'] = self.new_object.get('oauth') or \ + self.new_object.get('oauth') + if self.new_object.get('perClientBandwidthLimitDown') is not None or self.new_object.get('per_client_bandwidth_limit_down') is not None: + new_object_params['perClientBandwidthLimitDown'] = self.new_object.get('perClientBandwidthLimitDown') or \ + self.new_object.get('per_client_bandwidth_limit_down') + if self.new_object.get('perClientBandwidthLimitUp') is not None or self.new_object.get('per_client_bandwidth_limit_up') is not None: + new_object_params['perClientBandwidthLimitUp'] = self.new_object.get('perClientBandwidthLimitUp') or \ + self.new_object.get('per_client_bandwidth_limit_up') + if self.new_object.get('perSsidBandwidthLimitDown') is not None or self.new_object.get('per_ssid_bandwidth_limit_down') is not None: + new_object_params['perSsidBandwidthLimitDown'] = self.new_object.get('perSsidBandwidthLimitDown') or \ + self.new_object.get('per_ssid_bandwidth_limit_down') + if self.new_object.get('perSsidBandwidthLimitUp') is not None or self.new_object.get('per_ssid_bandwidth_limit_up') is not None: + new_object_params['perSsidBandwidthLimitUp'] = self.new_object.get('perSsidBandwidthLimitUp') or \ + self.new_object.get('per_ssid_bandwidth_limit_up') + if self.new_object.get('psk') is not None or self.new_object.get('psk') is not None: + new_object_params['psk'] = self.new_object.get('psk') or \ + self.new_object.get('psk') + if self.new_object.get('radiusAccountingEnabled') is not None or self.new_object.get('radius_accounting_enabled') is not None: + new_object_params['radiusAccountingEnabled'] = self.new_object.get('radiusAccountingEnabled') + if self.new_object.get('radiusAccountingInterimInterval') is not None or self.new_object.get('radius_accounting_interim_interval') is not None: + new_object_params['radiusAccountingInterimInterval'] = self.new_object.get('radiusAccountingInterimInterval') or \ + self.new_object.get('radius_accounting_interim_interval') + if self.new_object.get('radiusAccountingServers') is not None or self.new_object.get('radius_accounting_servers') is not None: + new_object_params['radiusAccountingServers'] = self.new_object.get('radiusAccountingServers') or \ + self.new_object.get('radius_accounting_servers') + if self.new_object.get('radiusAttributeForGroupPolicies') is not None or self.new_object.get('radius_attribute_for_group_policies') is not None: + new_object_params['radiusAttributeForGroupPolicies'] = self.new_object.get('radiusAttributeForGroupPolicies') or \ + self.new_object.get('radius_attribute_for_group_policies') if self.new_object.get('radiusAuthenticationNasId') is not None or self.new_object.get('radius_authentication_nas_id') is not None: new_object_params['radiusAuthenticationNasId'] = self.new_object.get('radiusAuthenticationNasId') or \ self.new_object.get('radius_authentication_nas_id') - if self.new_object.get('radiusServerTimeout') is not None or self.new_object.get('radius_server_timeout') is not None: - new_object_params['radiusServerTimeout'] = self.new_object.get('radiusServerTimeout') or \ - self.new_object.get('radius_server_timeout') - if self.new_object.get('radiusServerAttemptsLimit') is not None or self.new_object.get('radius_server_attempts_limit') is not None: - new_object_params['radiusServerAttemptsLimit'] = self.new_object.get('radiusServerAttemptsLimit') or \ - self.new_object.get('radius_server_attempts_limit') - if self.new_object.get('radiusFallbackEnabled') is not None or self.new_object.get('radius_fallback_enabled') is not None: - new_object_params['radiusFallbackEnabled'] = self.new_object.get('radiusFallbackEnabled') + if self.new_object.get('radiusCalledStationId') is not None or self.new_object.get('radius_called_station_id') is not None: + new_object_params['radiusCalledStationId'] = self.new_object.get('radiusCalledStationId') or \ + self.new_object.get('radius_called_station_id') if self.new_object.get('radiusCoaEnabled') is not None or self.new_object.get('radius_coa_enabled') is not None: new_object_params['radiusCoaEnabled'] = self.new_object.get('radiusCoaEnabled') if self.new_object.get('radiusFailoverPolicy') is not None or self.new_object.get('radius_failover_policy') is not None: new_object_params['radiusFailoverPolicy'] = self.new_object.get('radiusFailoverPolicy') or \ self.new_object.get('radius_failover_policy') + if self.new_object.get('radiusFallbackEnabled') is not None or self.new_object.get('radius_fallback_enabled') is not None: + new_object_params['radiusFallbackEnabled'] = self.new_object.get('radiusFallbackEnabled') + if self.new_object.get('radiusGuestVlanEnabled') is not None or self.new_object.get('radius_guest_vlan_enabled') is not None: + new_object_params['radiusGuestVlanEnabled'] = self.new_object.get('radiusGuestVlanEnabled') + if self.new_object.get('radiusGuestVlanId') is not None or self.new_object.get('radius_guest_vlan_id') is not None: + new_object_params['radiusGuestVlanId'] = self.new_object.get('radiusGuestVlanId') or \ + self.new_object.get('radius_guest_vlan_id') if self.new_object.get('radiusLoadBalancingPolicy') is not None or self.new_object.get('radius_load_balancing_policy') is not None: new_object_params['radiusLoadBalancingPolicy'] = self.new_object.get('radiusLoadBalancingPolicy') or \ self.new_object.get('radius_load_balancing_policy') - if self.new_object.get('radiusAccountingEnabled') is not None or self.new_object.get('radius_accounting_enabled') is not None: - new_object_params['radiusAccountingEnabled'] = self.new_object.get('radiusAccountingEnabled') - if self.new_object.get('radiusAccountingServers') is not None or self.new_object.get('radius_accounting_servers') is not None: - new_object_params['radiusAccountingServers'] = self.new_object.get('radiusAccountingServers') or \ - self.new_object.get('radius_accounting_servers') - if self.new_object.get('radiusAccountingInterimInterval') is not None or self.new_object.get('radius_accounting_interim_interval') is not None: - new_object_params['radiusAccountingInterimInterval'] = self.new_object.get('radiusAccountingInterimInterval') or \ - self.new_object.get('radius_accounting_interim_interval') - if self.new_object.get('radiusAttributeForGroupPolicies') is not None or self.new_object.get('radius_attribute_for_group_policies') is not None: - new_object_params['radiusAttributeForGroupPolicies'] = self.new_object.get('radiusAttributeForGroupPolicies') or \ - self.new_object.get('radius_attribute_for_group_policies') - if self.new_object.get('ipAssignmentMode') is not None or self.new_object.get('ip_assignment_mode') is not None: - new_object_params['ipAssignmentMode'] = self.new_object.get('ipAssignmentMode') or \ - self.new_object.get('ip_assignment_mode') - if self.new_object.get('useVlanTagging') is not None or self.new_object.get('use_vlan_tagging') is not None: - new_object_params['useVlanTagging'] = self.new_object.get('useVlanTagging') - if self.new_object.get('concentratorNetworkId') is not None or self.new_object.get('concentrator_network_id') is not None: - new_object_params['concentratorNetworkId'] = self.new_object.get('concentratorNetworkId') or \ - self.new_object.get('concentrator_network_id') + if self.new_object.get('radiusOverride') is not None or self.new_object.get('radius_override') is not None: + new_object_params['radiusOverride'] = self.new_object.get('radiusOverride') + if self.new_object.get('radiusProxyEnabled') is not None or self.new_object.get('radius_proxy_enabled') is not None: + new_object_params['radiusProxyEnabled'] = self.new_object.get('radiusProxyEnabled') + if self.new_object.get('radiusServerAttemptsLimit') is not None or self.new_object.get('radius_server_attempts_limit') is not None: + new_object_params['radiusServerAttemptsLimit'] = self.new_object.get('radiusServerAttemptsLimit') or \ + self.new_object.get('radius_server_attempts_limit') + if self.new_object.get('radiusServerTimeout') is not None or self.new_object.get('radius_server_timeout') is not None: + new_object_params['radiusServerTimeout'] = self.new_object.get('radiusServerTimeout') or \ + self.new_object.get('radius_server_timeout') + if self.new_object.get('radiusServers') is not None or self.new_object.get('radius_servers') is not None: + new_object_params['radiusServers'] = self.new_object.get('radiusServers') or \ + self.new_object.get('radius_servers') + if self.new_object.get('radiusTestingEnabled') is not None or self.new_object.get('radius_testing_enabled') is not None: + new_object_params['radiusTestingEnabled'] = self.new_object.get('radiusTestingEnabled') if self.new_object.get('secondaryConcentratorNetworkId') is not None or self.new_object.get('secondary_concentrator_network_id') is not None: new_object_params['secondaryConcentratorNetworkId'] = self.new_object.get('secondaryConcentratorNetworkId') or \ self.new_object.get('secondary_concentrator_network_id') - if self.new_object.get('disassociateClientsOnVpnFailover') is not None or self.new_object.get('disassociate_clients_on_vpn_failover') is not None: - new_object_params['disassociateClientsOnVpnFailover'] = self.new_object.get('disassociateClientsOnVpnFailover') + if self.new_object.get('speedBurst') is not None or self.new_object.get('speed_burst') is not None: + new_object_params['speedBurst'] = self.new_object.get('speedBurst') or \ + self.new_object.get('speed_burst') + if self.new_object.get('splashGuestSponsorDomains') is not None or self.new_object.get('splash_guest_sponsor_domains') is not None: + new_object_params['splashGuestSponsorDomains'] = self.new_object.get('splashGuestSponsorDomains') or \ + self.new_object.get('splash_guest_sponsor_domains') + if self.new_object.get('splashPage') is not None or self.new_object.get('splash_page') is not None: + new_object_params['splashPage'] = self.new_object.get('splashPage') or \ + self.new_object.get('splash_page') + if self.new_object.get('useVlanTagging') is not None or self.new_object.get('use_vlan_tagging') is not None: + new_object_params['useVlanTagging'] = self.new_object.get('useVlanTagging') + if self.new_object.get('visible') is not None or self.new_object.get('visible') is not None: + new_object_params['visible'] = self.new_object.get('visible') if self.new_object.get('vlanId') is not None or self.new_object.get('vlan_id') is not None: new_object_params['vlanId'] = self.new_object.get('vlanId') or \ self.new_object.get('vlan_id') - if self.new_object.get('defaultVlanId') is not None or self.new_object.get('default_vlan_id') is not None: - new_object_params['defaultVlanId'] = self.new_object.get('defaultVlanId') or \ - self.new_object.get('default_vlan_id') - if self.new_object.get('apTagsAndVlanIds') is not None or self.new_object.get('ap_tags_and_vlan_ids') is not None: - new_object_params['apTagsAndVlanIds'] = self.new_object.get('apTagsAndVlanIds') or \ - self.new_object.get('ap_tags_and_vlan_ids') if self.new_object.get('walledGardenEnabled') is not None or self.new_object.get('walled_garden_enabled') is not None: new_object_params['walledGardenEnabled'] = self.new_object.get('walledGardenEnabled') if self.new_object.get('walledGardenRanges') is not None or self.new_object.get('walled_garden_ranges') is not None: new_object_params['walledGardenRanges'] = self.new_object.get('walledGardenRanges') or \ self.new_object.get('walled_garden_ranges') - if self.new_object.get('gre') is not None or self.new_object.get('gre') is not None: - new_object_params['gre'] = self.new_object.get('gre') or \ - self.new_object.get('gre') - if self.new_object.get('radiusOverride') is not None or self.new_object.get('radius_override') is not None: - new_object_params['radiusOverride'] = self.new_object.get('radiusOverride') - if self.new_object.get('radiusGuestVlanEnabled') is not None or self.new_object.get('radius_guest_vlan_enabled') is not None: - new_object_params['radiusGuestVlanEnabled'] = self.new_object.get('radiusGuestVlanEnabled') - if self.new_object.get('radiusGuestVlanId') is not None or self.new_object.get('radius_guest_vlan_id') is not None: - new_object_params['radiusGuestVlanId'] = self.new_object.get('radiusGuestVlanId') or \ - self.new_object.get('radius_guest_vlan_id') - if self.new_object.get('minBitrate') is not None or self.new_object.get('min_bitrate') is not None: - new_object_params['minBitrate'] = self.new_object.get('minBitrate') or \ - self.new_object.get('min_bitrate') - if self.new_object.get('bandSelection') is not None or self.new_object.get('band_selection') is not None: - new_object_params['bandSelection'] = self.new_object.get('bandSelection') or \ - self.new_object.get('band_selection') - if self.new_object.get('perClientBandwidthLimitUp') is not None or self.new_object.get('per_client_bandwidth_limit_up') is not None: - new_object_params['perClientBandwidthLimitUp'] = self.new_object.get('perClientBandwidthLimitUp') or \ - self.new_object.get('per_client_bandwidth_limit_up') - if self.new_object.get('perClientBandwidthLimitDown') is not None or self.new_object.get('per_client_bandwidth_limit_down') is not None: - new_object_params['perClientBandwidthLimitDown'] = self.new_object.get('perClientBandwidthLimitDown') or \ - self.new_object.get('per_client_bandwidth_limit_down') - if self.new_object.get('perSsidBandwidthLimitUp') is not None or self.new_object.get('per_ssid_bandwidth_limit_up') is not None: - new_object_params['perSsidBandwidthLimitUp'] = self.new_object.get('perSsidBandwidthLimitUp') or \ - self.new_object.get('per_ssid_bandwidth_limit_up') - if self.new_object.get('perSsidBandwidthLimitDown') is not None or self.new_object.get('per_ssid_bandwidth_limit_down') is not None: - new_object_params['perSsidBandwidthLimitDown'] = self.new_object.get('perSsidBandwidthLimitDown') or \ - self.new_object.get('per_ssid_bandwidth_limit_down') - if self.new_object.get('lanIsolationEnabled') is not None or self.new_object.get('lan_isolation_enabled') is not None: - new_object_params['lanIsolationEnabled'] = self.new_object.get('lanIsolationEnabled') - if self.new_object.get('visible') is not None or self.new_object.get('visible') is not None: - new_object_params['visible'] = self.new_object.get('visible') - if self.new_object.get('availableOnAllAps') is not None or self.new_object.get('available_on_all_aps') is not None: - new_object_params['availableOnAllAps'] = self.new_object.get('availableOnAllAps') - if self.new_object.get('availabilityTags') is not None or self.new_object.get('availability_tags') is not None: - new_object_params['availabilityTags'] = self.new_object.get('availabilityTags') or \ - self.new_object.get('availability_tags') - if self.new_object.get('mandatoryDhcpEnabled') is not None or self.new_object.get('mandatory_dhcp_enabled') is not None: - new_object_params['mandatoryDhcpEnabled'] = self.new_object.get('mandatoryDhcpEnabled') - if self.new_object.get('adultContentFilteringEnabled') is not None or self.new_object.get('adult_content_filtering_enabled') is not None: - new_object_params['adultContentFilteringEnabled'] = self.new_object.get('adultContentFilteringEnabled') - if self.new_object.get('dnsRewrite') is not None or self.new_object.get('dns_rewrite') is not None: - new_object_params['dnsRewrite'] = self.new_object.get('dnsRewrite') or \ - self.new_object.get('dns_rewrite') - if self.new_object.get('speedBurst') is not None or self.new_object.get('speed_burst') is not None: - new_object_params['speedBurst'] = self.new_object.get('speedBurst') or \ - self.new_object.get('speed_burst') + if self.new_object.get('wpaEncryptionMode') is not None or self.new_object.get('wpa_encryption_mode') is not None: + new_object_params['wpaEncryptionMode'] = self.new_object.get('wpaEncryptionMode') or \ + self.new_object.get('wpa_encryption_mode') if self.new_object.get('networkId') is not None or self.new_object.get('network_id') is not None: new_object_params['networkId'] = self.new_object.get('networkId') or \ self.new_object.get('network_id') @@ -421,64 +426,65 @@ class NetworksWirelessSsids(object): requested_obj = self.new_object obj_params = [ - ("name", "name"), - ("enabled", "enabled"), + ("activeDirectory", "activeDirectory"), + ("adultContentFilteringEnabled", "adultContentFilteringEnabled"), + ("apTagsAndVlanIds", "apTagsAndVlanIds"), ("authMode", "authMode"), - ("enterpriseAdminAccess", "enterpriseAdminAccess"), - ("encryptionMode", "encryptionMode"), - ("psk", "psk"), - ("wpaEncryptionMode", "wpaEncryptionMode"), - ("dot11w", "dot11w"), + ("availabilityTags", "availabilityTags"), + ("availableOnAllAps", "availableOnAllAps"), + ("bandSelection", "bandSelection"), + ("concentratorNetworkId", "concentratorNetworkId"), + ("defaultVlanId", "defaultVlanId"), + ("disassociateClientsOnVpnFailover", "disassociateClientsOnVpnFailover"), + ("dnsRewrite", "dnsRewrite"), ("dot11r", "dot11r"), - ("splashPage", "splashPage"), - ("splashGuestSponsorDomains", "splashGuestSponsorDomains"), - ("oauth", "oauth"), - ("localRadius", "localRadius"), + ("dot11w", "dot11w"), + ("enabled", "enabled"), + ("encryptionMode", "encryptionMode"), + ("enterpriseAdminAccess", "enterpriseAdminAccess"), + ("gre", "gre"), + ("ipAssignmentMode", "ipAssignmentMode"), + ("lanIsolationEnabled", "lanIsolationEnabled"), ("ldap", "ldap"), - ("activeDirectory", "activeDirectory"), - ("radiusServers", "radiusServers"), - ("radiusProxyEnabled", "radiusProxyEnabled"), - ("radiusTestingEnabled", "radiusTestingEnabled"), - ("radiusCalledStationId", "radiusCalledStationId"), + ("localRadius", "localRadius"), + ("mandatoryDhcpEnabled", "mandatoryDhcpEnabled"), + ("minBitrate", "minBitrate"), + ("name", "name"), + ("namedVlans", "namedVlans"), + ("oauth", "oauth"), + ("perClientBandwidthLimitDown", "perClientBandwidthLimitDown"), + ("perClientBandwidthLimitUp", "perClientBandwidthLimitUp"), + ("perSsidBandwidthLimitDown", "perSsidBandwidthLimitDown"), + ("perSsidBandwidthLimitUp", "perSsidBandwidthLimitUp"), + ("psk", "psk"), + ("radiusAccountingEnabled", "radiusAccountingEnabled"), + ("radiusAccountingInterimInterval", "radiusAccountingInterimInterval"), + ("radiusAccountingServers", "radiusAccountingServers"), + ("radiusAttributeForGroupPolicies", "radiusAttributeForGroupPolicies"), ("radiusAuthenticationNasId", "radiusAuthenticationNasId"), - ("radiusServerTimeout", "radiusServerTimeout"), - ("radiusServerAttemptsLimit", "radiusServerAttemptsLimit"), - ("radiusFallbackEnabled", "radiusFallbackEnabled"), + ("radiusCalledStationId", "radiusCalledStationId"), ("radiusCoaEnabled", "radiusCoaEnabled"), ("radiusFailoverPolicy", "radiusFailoverPolicy"), + ("radiusFallbackEnabled", "radiusFallbackEnabled"), + ("radiusGuestVlanEnabled", "radiusGuestVlanEnabled"), + ("radiusGuestVlanId", "radiusGuestVlanId"), ("radiusLoadBalancingPolicy", "radiusLoadBalancingPolicy"), - ("radiusAccountingEnabled", "radiusAccountingEnabled"), - ("radiusAccountingServers", "radiusAccountingServers"), - ("radiusAccountingInterimInterval", "radiusAccountingInterimInterval"), - ("radiusAttributeForGroupPolicies", "radiusAttributeForGroupPolicies"), - ("ipAssignmentMode", "ipAssignmentMode"), - ("useVlanTagging", "useVlanTagging"), - ("concentratorNetworkId", "concentratorNetworkId"), + ("radiusOverride", "radiusOverride"), + ("radiusProxyEnabled", "radiusProxyEnabled"), + ("radiusServerAttemptsLimit", "radiusServerAttemptsLimit"), + ("radiusServerTimeout", "radiusServerTimeout"), + ("radiusServers", "radiusServers"), + ("radiusTestingEnabled", "radiusTestingEnabled"), ("secondaryConcentratorNetworkId", "secondaryConcentratorNetworkId"), - ("disassociateClientsOnVpnFailover", "disassociateClientsOnVpnFailover"), + ("speedBurst", "speedBurst"), + ("splashGuestSponsorDomains", "splashGuestSponsorDomains"), + ("splashPage", "splashPage"), + ("useVlanTagging", "useVlanTagging"), + ("visible", "visible"), ("vlanId", "vlanId"), - ("defaultVlanId", "defaultVlanId"), - ("apTagsAndVlanIds", "apTagsAndVlanIds"), ("walledGardenEnabled", "walledGardenEnabled"), ("walledGardenRanges", "walledGardenRanges"), - ("gre", "gre"), - ("radiusOverride", "radiusOverride"), - ("radiusGuestVlanEnabled", "radiusGuestVlanEnabled"), - ("radiusGuestVlanId", "radiusGuestVlanId"), - ("minBitrate", "minBitrate"), - ("bandSelection", "bandSelection"), - ("perClientBandwidthLimitUp", "perClientBandwidthLimitUp"), - ("perClientBandwidthLimitDown", "perClientBandwidthLimitDown"), - ("perSsidBandwidthLimitUp", "perSsidBandwidthLimitUp"), - ("perSsidBandwidthLimitDown", "perSsidBandwidthLimitDown"), - ("lanIsolationEnabled", "lanIsolationEnabled"), - ("visible", "visible"), - ("availableOnAllAps", "availableOnAllAps"), - ("availabilityTags", "availabilityTags"), - ("mandatoryDhcpEnabled", "mandatoryDhcpEnabled"), - ("adultContentFilteringEnabled", "adultContentFilteringEnabled"), - ("dnsRewrite", "dnsRewrite"), - ("speedBurst", "speedBurst"), + ("wpaEncryptionMode", "wpaEncryptionMode"), ("networkId", "networkId"), ("number", "number"), ] diff --git a/ansible_collections/cisco/meraki/plugins/action/networks_wireless_ssids_bonjour_forwarding.py b/ansible_collections/cisco/meraki/plugins/action/networks_wireless_ssids_bonjour_forwarding.py index 43f69849a..85a078a39 100644 --- a/ansible_collections/cisco/meraki/plugins/action/networks_wireless_ssids_bonjour_forwarding.py +++ b/ansible_collections/cisco/meraki/plugins/action/networks_wireless_ssids_bonjour_forwarding.py @@ -33,6 +33,7 @@ argument_spec = meraki_argument_spec() argument_spec.update(dict( state=dict(type="str", default="present", choices=["present"]), enabled=dict(type="bool"), + exception=dict(type="dict"), rules=dict(type="list"), networkId=dict(type="str"), number=dict(type="str"), @@ -51,6 +52,7 @@ class NetworksWirelessSsidsBonjourForwarding(object): self.meraki = meraki self.new_object = dict( enabled=params.get("enabled"), + exception=params.get("exception"), rules=params.get("rules"), network_id=params.get("networkId"), number=params.get("number"), @@ -69,6 +71,9 @@ class NetworksWirelessSsidsBonjourForwarding(object): new_object_params = {} if self.new_object.get('enabled') is not None or self.new_object.get('enabled') is not None: new_object_params['enabled'] = self.new_object.get('enabled') + if self.new_object.get('exception') is not None or self.new_object.get('exception') is not None: + new_object_params['exception'] = self.new_object.get('exception') or \ + self.new_object.get('exception') if self.new_object.get('rules') is not None or self.new_object.get('rules') is not None: new_object_params['rules'] = self.new_object.get('rules') or \ self.new_object.get('rules') @@ -132,6 +137,7 @@ class NetworksWirelessSsidsBonjourForwarding(object): obj_params = [ ("enabled", "enabled"), + ("exception", "exception"), ("rules", "rules"), ("networkId", "networkId"), ("number", "number"), diff --git a/ansible_collections/cisco/meraki/plugins/action/networks_wireless_ssids_device_type_group_policies.py b/ansible_collections/cisco/meraki/plugins/action/networks_wireless_ssids_device_type_group_policies.py index 7cc30fd3e..b3890afbe 100644 --- a/ansible_collections/cisco/meraki/plugins/action/networks_wireless_ssids_device_type_group_policies.py +++ b/ansible_collections/cisco/meraki/plugins/action/networks_wireless_ssids_device_type_group_policies.py @@ -32,8 +32,8 @@ argument_spec = meraki_argument_spec() # Add arguments specific for this module argument_spec.update(dict( state=dict(type="str", default="present", choices=["present"]), - enabled=dict(type="bool"), deviceTypePolicies=dict(type="list"), + enabled=dict(type="bool"), networkId=dict(type="str"), number=dict(type="str"), )) @@ -50,8 +50,8 @@ class NetworksWirelessSsidsDeviceTypeGroupPolicies(object): def __init__(self, params, meraki): self.meraki = meraki self.new_object = dict( - enabled=params.get("enabled"), deviceTypePolicies=params.get("deviceTypePolicies"), + enabled=params.get("enabled"), network_id=params.get("networkId"), number=params.get("number"), ) @@ -67,11 +67,11 @@ class NetworksWirelessSsidsDeviceTypeGroupPolicies(object): def update_all_params(self): new_object_params = {} - if self.new_object.get('enabled') is not None or self.new_object.get('enabled') is not None: - new_object_params['enabled'] = self.new_object.get('enabled') if self.new_object.get('deviceTypePolicies') is not None or self.new_object.get('device_type_policies') is not None: new_object_params['deviceTypePolicies'] = self.new_object.get('deviceTypePolicies') or \ self.new_object.get('device_type_policies') + if self.new_object.get('enabled') is not None or self.new_object.get('enabled') is not None: + new_object_params['enabled'] = self.new_object.get('enabled') if self.new_object.get('networkId') is not None or self.new_object.get('network_id') is not None: new_object_params['networkId'] = self.new_object.get('networkId') or \ self.new_object.get('network_id') @@ -131,8 +131,8 @@ class NetworksWirelessSsidsDeviceTypeGroupPolicies(object): requested_obj = self.new_object obj_params = [ - ("enabled", "enabled"), ("deviceTypePolicies", "deviceTypePolicies"), + ("enabled", "enabled"), ("networkId", "networkId"), ("number", "number"), ] diff --git a/ansible_collections/cisco/meraki/plugins/action/networks_wireless_ssids_eap_override.py b/ansible_collections/cisco/meraki/plugins/action/networks_wireless_ssids_eap_override.py index d0e924aaa..2d0748958 100644 --- a/ansible_collections/cisco/meraki/plugins/action/networks_wireless_ssids_eap_override.py +++ b/ansible_collections/cisco/meraki/plugins/action/networks_wireless_ssids_eap_override.py @@ -32,10 +32,10 @@ argument_spec = meraki_argument_spec() # Add arguments specific for this module argument_spec.update(dict( state=dict(type="str", default="present", choices=["present"]), - timeout=dict(type="int"), + eapolKey=dict(type="dict"), identity=dict(type="dict"), maxRetries=dict(type="int"), - eapolKey=dict(type="dict"), + timeout=dict(type="int"), networkId=dict(type="str"), number=dict(type="str"), )) @@ -52,10 +52,10 @@ class NetworksWirelessSsidsEapOverride(object): def __init__(self, params, meraki): self.meraki = meraki self.new_object = dict( - timeout=params.get("timeout"), + eapolKey=params.get("eapolKey"), identity=params.get("identity"), maxRetries=params.get("maxRetries"), - eapolKey=params.get("eapolKey"), + timeout=params.get("timeout"), network_id=params.get("networkId"), number=params.get("number"), ) @@ -71,18 +71,18 @@ class NetworksWirelessSsidsEapOverride(object): def update_all_params(self): new_object_params = {} - if self.new_object.get('timeout') is not None or self.new_object.get('timeout') is not None: - new_object_params['timeout'] = self.new_object.get('timeout') or \ - self.new_object.get('timeout') + if self.new_object.get('eapolKey') is not None or self.new_object.get('eapol_key') is not None: + new_object_params['eapolKey'] = self.new_object.get('eapolKey') or \ + self.new_object.get('eapol_key') if self.new_object.get('identity') is not None or self.new_object.get('identity') is not None: new_object_params['identity'] = self.new_object.get('identity') or \ self.new_object.get('identity') if self.new_object.get('maxRetries') is not None or self.new_object.get('max_retries') is not None: new_object_params['maxRetries'] = self.new_object.get('maxRetries') or \ self.new_object.get('max_retries') - if self.new_object.get('eapolKey') is not None or self.new_object.get('eapol_key') is not None: - new_object_params['eapolKey'] = self.new_object.get('eapolKey') or \ - self.new_object.get('eapol_key') + if self.new_object.get('timeout') is not None or self.new_object.get('timeout') is not None: + new_object_params['timeout'] = self.new_object.get('timeout') or \ + self.new_object.get('timeout') if self.new_object.get('networkId') is not None or self.new_object.get('network_id') is not None: new_object_params['networkId'] = self.new_object.get('networkId') or \ self.new_object.get('network_id') @@ -142,10 +142,10 @@ class NetworksWirelessSsidsEapOverride(object): requested_obj = self.new_object obj_params = [ - ("timeout", "timeout"), + ("eapolKey", "eapolKey"), ("identity", "identity"), ("maxRetries", "maxRetries"), - ("eapolKey", "eapolKey"), + ("timeout", "timeout"), ("networkId", "networkId"), ("number", "number"), ] diff --git a/ansible_collections/cisco/meraki/plugins/action/networks_wireless_ssids_firewall_l3_firewall_rules.py b/ansible_collections/cisco/meraki/plugins/action/networks_wireless_ssids_firewall_l3_firewall_rules.py index 178967038..909fc147c 100644 --- a/ansible_collections/cisco/meraki/plugins/action/networks_wireless_ssids_firewall_l3_firewall_rules.py +++ b/ansible_collections/cisco/meraki/plugins/action/networks_wireless_ssids_firewall_l3_firewall_rules.py @@ -32,8 +32,8 @@ argument_spec = meraki_argument_spec() # Add arguments specific for this module argument_spec.update(dict( state=dict(type="str", default="present", choices=["present"]), - rules=dict(type="list"), allowLanAccess=dict(type="bool"), + rules=dict(type="list"), networkId=dict(type="str"), number=dict(type="str"), )) @@ -50,8 +50,8 @@ class NetworksWirelessSsidsFirewallL3FirewallRules(object): def __init__(self, params, meraki): self.meraki = meraki self.new_object = dict( - rules=params.get("rules"), allowLanAccess=params.get("allowLanAccess"), + rules=params.get("rules"), network_id=params.get("networkId"), number=params.get("number"), ) @@ -67,11 +67,11 @@ class NetworksWirelessSsidsFirewallL3FirewallRules(object): def update_all_params(self): new_object_params = {} + if self.new_object.get('allowLanAccess') is not None or self.new_object.get('allow_lan_access') is not None: + new_object_params['allowLanAccess'] = self.new_object.get('allowLanAccess') if self.new_object.get('rules') is not None or self.new_object.get('rules') is not None: new_object_params['rules'] = self.new_object.get('rules') or \ self.new_object.get('rules') - if self.new_object.get('allowLanAccess') is not None or self.new_object.get('allow_lan_access') is not None: - new_object_params['allowLanAccess'] = self.new_object.get('allowLanAccess') if self.new_object.get('networkId') is not None or self.new_object.get('network_id') is not None: new_object_params['networkId'] = self.new_object.get('networkId') or \ self.new_object.get('network_id') @@ -131,8 +131,8 @@ class NetworksWirelessSsidsFirewallL3FirewallRules(object): requested_obj = self.new_object obj_params = [ - ("rules", "rules"), ("allowLanAccess", "allowLanAccess"), + ("rules", "rules"), ("networkId", "networkId"), ("number", "number"), ] diff --git a/ansible_collections/cisco/meraki/plugins/action/networks_wireless_ssids_hotspot20.py b/ansible_collections/cisco/meraki/plugins/action/networks_wireless_ssids_hotspot20.py index 553ea6544..8efc94199 100644 --- a/ansible_collections/cisco/meraki/plugins/action/networks_wireless_ssids_hotspot20.py +++ b/ansible_collections/cisco/meraki/plugins/action/networks_wireless_ssids_hotspot20.py @@ -32,14 +32,14 @@ argument_spec = meraki_argument_spec() # Add arguments specific for this module argument_spec.update(dict( state=dict(type="str", default="present", choices=["present"]), - enabled=dict(type="bool"), - operator=dict(type="dict"), - venue=dict(type="dict"), - networkAccessType=dict(type="str"), domains=dict(type="list"), - roamConsortOis=dict(type="list"), + enabled=dict(type="bool"), mccMncs=dict(type="list"), naiRealms=dict(type="list"), + networkAccessType=dict(type="str"), + operator=dict(type="dict"), + roamConsortOis=dict(type="list"), + venue=dict(type="dict"), networkId=dict(type="str"), number=dict(type="str"), )) @@ -56,14 +56,14 @@ class NetworksWirelessSsidsHotspot20(object): def __init__(self, params, meraki): self.meraki = meraki self.new_object = dict( - enabled=params.get("enabled"), - operator=params.get("operator"), - venue=params.get("venue"), - networkAccessType=params.get("networkAccessType"), domains=params.get("domains"), - roamConsortOis=params.get("roamConsortOis"), + enabled=params.get("enabled"), mccMncs=params.get("mccMncs"), naiRealms=params.get("naiRealms"), + networkAccessType=params.get("networkAccessType"), + operator=params.get("operator"), + roamConsortOis=params.get("roamConsortOis"), + venue=params.get("venue"), network_id=params.get("networkId"), number=params.get("number"), ) @@ -79,29 +79,29 @@ class NetworksWirelessSsidsHotspot20(object): def update_all_params(self): new_object_params = {} - if self.new_object.get('enabled') is not None or self.new_object.get('enabled') is not None: - new_object_params['enabled'] = self.new_object.get('enabled') - if self.new_object.get('operator') is not None or self.new_object.get('operator') is not None: - new_object_params['operator'] = self.new_object.get('operator') or \ - self.new_object.get('operator') - if self.new_object.get('venue') is not None or self.new_object.get('venue') is not None: - new_object_params['venue'] = self.new_object.get('venue') or \ - self.new_object.get('venue') - if self.new_object.get('networkAccessType') is not None or self.new_object.get('network_access_type') is not None: - new_object_params['networkAccessType'] = self.new_object.get('networkAccessType') or \ - self.new_object.get('network_access_type') if self.new_object.get('domains') is not None or self.new_object.get('domains') is not None: new_object_params['domains'] = self.new_object.get('domains') or \ self.new_object.get('domains') - if self.new_object.get('roamConsortOis') is not None or self.new_object.get('roam_consort_ois') is not None: - new_object_params['roamConsortOis'] = self.new_object.get('roamConsortOis') or \ - self.new_object.get('roam_consort_ois') + if self.new_object.get('enabled') is not None or self.new_object.get('enabled') is not None: + new_object_params['enabled'] = self.new_object.get('enabled') if self.new_object.get('mccMncs') is not None or self.new_object.get('mcc_mncs') is not None: new_object_params['mccMncs'] = self.new_object.get('mccMncs') or \ self.new_object.get('mcc_mncs') if self.new_object.get('naiRealms') is not None or self.new_object.get('nai_realms') is not None: new_object_params['naiRealms'] = self.new_object.get('naiRealms') or \ self.new_object.get('nai_realms') + if self.new_object.get('networkAccessType') is not None or self.new_object.get('network_access_type') is not None: + new_object_params['networkAccessType'] = self.new_object.get('networkAccessType') or \ + self.new_object.get('network_access_type') + if self.new_object.get('operator') is not None or self.new_object.get('operator') is not None: + new_object_params['operator'] = self.new_object.get('operator') or \ + self.new_object.get('operator') + if self.new_object.get('roamConsortOis') is not None or self.new_object.get('roam_consort_ois') is not None: + new_object_params['roamConsortOis'] = self.new_object.get('roamConsortOis') or \ + self.new_object.get('roam_consort_ois') + if self.new_object.get('venue') is not None or self.new_object.get('venue') is not None: + new_object_params['venue'] = self.new_object.get('venue') or \ + self.new_object.get('venue') if self.new_object.get('networkId') is not None or self.new_object.get('network_id') is not None: new_object_params['networkId'] = self.new_object.get('networkId') or \ self.new_object.get('network_id') @@ -161,14 +161,14 @@ class NetworksWirelessSsidsHotspot20(object): requested_obj = self.new_object obj_params = [ - ("enabled", "enabled"), - ("operator", "operator"), - ("venue", "venue"), - ("networkAccessType", "networkAccessType"), ("domains", "domains"), - ("roamConsortOis", "roamConsortOis"), + ("enabled", "enabled"), ("mccMncs", "mccMncs"), ("naiRealms", "naiRealms"), + ("networkAccessType", "networkAccessType"), + ("operator", "operator"), + ("roamConsortOis", "roamConsortOis"), + ("venue", "venue"), ("networkId", "networkId"), ("number", "number"), ] diff --git a/ansible_collections/cisco/meraki/plugins/action/networks_wireless_ssids_identity_psks.py b/ansible_collections/cisco/meraki/plugins/action/networks_wireless_ssids_identity_psks.py index 266306851..995997893 100644 --- a/ansible_collections/cisco/meraki/plugins/action/networks_wireless_ssids_identity_psks.py +++ b/ansible_collections/cisco/meraki/plugins/action/networks_wireless_ssids_identity_psks.py @@ -32,10 +32,10 @@ argument_spec = meraki_argument_spec() # Add arguments specific for this module argument_spec.update(dict( state=dict(type="str", default="present", choices=["present", "absent"]), + expiresAt=dict(type="str"), + groupPolicyId=dict(type="str"), name=dict(type="str"), passphrase=dict(type="str"), - groupPolicyId=dict(type="str"), - expiresAt=dict(type="str"), networkId=dict(type="str"), number=dict(type="str"), identityPskId=dict(type="str"), @@ -54,10 +54,10 @@ class NetworksWirelessSsidsIdentityPsks(object): def __init__(self, params, meraki): self.meraki = meraki self.new_object = dict( + expiresAt=params.get("expiresAt"), + groupPolicyId=params.get("groupPolicyId"), name=params.get("name"), passphrase=params.get("passphrase"), - groupPolicyId=params.get("groupPolicyId"), - expiresAt=params.get("expiresAt"), networkId=params.get("networkId"), number=params.get("number"), identityPskId=params.get("identityPskId"), @@ -86,18 +86,18 @@ class NetworksWirelessSsidsIdentityPsks(object): def create_params(self): new_object_params = {} + if self.new_object.get('expiresAt') is not None or self.new_object.get('expires_at') is not None: + new_object_params['expiresAt'] = self.new_object.get('expiresAt') or \ + self.new_object.get('expires_at') + if self.new_object.get('groupPolicyId') is not None or self.new_object.get('group_policy_id') is not None: + new_object_params['groupPolicyId'] = self.new_object.get('groupPolicyId') or \ + self.new_object.get('group_policy_id') if self.new_object.get('name') is not None or self.new_object.get('name') is not None: new_object_params['name'] = self.new_object.get('name') or \ self.new_object.get('name') if self.new_object.get('passphrase') is not None or self.new_object.get('passphrase') is not None: new_object_params['passphrase'] = self.new_object.get('passphrase') or \ self.new_object.get('passphrase') - if self.new_object.get('groupPolicyId') is not None or self.new_object.get('group_policy_id') is not None: - new_object_params['groupPolicyId'] = self.new_object.get('groupPolicyId') or \ - self.new_object.get('group_policy_id') - if self.new_object.get('expiresAt') is not None or self.new_object.get('expires_at') is not None: - new_object_params['expiresAt'] = self.new_object.get('expiresAt') or \ - self.new_object.get('expires_at') if self.new_object.get('networkId') is not None or self.new_object.get('network_id') is not None: new_object_params['networkId'] = self.new_object.get('networkId') or \ self.new_object.get('network_id') @@ -121,18 +121,18 @@ class NetworksWirelessSsidsIdentityPsks(object): def update_by_id_params(self): new_object_params = {} + if self.new_object.get('expiresAt') is not None or self.new_object.get('expires_at') is not None: + new_object_params['expiresAt'] = self.new_object.get('expiresAt') or \ + self.new_object.get('expires_at') + if self.new_object.get('groupPolicyId') is not None or self.new_object.get('group_policy_id') is not None: + new_object_params['groupPolicyId'] = self.new_object.get('groupPolicyId') or \ + self.new_object.get('group_policy_id') if self.new_object.get('name') is not None or self.new_object.get('name') is not None: new_object_params['name'] = self.new_object.get('name') or \ self.new_object.get('name') if self.new_object.get('passphrase') is not None or self.new_object.get('passphrase') is not None: new_object_params['passphrase'] = self.new_object.get('passphrase') or \ self.new_object.get('passphrase') - if self.new_object.get('groupPolicyId') is not None or self.new_object.get('group_policy_id') is not None: - new_object_params['groupPolicyId'] = self.new_object.get('groupPolicyId') or \ - self.new_object.get('group_policy_id') - if self.new_object.get('expiresAt') is not None or self.new_object.get('expires_at') is not None: - new_object_params['expiresAt'] = self.new_object.get('expiresAt') or \ - self.new_object.get('expires_at') if self.new_object.get('networkId') is not None or self.new_object.get('network_id') is not None: new_object_params['networkId'] = self.new_object.get('networkId') or \ self.new_object.get('network_id') @@ -213,10 +213,10 @@ class NetworksWirelessSsidsIdentityPsks(object): requested_obj = self.new_object obj_params = [ + ("expiresAt", "expiresAt"), + ("groupPolicyId", "groupPolicyId"), ("name", "name"), ("passphrase", "passphrase"), - ("groupPolicyId", "groupPolicyId"), - ("expiresAt", "expiresAt"), ("networkId", "networkId"), ("number", "number"), ("identityPskId", "identityPskId"), diff --git a/ansible_collections/cisco/meraki/plugins/action/networks_wireless_ssids_splash_settings.py b/ansible_collections/cisco/meraki/plugins/action/networks_wireless_ssids_splash_settings.py index 71989ade2..b062af863 100644 --- a/ansible_collections/cisco/meraki/plugins/action/networks_wireless_ssids_splash_settings.py +++ b/ansible_collections/cisco/meraki/plugins/action/networks_wireless_ssids_splash_settings.py @@ -32,21 +32,22 @@ argument_spec = meraki_argument_spec() # Add arguments specific for this module argument_spec.update(dict( state=dict(type="str", default="present", choices=["present"]), - splashUrl=dict(type="str"), - useSplashUrl=dict(type="bool"), - splashTimeout=dict(type="int"), - redirectUrl=dict(type="str"), - useRedirectUrl=dict(type="bool"), - welcomeMessage=dict(type="str"), - splashLogo=dict(type="dict"), - splashImage=dict(type="dict"), - splashPrepaidFront=dict(type="dict"), + allowSimultaneousLogins=dict(type="bool"), + billing=dict(type="dict"), blockAllTrafficBeforeSignOn=dict(type="bool"), controllerDisconnectionBehavior=dict(type="str"), - allowSimultaneousLogins=dict(type="bool"), guestSponsorship=dict(type="dict"), - billing=dict(type="dict"), + redirectUrl=dict(type="str"), sentryEnrollment=dict(type="dict"), + splashImage=dict(type="dict"), + splashLogo=dict(type="dict"), + splashPrepaidFront=dict(type="dict"), + splashTimeout=dict(type="int"), + splashUrl=dict(type="str"), + themeId=dict(type="str"), + useRedirectUrl=dict(type="bool"), + useSplashUrl=dict(type="bool"), + welcomeMessage=dict(type="str"), networkId=dict(type="str"), number=dict(type="str"), )) @@ -63,21 +64,22 @@ class NetworksWirelessSsidsSplashSettings(object): def __init__(self, params, meraki): self.meraki = meraki self.new_object = dict( - splashUrl=params.get("splashUrl"), - useSplashUrl=params.get("useSplashUrl"), - splashTimeout=params.get("splashTimeout"), - redirectUrl=params.get("redirectUrl"), - useRedirectUrl=params.get("useRedirectUrl"), - welcomeMessage=params.get("welcomeMessage"), - splashLogo=params.get("splashLogo"), - splashImage=params.get("splashImage"), - splashPrepaidFront=params.get("splashPrepaidFront"), + allowSimultaneousLogins=params.get("allowSimultaneousLogins"), + billing=params.get("billing"), blockAllTrafficBeforeSignOn=params.get("blockAllTrafficBeforeSignOn"), controllerDisconnectionBehavior=params.get("controllerDisconnectionBehavior"), - allowSimultaneousLogins=params.get("allowSimultaneousLogins"), guestSponsorship=params.get("guestSponsorship"), - billing=params.get("billing"), + redirectUrl=params.get("redirectUrl"), sentryEnrollment=params.get("sentryEnrollment"), + splashImage=params.get("splashImage"), + splashLogo=params.get("splashLogo"), + splashPrepaidFront=params.get("splashPrepaidFront"), + splashTimeout=params.get("splashTimeout"), + splashUrl=params.get("splashUrl"), + themeId=params.get("themeId"), + useRedirectUrl=params.get("useRedirectUrl"), + useSplashUrl=params.get("useSplashUrl"), + welcomeMessage=params.get("welcomeMessage"), network_id=params.get("networkId"), number=params.get("number"), ) @@ -93,47 +95,50 @@ class NetworksWirelessSsidsSplashSettings(object): def update_all_params(self): new_object_params = {} - if self.new_object.get('splashUrl') is not None or self.new_object.get('splash_url') is not None: - new_object_params['splashUrl'] = self.new_object.get('splashUrl') or \ - self.new_object.get('splash_url') - if self.new_object.get('useSplashUrl') is not None or self.new_object.get('use_splash_url') is not None: - new_object_params['useSplashUrl'] = self.new_object.get('useSplashUrl') - if self.new_object.get('splashTimeout') is not None or self.new_object.get('splash_timeout') is not None: - new_object_params['splashTimeout'] = self.new_object.get('splashTimeout') or \ - self.new_object.get('splash_timeout') - if self.new_object.get('redirectUrl') is not None or self.new_object.get('redirect_url') is not None: - new_object_params['redirectUrl'] = self.new_object.get('redirectUrl') or \ - self.new_object.get('redirect_url') - if self.new_object.get('useRedirectUrl') is not None or self.new_object.get('use_redirect_url') is not None: - new_object_params['useRedirectUrl'] = self.new_object.get('useRedirectUrl') - if self.new_object.get('welcomeMessage') is not None or self.new_object.get('welcome_message') is not None: - new_object_params['welcomeMessage'] = self.new_object.get('welcomeMessage') or \ - self.new_object.get('welcome_message') - if self.new_object.get('splashLogo') is not None or self.new_object.get('splash_logo') is not None: - new_object_params['splashLogo'] = self.new_object.get('splashLogo') or \ - self.new_object.get('splash_logo') - if self.new_object.get('splashImage') is not None or self.new_object.get('splash_image') is not None: - new_object_params['splashImage'] = self.new_object.get('splashImage') or \ - self.new_object.get('splash_image') - if self.new_object.get('splashPrepaidFront') is not None or self.new_object.get('splash_prepaid_front') is not None: - new_object_params['splashPrepaidFront'] = self.new_object.get('splashPrepaidFront') or \ - self.new_object.get('splash_prepaid_front') + if self.new_object.get('allowSimultaneousLogins') is not None or self.new_object.get('allow_simultaneous_logins') is not None: + new_object_params['allowSimultaneousLogins'] = self.new_object.get('allowSimultaneousLogins') + if self.new_object.get('billing') is not None or self.new_object.get('billing') is not None: + new_object_params['billing'] = self.new_object.get('billing') or \ + self.new_object.get('billing') if self.new_object.get('blockAllTrafficBeforeSignOn') is not None or self.new_object.get('block_all_traffic_before_sign_on') is not None: new_object_params['blockAllTrafficBeforeSignOn'] = self.new_object.get('blockAllTrafficBeforeSignOn') if self.new_object.get('controllerDisconnectionBehavior') is not None or self.new_object.get('controller_disconnection_behavior') is not None: new_object_params['controllerDisconnectionBehavior'] = self.new_object.get('controllerDisconnectionBehavior') or \ self.new_object.get('controller_disconnection_behavior') - if self.new_object.get('allowSimultaneousLogins') is not None or self.new_object.get('allow_simultaneous_logins') is not None: - new_object_params['allowSimultaneousLogins'] = self.new_object.get('allowSimultaneousLogins') if self.new_object.get('guestSponsorship') is not None or self.new_object.get('guest_sponsorship') is not None: new_object_params['guestSponsorship'] = self.new_object.get('guestSponsorship') or \ self.new_object.get('guest_sponsorship') - if self.new_object.get('billing') is not None or self.new_object.get('billing') is not None: - new_object_params['billing'] = self.new_object.get('billing') or \ - self.new_object.get('billing') + if self.new_object.get('redirectUrl') is not None or self.new_object.get('redirect_url') is not None: + new_object_params['redirectUrl'] = self.new_object.get('redirectUrl') or \ + self.new_object.get('redirect_url') if self.new_object.get('sentryEnrollment') is not None or self.new_object.get('sentry_enrollment') is not None: new_object_params['sentryEnrollment'] = self.new_object.get('sentryEnrollment') or \ self.new_object.get('sentry_enrollment') + if self.new_object.get('splashImage') is not None or self.new_object.get('splash_image') is not None: + new_object_params['splashImage'] = self.new_object.get('splashImage') or \ + self.new_object.get('splash_image') + if self.new_object.get('splashLogo') is not None or self.new_object.get('splash_logo') is not None: + new_object_params['splashLogo'] = self.new_object.get('splashLogo') or \ + self.new_object.get('splash_logo') + if self.new_object.get('splashPrepaidFront') is not None or self.new_object.get('splash_prepaid_front') is not None: + new_object_params['splashPrepaidFront'] = self.new_object.get('splashPrepaidFront') or \ + self.new_object.get('splash_prepaid_front') + if self.new_object.get('splashTimeout') is not None or self.new_object.get('splash_timeout') is not None: + new_object_params['splashTimeout'] = self.new_object.get('splashTimeout') or \ + self.new_object.get('splash_timeout') + if self.new_object.get('splashUrl') is not None or self.new_object.get('splash_url') is not None: + new_object_params['splashUrl'] = self.new_object.get('splashUrl') or \ + self.new_object.get('splash_url') + if self.new_object.get('themeId') is not None or self.new_object.get('theme_id') is not None: + new_object_params['themeId'] = self.new_object.get('themeId') or \ + self.new_object.get('theme_id') + if self.new_object.get('useRedirectUrl') is not None or self.new_object.get('use_redirect_url') is not None: + new_object_params['useRedirectUrl'] = self.new_object.get('useRedirectUrl') + if self.new_object.get('useSplashUrl') is not None or self.new_object.get('use_splash_url') is not None: + new_object_params['useSplashUrl'] = self.new_object.get('useSplashUrl') + if self.new_object.get('welcomeMessage') is not None or self.new_object.get('welcome_message') is not None: + new_object_params['welcomeMessage'] = self.new_object.get('welcomeMessage') or \ + self.new_object.get('welcome_message') if self.new_object.get('networkId') is not None or self.new_object.get('network_id') is not None: new_object_params['networkId'] = self.new_object.get('networkId') or \ self.new_object.get('network_id') @@ -193,21 +198,22 @@ class NetworksWirelessSsidsSplashSettings(object): requested_obj = self.new_object obj_params = [ - ("splashUrl", "splashUrl"), - ("useSplashUrl", "useSplashUrl"), - ("splashTimeout", "splashTimeout"), - ("redirectUrl", "redirectUrl"), - ("useRedirectUrl", "useRedirectUrl"), - ("welcomeMessage", "welcomeMessage"), - ("splashLogo", "splashLogo"), - ("splashImage", "splashImage"), - ("splashPrepaidFront", "splashPrepaidFront"), + ("allowSimultaneousLogins", "allowSimultaneousLogins"), + ("billing", "billing"), ("blockAllTrafficBeforeSignOn", "blockAllTrafficBeforeSignOn"), ("controllerDisconnectionBehavior", "controllerDisconnectionBehavior"), - ("allowSimultaneousLogins", "allowSimultaneousLogins"), ("guestSponsorship", "guestSponsorship"), - ("billing", "billing"), + ("redirectUrl", "redirectUrl"), ("sentryEnrollment", "sentryEnrollment"), + ("splashImage", "splashImage"), + ("splashLogo", "splashLogo"), + ("splashPrepaidFront", "splashPrepaidFront"), + ("splashTimeout", "splashTimeout"), + ("splashUrl", "splashUrl"), + ("themeId", "themeId"), + ("useRedirectUrl", "useRedirectUrl"), + ("useSplashUrl", "useSplashUrl"), + ("welcomeMessage", "welcomeMessage"), ("networkId", "networkId"), ("number", "number"), ] diff --git a/ansible_collections/cisco/meraki/plugins/action/networks_wireless_ssids_traffic_shaping_rules.py b/ansible_collections/cisco/meraki/plugins/action/networks_wireless_ssids_traffic_shaping_rules.py index de13a0d80..bddddcbea 100644 --- a/ansible_collections/cisco/meraki/plugins/action/networks_wireless_ssids_traffic_shaping_rules.py +++ b/ansible_collections/cisco/meraki/plugins/action/networks_wireless_ssids_traffic_shaping_rules.py @@ -32,9 +32,9 @@ argument_spec = meraki_argument_spec() # Add arguments specific for this module argument_spec.update(dict( state=dict(type="str", default="present", choices=["present"]), - trafficShapingEnabled=dict(type="bool"), defaultRulesEnabled=dict(type="bool"), rules=dict(type="list"), + trafficShapingEnabled=dict(type="bool"), networkId=dict(type="str"), number=dict(type="str"), )) @@ -51,9 +51,9 @@ class NetworksWirelessSsidsTrafficShapingRules(object): def __init__(self, params, meraki): self.meraki = meraki self.new_object = dict( - trafficShapingEnabled=params.get("trafficShapingEnabled"), defaultRulesEnabled=params.get("defaultRulesEnabled"), rules=params.get("rules"), + trafficShapingEnabled=params.get("trafficShapingEnabled"), network_id=params.get("networkId"), number=params.get("number"), ) @@ -69,13 +69,13 @@ class NetworksWirelessSsidsTrafficShapingRules(object): def update_all_params(self): new_object_params = {} - if self.new_object.get('trafficShapingEnabled') is not None or self.new_object.get('traffic_shaping_enabled') is not None: - new_object_params['trafficShapingEnabled'] = self.new_object.get('trafficShapingEnabled') if self.new_object.get('defaultRulesEnabled') is not None or self.new_object.get('default_rules_enabled') is not None: new_object_params['defaultRulesEnabled'] = self.new_object.get('defaultRulesEnabled') if self.new_object.get('rules') is not None or self.new_object.get('rules') is not None: new_object_params['rules'] = self.new_object.get('rules') or \ self.new_object.get('rules') + if self.new_object.get('trafficShapingEnabled') is not None or self.new_object.get('traffic_shaping_enabled') is not None: + new_object_params['trafficShapingEnabled'] = self.new_object.get('trafficShapingEnabled') if self.new_object.get('networkId') is not None or self.new_object.get('network_id') is not None: new_object_params['networkId'] = self.new_object.get('networkId') or \ self.new_object.get('network_id') @@ -135,9 +135,9 @@ class NetworksWirelessSsidsTrafficShapingRules(object): requested_obj = self.new_object obj_params = [ - ("trafficShapingEnabled", "trafficShapingEnabled"), ("defaultRulesEnabled", "defaultRulesEnabled"), ("rules", "rules"), + ("trafficShapingEnabled", "trafficShapingEnabled"), ("networkId", "networkId"), ("number", "number"), ] diff --git a/ansible_collections/cisco/meraki/plugins/action/networks_wireless_ssids_vpn.py b/ansible_collections/cisco/meraki/plugins/action/networks_wireless_ssids_vpn.py index cc3836353..a66830f81 100644 --- a/ansible_collections/cisco/meraki/plugins/action/networks_wireless_ssids_vpn.py +++ b/ansible_collections/cisco/meraki/plugins/action/networks_wireless_ssids_vpn.py @@ -33,8 +33,8 @@ argument_spec = meraki_argument_spec() argument_spec.update(dict( state=dict(type="str", default="present", choices=["present"]), concentrator=dict(type="dict"), - splitTunnel=dict(type="dict"), failover=dict(type="dict"), + splitTunnel=dict(type="dict"), networkId=dict(type="str"), number=dict(type="str"), )) @@ -52,8 +52,8 @@ class NetworksWirelessSsidsVpn(object): self.meraki = meraki self.new_object = dict( concentrator=params.get("concentrator"), - splitTunnel=params.get("splitTunnel"), failover=params.get("failover"), + splitTunnel=params.get("splitTunnel"), network_id=params.get("networkId"), number=params.get("number"), ) @@ -72,12 +72,12 @@ class NetworksWirelessSsidsVpn(object): if self.new_object.get('concentrator') is not None or self.new_object.get('concentrator') is not None: new_object_params['concentrator'] = self.new_object.get('concentrator') or \ self.new_object.get('concentrator') - if self.new_object.get('splitTunnel') is not None or self.new_object.get('split_tunnel') is not None: - new_object_params['splitTunnel'] = self.new_object.get('splitTunnel') or \ - self.new_object.get('split_tunnel') if self.new_object.get('failover') is not None or self.new_object.get('failover') is not None: new_object_params['failover'] = self.new_object.get('failover') or \ self.new_object.get('failover') + if self.new_object.get('splitTunnel') is not None or self.new_object.get('split_tunnel') is not None: + new_object_params['splitTunnel'] = self.new_object.get('splitTunnel') or \ + self.new_object.get('split_tunnel') if self.new_object.get('networkId') is not None or self.new_object.get('network_id') is not None: new_object_params['networkId'] = self.new_object.get('networkId') or \ self.new_object.get('network_id') @@ -138,8 +138,8 @@ class NetworksWirelessSsidsVpn(object): obj_params = [ ("concentrator", "concentrator"), - ("splitTunnel", "splitTunnel"), ("failover", "failover"), + ("splitTunnel", "splitTunnel"), ("networkId", "networkId"), ("number", "number"), ] diff --git a/ansible_collections/cisco/meraki/plugins/action/organizations.py b/ansible_collections/cisco/meraki/plugins/action/organizations.py index 0cb1670ef..410ebc37d 100644 --- a/ansible_collections/cisco/meraki/plugins/action/organizations.py +++ b/ansible_collections/cisco/meraki/plugins/action/organizations.py @@ -32,8 +32,8 @@ argument_spec = meraki_argument_spec() # Add arguments specific for this module argument_spec.update(dict( state=dict(type="str", default="present", choices=["present", "absent"]), - name=dict(type="str"), management=dict(type="dict"), + name=dict(type="str"), organizationId=dict(type="str"), api=dict(type="dict"), )) @@ -51,14 +51,24 @@ class Organizations(object): def __init__(self, params, meraki): self.meraki = meraki self.new_object = dict( - name=params.get("name"), management=params.get("management"), + name=params.get("name"), organizationId=params.get("organizationId"), api=params.get("api"), ) def get_all_params(self, name=None, id=None): new_object_params = {} + if self.new_object.get('perPage') is not None or self.new_object.get('per_page') is not None: + new_object_params['perPage'] = self.new_object.get('perPage') or \ + self.new_object.get('per_page') + new_object_params['total_pages'] = -1 + if self.new_object.get('startingAfter') is not None or self.new_object.get('starting_after') is not None: + new_object_params['startingAfter'] = self.new_object.get('startingAfter') or \ + self.new_object.get('starting_after') + if self.new_object.get('endingBefore') is not None or self.new_object.get('ending_before') is not None: + new_object_params['endingBefore'] = self.new_object.get('endingBefore') or \ + self.new_object.get('ending_before') return new_object_params def get_params_by_id(self, name=None, id=None): @@ -70,12 +80,12 @@ class Organizations(object): def create_params(self): new_object_params = {} - if self.new_object.get('name') is not None or self.new_object.get('name') is not None: - new_object_params['name'] = self.new_object.get('name') or \ - self.new_object.get('name') if self.new_object.get('management') is not None or self.new_object.get('management') is not None: new_object_params['management'] = self.new_object.get('management') or \ self.new_object.get('management') + if self.new_object.get('name') is not None or self.new_object.get('name') is not None: + new_object_params['name'] = self.new_object.get('name') or \ + self.new_object.get('name') return new_object_params def delete_by_id_params(self): @@ -87,15 +97,15 @@ class Organizations(object): def update_by_id_params(self): new_object_params = {} - if self.new_object.get('name') is not None or self.new_object.get('name') is not None: - new_object_params['name'] = self.new_object.get('name') or \ - self.new_object.get('name') - if self.new_object.get('management') is not None or self.new_object.get('management') is not None: - new_object_params['management'] = self.new_object.get('management') or \ - self.new_object.get('management') if self.new_object.get('api') is not None or self.new_object.get('api') is not None: new_object_params['api'] = self.new_object.get('api') or \ self.new_object.get('api') + if self.new_object.get('management') is not None or self.new_object.get('management') is not None: + new_object_params['management'] = self.new_object.get('management') or \ + self.new_object.get('management') + if self.new_object.get('name') is not None or self.new_object.get('name') is not None: + new_object_params['name'] = self.new_object.get('name') or \ + self.new_object.get('name') if self.new_object.get('organizationId') is not None or self.new_object.get('organization_id') is not None: new_object_params['organizationId'] = self.new_object.get('organizationId') or \ self.new_object.get('organization_id') @@ -170,8 +180,8 @@ class Organizations(object): requested_obj = self.new_object obj_params = [ - ("name", "name"), ("management", "management"), + ("name", "name"), ("organizationId", "organizationId"), ("api", "api"), ] diff --git a/ansible_collections/cisco/meraki/plugins/action/organizations_action_batches.py b/ansible_collections/cisco/meraki/plugins/action/organizations_action_batches.py index 8780b3e82..92a82e869 100644 --- a/ansible_collections/cisco/meraki/plugins/action/organizations_action_batches.py +++ b/ansible_collections/cisco/meraki/plugins/action/organizations_action_batches.py @@ -32,9 +32,10 @@ argument_spec = meraki_argument_spec() # Add arguments specific for this module argument_spec.update(dict( state=dict(type="str", default="present", choices=["present", "absent"]), + actions=dict(type="list"), + callback=dict(type="dict"), confirmed=dict(type="bool"), synchronous=dict(type="bool"), - actions=dict(type="list"), organizationId=dict(type="str"), actionBatchId=dict(type="str"), )) @@ -52,9 +53,10 @@ class OrganizationsActionBatches(object): def __init__(self, params, meraki): self.meraki = meraki self.new_object = dict( + actions=params.get("actions"), + callback=params.get("callback"), confirmed=params.get("confirmed"), synchronous=params.get("synchronous"), - actions=params.get("actions"), organizationId=params.get("organizationId"), actionBatchId=params.get("actionBatchId"), ) @@ -80,13 +82,16 @@ class OrganizationsActionBatches(object): def create_params(self): new_object_params = {} + if self.new_object.get('actions') is not None or self.new_object.get('actions') is not None: + new_object_params['actions'] = self.new_object.get('actions') or \ + self.new_object.get('actions') + if self.new_object.get('callback') is not None or self.new_object.get('callback') is not None: + new_object_params['callback'] = self.new_object.get('callback') or \ + self.new_object.get('callback') if self.new_object.get('confirmed') is not None or self.new_object.get('confirmed') is not None: new_object_params['confirmed'] = self.new_object.get('confirmed') if self.new_object.get('synchronous') is not None or self.new_object.get('synchronous') is not None: new_object_params['synchronous'] = self.new_object.get('synchronous') - if self.new_object.get('actions') is not None or self.new_object.get('actions') is not None: - new_object_params['actions'] = self.new_object.get('actions') or \ - self.new_object.get('actions') if self.new_object.get('organizationId') is not None or self.new_object.get('organization_id') is not None: new_object_params['organizationId'] = self.new_object.get('organizationId') or \ self.new_object.get('organization_id') @@ -185,9 +190,10 @@ class OrganizationsActionBatches(object): requested_obj = self.new_object obj_params = [ + ("actions", "actions"), + ("callback", "callback"), ("confirmed", "confirmed"), ("synchronous", "synchronous"), - ("actions", "actions"), ("organizationId", "organizationId"), ("actionBatchId", "actionBatchId"), ] diff --git a/ansible_collections/cisco/meraki/plugins/action/organizations_adaptive_policy_acls.py b/ansible_collections/cisco/meraki/plugins/action/organizations_adaptive_policy_acls.py index cc445e11f..b5249443c 100644 --- a/ansible_collections/cisco/meraki/plugins/action/organizations_adaptive_policy_acls.py +++ b/ansible_collections/cisco/meraki/plugins/action/organizations_adaptive_policy_acls.py @@ -32,10 +32,10 @@ argument_spec = meraki_argument_spec() # Add arguments specific for this module argument_spec.update(dict( state=dict(type="str", default="present", choices=["present", "absent"]), - name=dict(type="str"), description=dict(type="str"), - rules=dict(type="list"), ipVersion=dict(type="str"), + name=dict(type="str"), + rules=dict(type="list"), organizationId=dict(type="str"), aclId=dict(type="str"), )) @@ -53,10 +53,10 @@ class OrganizationsAdaptivePolicyAcls(object): def __init__(self, params, meraki): self.meraki = meraki self.new_object = dict( - name=params.get("name"), description=params.get("description"), - rules=params.get("rules"), ipVersion=params.get("ipVersion"), + name=params.get("name"), + rules=params.get("rules"), organizationId=params.get("organizationId"), aclId=params.get("aclId"), ) @@ -80,18 +80,18 @@ class OrganizationsAdaptivePolicyAcls(object): def create_params(self): new_object_params = {} - if self.new_object.get('name') is not None or self.new_object.get('name') is not None: - new_object_params['name'] = self.new_object.get('name') or \ - self.new_object.get('name') if self.new_object.get('description') is not None or self.new_object.get('description') is not None: new_object_params['description'] = self.new_object.get('description') or \ self.new_object.get('description') - if self.new_object.get('rules') is not None or self.new_object.get('rules') is not None: - new_object_params['rules'] = self.new_object.get('rules') or \ - self.new_object.get('rules') if self.new_object.get('ipVersion') is not None or self.new_object.get('ip_version') is not None: new_object_params['ipVersion'] = self.new_object.get('ipVersion') or \ self.new_object.get('ip_version') + if self.new_object.get('name') is not None or self.new_object.get('name') is not None: + new_object_params['name'] = self.new_object.get('name') or \ + self.new_object.get('name') + if self.new_object.get('rules') is not None or self.new_object.get('rules') is not None: + new_object_params['rules'] = self.new_object.get('rules') or \ + self.new_object.get('rules') if self.new_object.get('organizationId') is not None or self.new_object.get('organization_id') is not None: new_object_params['organizationId'] = self.new_object.get('organizationId') or \ self.new_object.get('organization_id') @@ -109,18 +109,18 @@ class OrganizationsAdaptivePolicyAcls(object): def update_by_id_params(self): new_object_params = {} - if self.new_object.get('name') is not None or self.new_object.get('name') is not None: - new_object_params['name'] = self.new_object.get('name') or \ - self.new_object.get('name') if self.new_object.get('description') is not None or self.new_object.get('description') is not None: new_object_params['description'] = self.new_object.get('description') or \ self.new_object.get('description') - if self.new_object.get('rules') is not None or self.new_object.get('rules') is not None: - new_object_params['rules'] = self.new_object.get('rules') or \ - self.new_object.get('rules') if self.new_object.get('ipVersion') is not None or self.new_object.get('ip_version') is not None: new_object_params['ipVersion'] = self.new_object.get('ipVersion') or \ self.new_object.get('ip_version') + if self.new_object.get('name') is not None or self.new_object.get('name') is not None: + new_object_params['name'] = self.new_object.get('name') or \ + self.new_object.get('name') + if self.new_object.get('rules') is not None or self.new_object.get('rules') is not None: + new_object_params['rules'] = self.new_object.get('rules') or \ + self.new_object.get('rules') if self.new_object.get('organizationId') is not None or self.new_object.get('organization_id') is not None: new_object_params['organizationId'] = self.new_object.get('organizationId') or \ self.new_object.get('organization_id') @@ -198,10 +198,10 @@ class OrganizationsAdaptivePolicyAcls(object): requested_obj = self.new_object obj_params = [ - ("name", "name"), ("description", "description"), - ("rules", "rules"), ("ipVersion", "ipVersion"), + ("name", "name"), + ("rules", "rules"), ("organizationId", "organizationId"), ("aclId", "aclId"), ] diff --git a/ansible_collections/cisco/meraki/plugins/action/organizations_adaptive_policy_groups.py b/ansible_collections/cisco/meraki/plugins/action/organizations_adaptive_policy_groups.py index f170a7ad0..7a871b57b 100644 --- a/ansible_collections/cisco/meraki/plugins/action/organizations_adaptive_policy_groups.py +++ b/ansible_collections/cisco/meraki/plugins/action/organizations_adaptive_policy_groups.py @@ -32,10 +32,10 @@ argument_spec = meraki_argument_spec() # Add arguments specific for this module argument_spec.update(dict( state=dict(type="str", default="present", choices=["present", "absent"]), - name=dict(type="str"), - sgt=dict(type="int"), description=dict(type="str"), + name=dict(type="str"), policyObjects=dict(type="list"), + sgt=dict(type="int"), organizationId=dict(type="str"), id=dict(type="str"), )) @@ -53,10 +53,10 @@ class OrganizationsAdaptivePolicyGroups(object): def __init__(self, params, meraki): self.meraki = meraki self.new_object = dict( - name=params.get("name"), - sgt=params.get("sgt"), description=params.get("description"), + name=params.get("name"), policyObjects=params.get("policyObjects"), + sgt=params.get("sgt"), organizationId=params.get("organizationId"), id=params.get("id"), ) @@ -79,18 +79,18 @@ class OrganizationsAdaptivePolicyGroups(object): def create_params(self): new_object_params = {} - if self.new_object.get('name') is not None or self.new_object.get('name') is not None: - new_object_params['name'] = self.new_object.get('name') or \ - self.new_object.get('name') - if self.new_object.get('sgt') is not None or self.new_object.get('sgt') is not None: - new_object_params['sgt'] = self.new_object.get('sgt') or \ - self.new_object.get('sgt') if self.new_object.get('description') is not None or self.new_object.get('description') is not None: new_object_params['description'] = self.new_object.get('description') or \ self.new_object.get('description') + if self.new_object.get('name') is not None or self.new_object.get('name') is not None: + new_object_params['name'] = self.new_object.get('name') or \ + self.new_object.get('name') if self.new_object.get('policyObjects') is not None or self.new_object.get('policy_objects') is not None: new_object_params['policyObjects'] = self.new_object.get('policyObjects') or \ self.new_object.get('policy_objects') + if self.new_object.get('sgt') is not None or self.new_object.get('sgt') is not None: + new_object_params['sgt'] = self.new_object.get('sgt') or \ + self.new_object.get('sgt') if self.new_object.get('organizationId') is not None or self.new_object.get('organization_id') is not None: new_object_params['organizationId'] = self.new_object.get('organizationId') or \ self.new_object.get('organization_id') @@ -108,18 +108,18 @@ class OrganizationsAdaptivePolicyGroups(object): def update_by_id_params(self): new_object_params = {} - if self.new_object.get('name') is not None or self.new_object.get('name') is not None: - new_object_params['name'] = self.new_object.get('name') or \ - self.new_object.get('name') - if self.new_object.get('sgt') is not None or self.new_object.get('sgt') is not None: - new_object_params['sgt'] = self.new_object.get('sgt') or \ - self.new_object.get('sgt') if self.new_object.get('description') is not None or self.new_object.get('description') is not None: new_object_params['description'] = self.new_object.get('description') or \ self.new_object.get('description') + if self.new_object.get('name') is not None or self.new_object.get('name') is not None: + new_object_params['name'] = self.new_object.get('name') or \ + self.new_object.get('name') if self.new_object.get('policyObjects') is not None or self.new_object.get('policy_objects') is not None: new_object_params['policyObjects'] = self.new_object.get('policyObjects') or \ self.new_object.get('policy_objects') + if self.new_object.get('sgt') is not None or self.new_object.get('sgt') is not None: + new_object_params['sgt'] = self.new_object.get('sgt') or \ + self.new_object.get('sgt') if self.new_object.get('organizationId') is not None or self.new_object.get('organization_id') is not None: new_object_params['organizationId'] = self.new_object.get('organizationId') or \ self.new_object.get('organization_id') @@ -193,10 +193,10 @@ class OrganizationsAdaptivePolicyGroups(object): requested_obj = self.new_object obj_params = [ - ("name", "name"), - ("sgt", "sgt"), ("description", "description"), + ("name", "name"), ("policyObjects", "policyObjects"), + ("sgt", "sgt"), ("organizationId", "organizationId"), ("id", "id"), ] diff --git a/ansible_collections/cisco/meraki/plugins/action/organizations_adaptive_policy_policies.py b/ansible_collections/cisco/meraki/plugins/action/organizations_adaptive_policy_policies.py index 9717b4aef..856b7ac16 100644 --- a/ansible_collections/cisco/meraki/plugins/action/organizations_adaptive_policy_policies.py +++ b/ansible_collections/cisco/meraki/plugins/action/organizations_adaptive_policy_policies.py @@ -32,10 +32,10 @@ argument_spec = meraki_argument_spec() # Add arguments specific for this module argument_spec.update(dict( state=dict(type="str", default="present", choices=["present", "absent"]), - sourceGroup=dict(type="dict"), - destinationGroup=dict(type="dict"), acls=dict(type="list"), + destinationGroup=dict(type="dict"), lastEntryRule=dict(type="str"), + sourceGroup=dict(type="dict"), organizationId=dict(type="str"), id=dict(type="str"), )) @@ -53,10 +53,10 @@ class OrganizationsAdaptivePolicyPolicies(object): def __init__(self, params, meraki): self.meraki = meraki self.new_object = dict( - sourceGroup=params.get("sourceGroup"), - destinationGroup=params.get("destinationGroup"), acls=params.get("acls"), + destinationGroup=params.get("destinationGroup"), lastEntryRule=params.get("lastEntryRule"), + sourceGroup=params.get("sourceGroup"), organizationId=params.get("organizationId"), id=params.get("id"), ) @@ -79,18 +79,18 @@ class OrganizationsAdaptivePolicyPolicies(object): def create_params(self): new_object_params = {} - if self.new_object.get('sourceGroup') is not None or self.new_object.get('source_group') is not None: - new_object_params['sourceGroup'] = self.new_object.get('sourceGroup') or \ - self.new_object.get('source_group') - if self.new_object.get('destinationGroup') is not None or self.new_object.get('destination_group') is not None: - new_object_params['destinationGroup'] = self.new_object.get('destinationGroup') or \ - self.new_object.get('destination_group') if self.new_object.get('acls') is not None or self.new_object.get('acls') is not None: new_object_params['acls'] = self.new_object.get('acls') or \ self.new_object.get('acls') + if self.new_object.get('destinationGroup') is not None or self.new_object.get('destination_group') is not None: + new_object_params['destinationGroup'] = self.new_object.get('destinationGroup') or \ + self.new_object.get('destination_group') if self.new_object.get('lastEntryRule') is not None or self.new_object.get('last_entry_rule') is not None: new_object_params['lastEntryRule'] = self.new_object.get('lastEntryRule') or \ self.new_object.get('last_entry_rule') + if self.new_object.get('sourceGroup') is not None or self.new_object.get('source_group') is not None: + new_object_params['sourceGroup'] = self.new_object.get('sourceGroup') or \ + self.new_object.get('source_group') if self.new_object.get('organizationId') is not None or self.new_object.get('organization_id') is not None: new_object_params['organizationId'] = self.new_object.get('organizationId') or \ self.new_object.get('organization_id') @@ -108,18 +108,18 @@ class OrganizationsAdaptivePolicyPolicies(object): def update_by_id_params(self): new_object_params = {} - if self.new_object.get('sourceGroup') is not None or self.new_object.get('source_group') is not None: - new_object_params['sourceGroup'] = self.new_object.get('sourceGroup') or \ - self.new_object.get('source_group') - if self.new_object.get('destinationGroup') is not None or self.new_object.get('destination_group') is not None: - new_object_params['destinationGroup'] = self.new_object.get('destinationGroup') or \ - self.new_object.get('destination_group') if self.new_object.get('acls') is not None or self.new_object.get('acls') is not None: new_object_params['acls'] = self.new_object.get('acls') or \ self.new_object.get('acls') + if self.new_object.get('destinationGroup') is not None or self.new_object.get('destination_group') is not None: + new_object_params['destinationGroup'] = self.new_object.get('destinationGroup') or \ + self.new_object.get('destination_group') if self.new_object.get('lastEntryRule') is not None or self.new_object.get('last_entry_rule') is not None: new_object_params['lastEntryRule'] = self.new_object.get('lastEntryRule') or \ self.new_object.get('last_entry_rule') + if self.new_object.get('sourceGroup') is not None or self.new_object.get('source_group') is not None: + new_object_params['sourceGroup'] = self.new_object.get('sourceGroup') or \ + self.new_object.get('source_group') if self.new_object.get('organizationId') is not None or self.new_object.get('organization_id') is not None: new_object_params['organizationId'] = self.new_object.get('organizationId') or \ self.new_object.get('organization_id') @@ -193,10 +193,10 @@ class OrganizationsAdaptivePolicyPolicies(object): requested_obj = self.new_object obj_params = [ - ("sourceGroup", "sourceGroup"), - ("destinationGroup", "destinationGroup"), ("acls", "acls"), + ("destinationGroup", "destinationGroup"), ("lastEntryRule", "lastEntryRule"), + ("sourceGroup", "sourceGroup"), ("organizationId", "organizationId"), ("id", "id"), ] diff --git a/ansible_collections/cisco/meraki/plugins/action/organizations_admins.py b/ansible_collections/cisco/meraki/plugins/action/organizations_admins.py index a9b2140ef..641befa29 100644 --- a/ansible_collections/cisco/meraki/plugins/action/organizations_admins.py +++ b/ansible_collections/cisco/meraki/plugins/action/organizations_admins.py @@ -32,12 +32,12 @@ argument_spec = meraki_argument_spec() # Add arguments specific for this module argument_spec.update(dict( state=dict(type="str", default="present", choices=["present", "absent"]), + authenticationMethod=dict(type="str"), email=dict(type="str"), name=dict(type="str"), + networks=dict(type="list"), orgAccess=dict(type="str"), tags=dict(type="list"), - networks=dict(type="list"), - authenticationMethod=dict(type="str"), organizationId=dict(type="str"), adminId=dict(type="str"), )) @@ -55,12 +55,12 @@ class OrganizationsAdmins(object): def __init__(self, params, meraki): self.meraki = meraki self.new_object = dict( + authenticationMethod=params.get("authenticationMethod"), email=params.get("email"), name=params.get("name"), + networks=params.get("networks"), orgAccess=params.get("orgAccess"), tags=params.get("tags"), - networks=params.get("networks"), - authenticationMethod=params.get("authenticationMethod"), organizationId=params.get("organizationId"), adminId=params.get("adminId"), ) @@ -74,24 +74,24 @@ class OrganizationsAdmins(object): def create_params(self): new_object_params = {} + if self.new_object.get('authenticationMethod') is not None or self.new_object.get('authentication_method') is not None: + new_object_params['authenticationMethod'] = self.new_object.get('authenticationMethod') or \ + self.new_object.get('authentication_method') if self.new_object.get('email') is not None or self.new_object.get('email') is not None: new_object_params['email'] = self.new_object.get('email') or \ self.new_object.get('email') if self.new_object.get('name') is not None or self.new_object.get('name') is not None: new_object_params['name'] = self.new_object.get('name') or \ self.new_object.get('name') + if self.new_object.get('networks') is not None or self.new_object.get('networks') is not None: + new_object_params['networks'] = self.new_object.get('networks') or \ + self.new_object.get('networks') if self.new_object.get('orgAccess') is not None or self.new_object.get('org_access') is not None: new_object_params['orgAccess'] = self.new_object.get('orgAccess') or \ self.new_object.get('org_access') if self.new_object.get('tags') is not None or self.new_object.get('tags') is not None: new_object_params['tags'] = self.new_object.get('tags') or \ self.new_object.get('tags') - if self.new_object.get('networks') is not None or self.new_object.get('networks') is not None: - new_object_params['networks'] = self.new_object.get('networks') or \ - self.new_object.get('networks') - if self.new_object.get('authenticationMethod') is not None or self.new_object.get('authentication_method') is not None: - new_object_params['authenticationMethod'] = self.new_object.get('authenticationMethod') or \ - self.new_object.get('authentication_method') if self.new_object.get('organizationId') is not None or self.new_object.get('organization_id') is not None: new_object_params['organizationId'] = self.new_object.get('organizationId') or \ self.new_object.get('organization_id') @@ -112,15 +112,15 @@ class OrganizationsAdmins(object): if self.new_object.get('name') is not None or self.new_object.get('name') is not None: new_object_params['name'] = self.new_object.get('name') or \ self.new_object.get('name') + if self.new_object.get('networks') is not None or self.new_object.get('networks') is not None: + new_object_params['networks'] = self.new_object.get('networks') or \ + self.new_object.get('networks') if self.new_object.get('orgAccess') is not None or self.new_object.get('org_access') is not None: new_object_params['orgAccess'] = self.new_object.get('orgAccess') or \ self.new_object.get('org_access') if self.new_object.get('tags') is not None or self.new_object.get('tags') is not None: new_object_params['tags'] = self.new_object.get('tags') or \ self.new_object.get('tags') - if self.new_object.get('networks') is not None or self.new_object.get('networks') is not None: - new_object_params['networks'] = self.new_object.get('networks') or \ - self.new_object.get('networks') if self.new_object.get('organizationId') is not None or self.new_object.get('organization_id') is not None: new_object_params['organizationId'] = self.new_object.get('organizationId') or \ self.new_object.get('organization_id') @@ -195,12 +195,12 @@ class OrganizationsAdmins(object): requested_obj = self.new_object obj_params = [ + ("authenticationMethod", "authenticationMethod"), ("email", "email"), ("name", "name"), + ("networks", "networks"), ("orgAccess", "orgAccess"), ("tags", "tags"), - ("networks", "networks"), - ("authenticationMethod", "authenticationMethod"), ("organizationId", "organizationId"), ("adminId", "adminId"), ] diff --git a/ansible_collections/cisco/meraki/plugins/action/organizations_alerts_profiles.py b/ansible_collections/cisco/meraki/plugins/action/organizations_alerts_profiles.py index cc046ea86..b773a76cc 100644 --- a/ansible_collections/cisco/meraki/plugins/action/organizations_alerts_profiles.py +++ b/ansible_collections/cisco/meraki/plugins/action/organizations_alerts_profiles.py @@ -31,11 +31,11 @@ argument_spec = meraki_argument_spec() # Add arguments specific for this module argument_spec.update(dict( state=dict(type="str", default="present", choices=["present", "absent"]), - type=dict(type="str"), alertCondition=dict(type="dict"), - recipients=dict(type="dict"), - networkTags=dict(type="list"), description=dict(type="str"), + networkTags=dict(type="list"), + recipients=dict(type="dict"), + type=dict(type="str"), organizationId=dict(type="str"), enabled=dict(type="bool"), alertConfigId=dict(type="str"), @@ -54,11 +54,11 @@ class OrganizationsAlertsProfiles(object): def __init__(self, params, meraki): self.meraki = meraki self.new_object = dict( - type=params.get("type"), alertCondition=params.get("alertCondition"), - recipients=params.get("recipients"), - networkTags=params.get("networkTags"), description=params.get("description"), + networkTags=params.get("networkTags"), + recipients=params.get("recipients"), + type=params.get("type"), organization_id=params.get("organizationId"), enabled=params.get("enabled"), alert_config_id=params.get("alertConfigId"), @@ -66,21 +66,21 @@ class OrganizationsAlertsProfiles(object): def create_params(self): new_object_params = {} - if self.new_object.get('type') is not None or self.new_object.get('type') is not None: - new_object_params['type'] = self.new_object.get('type') or \ - self.new_object.get('type') if self.new_object.get('alertCondition') is not None or self.new_object.get('alert_condition') is not None: new_object_params['alertCondition'] = self.new_object.get('alertCondition') or \ self.new_object.get('alert_condition') - if self.new_object.get('recipients') is not None or self.new_object.get('recipients') is not None: - new_object_params['recipients'] = self.new_object.get('recipients') or \ - self.new_object.get('recipients') - if self.new_object.get('networkTags') is not None or self.new_object.get('network_tags') is not None: - new_object_params['networkTags'] = self.new_object.get('networkTags') or \ - self.new_object.get('network_tags') if self.new_object.get('description') is not None or self.new_object.get('description') is not None: new_object_params['description'] = self.new_object.get('description') or \ self.new_object.get('description') + if self.new_object.get('networkTags') is not None or self.new_object.get('network_tags') is not None: + new_object_params['networkTags'] = self.new_object.get('networkTags') or \ + self.new_object.get('network_tags') + if self.new_object.get('recipients') is not None or self.new_object.get('recipients') is not None: + new_object_params['recipients'] = self.new_object.get('recipients') or \ + self.new_object.get('recipients') + if self.new_object.get('type') is not None or self.new_object.get('type') is not None: + new_object_params['type'] = self.new_object.get('type') or \ + self.new_object.get('type') if self.new_object.get('organizationId') is not None or self.new_object.get('organization_id') is not None: new_object_params['organizationId'] = self.new_object.get('organizationId') or \ self.new_object.get('organization_id') @@ -98,23 +98,23 @@ class OrganizationsAlertsProfiles(object): def update_by_id_params(self): new_object_params = {} - if self.new_object.get('enabled') is not None or self.new_object.get('enabled') is not None: - new_object_params['enabled'] = self.new_object.get('enabled') - if self.new_object.get('type') is not None or self.new_object.get('type') is not None: - new_object_params['type'] = self.new_object.get('type') or \ - self.new_object.get('type') if self.new_object.get('alertCondition') is not None or self.new_object.get('alert_condition') is not None: new_object_params['alertCondition'] = self.new_object.get('alertCondition') or \ self.new_object.get('alert_condition') - if self.new_object.get('recipients') is not None or self.new_object.get('recipients') is not None: - new_object_params['recipients'] = self.new_object.get('recipients') or \ - self.new_object.get('recipients') - if self.new_object.get('networkTags') is not None or self.new_object.get('network_tags') is not None: - new_object_params['networkTags'] = self.new_object.get('networkTags') or \ - self.new_object.get('network_tags') if self.new_object.get('description') is not None or self.new_object.get('description') is not None: new_object_params['description'] = self.new_object.get('description') or \ self.new_object.get('description') + if self.new_object.get('enabled') is not None or self.new_object.get('enabled') is not None: + new_object_params['enabled'] = self.new_object.get('enabled') + if self.new_object.get('networkTags') is not None or self.new_object.get('network_tags') is not None: + new_object_params['networkTags'] = self.new_object.get('networkTags') or \ + self.new_object.get('network_tags') + if self.new_object.get('recipients') is not None or self.new_object.get('recipients') is not None: + new_object_params['recipients'] = self.new_object.get('recipients') or \ + self.new_object.get('recipients') + if self.new_object.get('type') is not None or self.new_object.get('type') is not None: + new_object_params['type'] = self.new_object.get('type') or \ + self.new_object.get('type') if self.new_object.get('organizationId') is not None or self.new_object.get('organization_id') is not None: new_object_params['organizationId'] = self.new_object.get('organizationId') or \ self.new_object.get('organization_id') @@ -163,11 +163,11 @@ class OrganizationsAlertsProfiles(object): requested_obj = self.new_object obj_params = [ - ("type", "type"), ("alertCondition", "alertCondition"), - ("recipients", "recipients"), - ("networkTags", "networkTags"), ("description", "description"), + ("networkTags", "networkTags"), + ("recipients", "recipients"), + ("type", "type"), ("organizationId", "organizationId"), ("enabled", "enabled"), ("alertConfigId", "alertConfigId"), diff --git a/ansible_collections/cisco/meraki/plugins/action/organizations_appliance_traffic_shaping_vpn_exclusions_by_network_info.py b/ansible_collections/cisco/meraki/plugins/action/organizations_appliance_traffic_shaping_vpn_exclusions_by_network_info.py new file mode 100644 index 000000000..6aad7552f --- /dev/null +++ b/ansible_collections/cisco/meraki/plugins/action/organizations_appliance_traffic_shaping_vpn_exclusions_by_network_info.py @@ -0,0 +1,112 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +# Copyright (c) 2021, Cisco Systems +# 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 +from ansible.plugins.action import ActionBase +try: + from ansible_collections.ansible.utils.plugins.module_utils.common.argspec_validate import ( + AnsibleArgSpecValidator, + ) +except ImportError: + ANSIBLE_UTILS_IS_INSTALLED = False +else: + ANSIBLE_UTILS_IS_INSTALLED = True +from ansible.errors import AnsibleActionFail +from ansible_collections.cisco.meraki.plugins.plugin_utils.meraki import ( + MERAKI, + meraki_argument_spec, +) + +# Get common arguments specification +argument_spec = meraki_argument_spec() +# Add arguments specific for this module +argument_spec.update(dict( + organizationId=dict(type="str"), + perPage=dict(type="int"), + total_pages=dict(type="int"), + direction=dict(type="str"), + startingAfter=dict(type="str"), + endingBefore=dict(type="str"), + networkIds=dict(type="list"), +)) + +required_if = [] +required_one_of = [] +mutually_exclusive = [] +required_together = [] + + +class ActionModule(ActionBase): + def __init__(self, *args, **kwargs): + if not ANSIBLE_UTILS_IS_INSTALLED: + raise AnsibleActionFail( + "ansible.utils is not installed. Execute 'ansible-galaxy collection install ansible.utils'") + super(ActionModule, self).__init__(*args, **kwargs) + self._supports_async = False + self._supports_check_mode = True + self._result = None + + # Checks the supplied parameters against the argument spec for this module + def _check_argspec(self): + aav = AnsibleArgSpecValidator( + data=self._task.args, + schema=dict(argument_spec=argument_spec), + schema_format="argspec", + schema_conditionals=dict( + required_if=required_if, + required_one_of=required_one_of, + mutually_exclusive=mutually_exclusive, + required_together=required_together, + ), + name=self._task.action, + ) + valid, errors, self._task.args = aav.validate() + if not valid: + raise AnsibleActionFail(errors) + + def get_all(self, params): + new_object = {} + if params.get("organizationId") is not None: + new_object["organizationId"] = params.get( + "organizationId") + if params.get("perPage") is not None: + new_object["perPage"] = params.get( + "perPage") + new_object['total_pages'] = params.get( + "total_pages") or 1 + new_object['direction'] = params.get( + "direction") or "next" + if params.get("startingAfter") is not None: + new_object["startingAfter"] = params.get( + "startingAfter") + if params.get("endingBefore") is not None: + new_object["endingBefore"] = params.get( + "endingBefore") + if params.get("networkIds") is not None: + new_object["networkIds"] = params.get( + "networkIds") + + return new_object + + def run(self, tmp=None, task_vars=None): + self._task.diff = False + self._result = super(ActionModule, self).run(tmp, task_vars) + self._result["changed"] = False + self._check_argspec() + + self._result.update(dict(meraki_response={})) + + meraki = MERAKI(params=self._task.args) + + response = meraki.exec_meraki( + family="appliance", + function='getOrganizationApplianceTrafficShapingVpnExclusionsByNetwork', + params=self.get_all(self._task.args), + ) + self._result.update(dict(meraki_response=response)) + self._result.update(meraki.exit_json()) + return self._result diff --git a/ansible_collections/cisco/meraki/plugins/action/organizations_appliance_uplinks_statuses_overview_info.py b/ansible_collections/cisco/meraki/plugins/action/organizations_appliance_uplinks_statuses_overview_info.py new file mode 100644 index 000000000..8180b0eb2 --- /dev/null +++ b/ansible_collections/cisco/meraki/plugins/action/organizations_appliance_uplinks_statuses_overview_info.py @@ -0,0 +1,90 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +# Copyright (c) 2021, Cisco Systems +# 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 +from ansible.plugins.action import ActionBase +try: + from ansible_collections.ansible.utils.plugins.module_utils.common.argspec_validate import ( + AnsibleArgSpecValidator, + ) +except ImportError: + ANSIBLE_UTILS_IS_INSTALLED = False +else: + ANSIBLE_UTILS_IS_INSTALLED = True +from ansible.errors import AnsibleActionFail +from ansible_collections.cisco.meraki.plugins.plugin_utils.meraki import ( + MERAKI, + meraki_argument_spec, +) + +# Get common arguments specification +argument_spec = meraki_argument_spec() +# Add arguments specific for this module +argument_spec.update(dict( + organizationId=dict(type="str"), +)) + +required_if = [] +required_one_of = [] +mutually_exclusive = [] +required_together = [] + + +class ActionModule(ActionBase): + def __init__(self, *args, **kwargs): + if not ANSIBLE_UTILS_IS_INSTALLED: + raise AnsibleActionFail( + "ansible.utils is not installed. Execute 'ansible-galaxy collection install ansible.utils'") + super(ActionModule, self).__init__(*args, **kwargs) + self._supports_async = False + self._supports_check_mode = True + self._result = None + + # Checks the supplied parameters against the argument spec for this module + def _check_argspec(self): + aav = AnsibleArgSpecValidator( + data=self._task.args, + schema=dict(argument_spec=argument_spec), + schema_format="argspec", + schema_conditionals=dict( + required_if=required_if, + required_one_of=required_one_of, + mutually_exclusive=mutually_exclusive, + required_together=required_together, + ), + name=self._task.action, + ) + valid, errors, self._task.args = aav.validate() + if not valid: + raise AnsibleActionFail(errors) + + def get_all(self, params): + new_object = {} + if params.get("organizationId") is not None: + new_object["organizationId"] = params.get( + "organizationId") + + return new_object + + def run(self, tmp=None, task_vars=None): + self._task.diff = False + self._result = super(ActionModule, self).run(tmp, task_vars) + self._result["changed"] = False + self._check_argspec() + + self._result.update(dict(meraki_response={})) + + meraki = MERAKI(params=self._task.args) + + response = meraki.exec_meraki( + family="appliance", + function='getOrganizationApplianceUplinksStatusesOverview', + params=self.get_all(self._task.args), + ) + self._result.update(dict(meraki_response=response)) + self._result.update(meraki.exit_json()) + return self._result diff --git a/ansible_collections/cisco/meraki/plugins/action/organizations_appliance_uplinks_usage_by_network_info.py b/ansible_collections/cisco/meraki/plugins/action/organizations_appliance_uplinks_usage_by_network_info.py new file mode 100644 index 000000000..c52e2bac2 --- /dev/null +++ b/ansible_collections/cisco/meraki/plugins/action/organizations_appliance_uplinks_usage_by_network_info.py @@ -0,0 +1,102 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +# Copyright (c) 2021, Cisco Systems +# 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 +from ansible.plugins.action import ActionBase +try: + from ansible_collections.ansible.utils.plugins.module_utils.common.argspec_validate import ( + AnsibleArgSpecValidator, + ) +except ImportError: + ANSIBLE_UTILS_IS_INSTALLED = False +else: + ANSIBLE_UTILS_IS_INSTALLED = True +from ansible.errors import AnsibleActionFail +from ansible_collections.cisco.meraki.plugins.plugin_utils.meraki import ( + MERAKI, + meraki_argument_spec, +) + +# Get common arguments specification +argument_spec = meraki_argument_spec() +# Add arguments specific for this module +argument_spec.update(dict( + organizationId=dict(type="str"), + t0=dict(type="str"), + t1=dict(type="str"), + timespan=dict(type="float"), +)) + +required_if = [] +required_one_of = [] +mutually_exclusive = [] +required_together = [] + + +class ActionModule(ActionBase): + def __init__(self, *args, **kwargs): + if not ANSIBLE_UTILS_IS_INSTALLED: + raise AnsibleActionFail( + "ansible.utils is not installed. Execute 'ansible-galaxy collection install ansible.utils'") + super(ActionModule, self).__init__(*args, **kwargs) + self._supports_async = False + self._supports_check_mode = True + self._result = None + + # Checks the supplied parameters against the argument spec for this module + def _check_argspec(self): + aav = AnsibleArgSpecValidator( + data=self._task.args, + schema=dict(argument_spec=argument_spec), + schema_format="argspec", + schema_conditionals=dict( + required_if=required_if, + required_one_of=required_one_of, + mutually_exclusive=mutually_exclusive, + required_together=required_together, + ), + name=self._task.action, + ) + valid, errors, self._task.args = aav.validate() + if not valid: + raise AnsibleActionFail(errors) + + def get_all(self, params): + new_object = {} + if params.get("organizationId") is not None: + new_object["organizationId"] = params.get( + "organizationId") + if params.get("t0") is not None: + new_object["t0"] = params.get( + "t0") + if params.get("t1") is not None: + new_object["t1"] = params.get( + "t1") + if params.get("timespan") is not None: + new_object["timespan"] = params.get( + "timespan") + + return new_object + + def run(self, tmp=None, task_vars=None): + self._task.diff = False + self._result = super(ActionModule, self).run(tmp, task_vars) + self._result["changed"] = False + self._check_argspec() + + self._result.update(dict(meraki_response={})) + + meraki = MERAKI(params=self._task.args) + + response = meraki.exec_meraki( + family="appliance", + function='getOrganizationApplianceUplinksUsageByNetwork', + params=self.get_all(self._task.args), + ) + self._result.update(dict(meraki_response=response)) + self._result.update(meraki.exit_json()) + return self._result diff --git a/ansible_collections/cisco/meraki/plugins/action/organizations_branding_policies.py b/ansible_collections/cisco/meraki/plugins/action/organizations_branding_policies.py index 870c0370e..246f94575 100644 --- a/ansible_collections/cisco/meraki/plugins/action/organizations_branding_policies.py +++ b/ansible_collections/cisco/meraki/plugins/action/organizations_branding_policies.py @@ -32,11 +32,11 @@ argument_spec = meraki_argument_spec() # Add arguments specific for this module argument_spec.update(dict( state=dict(type="str", default="present", choices=["present", "absent"]), - name=dict(type="str"), - enabled=dict(type="bool"), adminSettings=dict(type="dict"), - helpSettings=dict(type="dict"), customLogo=dict(type="dict"), + enabled=dict(type="bool"), + helpSettings=dict(type="dict"), + name=dict(type="str"), organizationId=dict(type="str"), brandingPolicyId=dict(type="str"), )) @@ -54,11 +54,11 @@ class OrganizationsBrandingPolicies(object): def __init__(self, params, meraki): self.meraki = meraki self.new_object = dict( - name=params.get("name"), - enabled=params.get("enabled"), adminSettings=params.get("adminSettings"), - helpSettings=params.get("helpSettings"), customLogo=params.get("customLogo"), + enabled=params.get("enabled"), + helpSettings=params.get("helpSettings"), + name=params.get("name"), organizationId=params.get("organizationId"), brandingPolicyId=params.get("brandingPolicyId"), ) @@ -82,20 +82,20 @@ class OrganizationsBrandingPolicies(object): def create_params(self): new_object_params = {} - if self.new_object.get('name') is not None or self.new_object.get('name') is not None: - new_object_params['name'] = self.new_object.get('name') or \ - self.new_object.get('name') - if self.new_object.get('enabled') is not None or self.new_object.get('enabled') is not None: - new_object_params['enabled'] = self.new_object.get('enabled') if self.new_object.get('adminSettings') is not None or self.new_object.get('admin_settings') is not None: new_object_params['adminSettings'] = self.new_object.get('adminSettings') or \ self.new_object.get('admin_settings') - if self.new_object.get('helpSettings') is not None or self.new_object.get('help_settings') is not None: - new_object_params['helpSettings'] = self.new_object.get('helpSettings') or \ - self.new_object.get('help_settings') if self.new_object.get('customLogo') is not None or self.new_object.get('custom_logo') is not None: new_object_params['customLogo'] = self.new_object.get('customLogo') or \ self.new_object.get('custom_logo') + if self.new_object.get('enabled') is not None or self.new_object.get('enabled') is not None: + new_object_params['enabled'] = self.new_object.get('enabled') + if self.new_object.get('helpSettings') is not None or self.new_object.get('help_settings') is not None: + new_object_params['helpSettings'] = self.new_object.get('helpSettings') or \ + self.new_object.get('help_settings') + if self.new_object.get('name') is not None or self.new_object.get('name') is not None: + new_object_params['name'] = self.new_object.get('name') or \ + self.new_object.get('name') if self.new_object.get('organizationId') is not None or self.new_object.get('organization_id') is not None: new_object_params['organizationId'] = self.new_object.get('organizationId') or \ self.new_object.get('organization_id') @@ -113,20 +113,20 @@ class OrganizationsBrandingPolicies(object): def update_by_id_params(self): new_object_params = {} - if self.new_object.get('name') is not None or self.new_object.get('name') is not None: - new_object_params['name'] = self.new_object.get('name') or \ - self.new_object.get('name') - if self.new_object.get('enabled') is not None or self.new_object.get('enabled') is not None: - new_object_params['enabled'] = self.new_object.get('enabled') if self.new_object.get('adminSettings') is not None or self.new_object.get('admin_settings') is not None: new_object_params['adminSettings'] = self.new_object.get('adminSettings') or \ self.new_object.get('admin_settings') - if self.new_object.get('helpSettings') is not None or self.new_object.get('help_settings') is not None: - new_object_params['helpSettings'] = self.new_object.get('helpSettings') or \ - self.new_object.get('help_settings') if self.new_object.get('customLogo') is not None or self.new_object.get('custom_logo') is not None: new_object_params['customLogo'] = self.new_object.get('customLogo') or \ self.new_object.get('custom_logo') + if self.new_object.get('enabled') is not None or self.new_object.get('enabled') is not None: + new_object_params['enabled'] = self.new_object.get('enabled') + if self.new_object.get('helpSettings') is not None or self.new_object.get('help_settings') is not None: + new_object_params['helpSettings'] = self.new_object.get('helpSettings') or \ + self.new_object.get('help_settings') + if self.new_object.get('name') is not None or self.new_object.get('name') is not None: + new_object_params['name'] = self.new_object.get('name') or \ + self.new_object.get('name') if self.new_object.get('organizationId') is not None or self.new_object.get('organization_id') is not None: new_object_params['organizationId'] = self.new_object.get('organizationId') or \ self.new_object.get('organization_id') @@ -204,11 +204,11 @@ class OrganizationsBrandingPolicies(object): requested_obj = self.new_object obj_params = [ - ("name", "name"), - ("enabled", "enabled"), ("adminSettings", "adminSettings"), - ("helpSettings", "helpSettings"), ("customLogo", "customLogo"), + ("enabled", "enabled"), + ("helpSettings", "helpSettings"), + ("name", "name"), ("organizationId", "organizationId"), ("brandingPolicyId", "brandingPolicyId"), ] diff --git a/ansible_collections/cisco/meraki/plugins/action/organizations_camera_boundaries_areas_by_device_info.py b/ansible_collections/cisco/meraki/plugins/action/organizations_camera_boundaries_areas_by_device_info.py new file mode 100644 index 000000000..a54a4f830 --- /dev/null +++ b/ansible_collections/cisco/meraki/plugins/action/organizations_camera_boundaries_areas_by_device_info.py @@ -0,0 +1,94 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +# Copyright (c) 2021, Cisco Systems +# 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 +from ansible.plugins.action import ActionBase +try: + from ansible_collections.ansible.utils.plugins.module_utils.common.argspec_validate import ( + AnsibleArgSpecValidator, + ) +except ImportError: + ANSIBLE_UTILS_IS_INSTALLED = False +else: + ANSIBLE_UTILS_IS_INSTALLED = True +from ansible.errors import AnsibleActionFail +from ansible_collections.cisco.meraki.plugins.plugin_utils.meraki import ( + MERAKI, + meraki_argument_spec, +) + +# Get common arguments specification +argument_spec = meraki_argument_spec() +# Add arguments specific for this module +argument_spec.update(dict( + organizationId=dict(type="str"), + serials=dict(type="list"), +)) + +required_if = [] +required_one_of = [] +mutually_exclusive = [] +required_together = [] + + +class ActionModule(ActionBase): + def __init__(self, *args, **kwargs): + if not ANSIBLE_UTILS_IS_INSTALLED: + raise AnsibleActionFail( + "ansible.utils is not installed. Execute 'ansible-galaxy collection install ansible.utils'") + super(ActionModule, self).__init__(*args, **kwargs) + self._supports_async = False + self._supports_check_mode = True + self._result = None + + # Checks the supplied parameters against the argument spec for this module + def _check_argspec(self): + aav = AnsibleArgSpecValidator( + data=self._task.args, + schema=dict(argument_spec=argument_spec), + schema_format="argspec", + schema_conditionals=dict( + required_if=required_if, + required_one_of=required_one_of, + mutually_exclusive=mutually_exclusive, + required_together=required_together, + ), + name=self._task.action, + ) + valid, errors, self._task.args = aav.validate() + if not valid: + raise AnsibleActionFail(errors) + + def get_all(self, params): + new_object = {} + if params.get("organizationId") is not None: + new_object["organizationId"] = params.get( + "organizationId") + if params.get("serials") is not None: + new_object["serials"] = params.get( + "serials") + + return new_object + + def run(self, tmp=None, task_vars=None): + self._task.diff = False + self._result = super(ActionModule, self).run(tmp, task_vars) + self._result["changed"] = False + self._check_argspec() + + self._result.update(dict(meraki_response={})) + + meraki = MERAKI(params=self._task.args) + + response = meraki.exec_meraki( + family="camera", + function='getOrganizationCameraBoundariesAreasByDevice', + params=self.get_all(self._task.args), + ) + self._result.update(dict(meraki_response=response)) + self._result.update(meraki.exit_json()) + return self._result diff --git a/ansible_collections/cisco/meraki/plugins/action/organizations_camera_boundaries_lines_by_device_info.py b/ansible_collections/cisco/meraki/plugins/action/organizations_camera_boundaries_lines_by_device_info.py new file mode 100644 index 000000000..89f74a210 --- /dev/null +++ b/ansible_collections/cisco/meraki/plugins/action/organizations_camera_boundaries_lines_by_device_info.py @@ -0,0 +1,94 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +# Copyright (c) 2021, Cisco Systems +# 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 +from ansible.plugins.action import ActionBase +try: + from ansible_collections.ansible.utils.plugins.module_utils.common.argspec_validate import ( + AnsibleArgSpecValidator, + ) +except ImportError: + ANSIBLE_UTILS_IS_INSTALLED = False +else: + ANSIBLE_UTILS_IS_INSTALLED = True +from ansible.errors import AnsibleActionFail +from ansible_collections.cisco.meraki.plugins.plugin_utils.meraki import ( + MERAKI, + meraki_argument_spec, +) + +# Get common arguments specification +argument_spec = meraki_argument_spec() +# Add arguments specific for this module +argument_spec.update(dict( + organizationId=dict(type="str"), + serials=dict(type="list"), +)) + +required_if = [] +required_one_of = [] +mutually_exclusive = [] +required_together = [] + + +class ActionModule(ActionBase): + def __init__(self, *args, **kwargs): + if not ANSIBLE_UTILS_IS_INSTALLED: + raise AnsibleActionFail( + "ansible.utils is not installed. Execute 'ansible-galaxy collection install ansible.utils'") + super(ActionModule, self).__init__(*args, **kwargs) + self._supports_async = False + self._supports_check_mode = True + self._result = None + + # Checks the supplied parameters against the argument spec for this module + def _check_argspec(self): + aav = AnsibleArgSpecValidator( + data=self._task.args, + schema=dict(argument_spec=argument_spec), + schema_format="argspec", + schema_conditionals=dict( + required_if=required_if, + required_one_of=required_one_of, + mutually_exclusive=mutually_exclusive, + required_together=required_together, + ), + name=self._task.action, + ) + valid, errors, self._task.args = aav.validate() + if not valid: + raise AnsibleActionFail(errors) + + def get_all(self, params): + new_object = {} + if params.get("organizationId") is not None: + new_object["organizationId"] = params.get( + "organizationId") + if params.get("serials") is not None: + new_object["serials"] = params.get( + "serials") + + return new_object + + def run(self, tmp=None, task_vars=None): + self._task.diff = False + self._result = super(ActionModule, self).run(tmp, task_vars) + self._result["changed"] = False + self._check_argspec() + + self._result.update(dict(meraki_response={})) + + meraki = MERAKI(params=self._task.args) + + response = meraki.exec_meraki( + family="camera", + function='getOrganizationCameraBoundariesLinesByDevice', + params=self.get_all(self._task.args), + ) + self._result.update(dict(meraki_response=response)) + self._result.update(meraki.exit_json()) + return self._result diff --git a/ansible_collections/cisco/meraki/plugins/action/organizations_camera_detections_history_by_boundary_by_interval_info.py b/ansible_collections/cisco/meraki/plugins/action/organizations_camera_detections_history_by_boundary_by_interval_info.py new file mode 100644 index 000000000..fd9ef63d5 --- /dev/null +++ b/ansible_collections/cisco/meraki/plugins/action/organizations_camera_detections_history_by_boundary_by_interval_info.py @@ -0,0 +1,116 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +# Copyright (c) 2021, Cisco Systems +# 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 +from ansible.plugins.action import ActionBase +try: + from ansible_collections.ansible.utils.plugins.module_utils.common.argspec_validate import ( + AnsibleArgSpecValidator, + ) +except ImportError: + ANSIBLE_UTILS_IS_INSTALLED = False +else: + ANSIBLE_UTILS_IS_INSTALLED = True +from ansible.errors import AnsibleActionFail +from ansible_collections.cisco.meraki.plugins.plugin_utils.meraki import ( + MERAKI, + meraki_argument_spec, +) + +# Get common arguments specification +argument_spec = meraki_argument_spec() +# Add arguments specific for this module +argument_spec.update(dict( + organizationId=dict(type="str"), + boundaryIds=dict(type="list"), + ranges=dict(type="list"), + duration=dict(type="int"), + perPage=dict(type="int"), + total_pages=dict(type="int"), + direction=dict(type="str"), + boundaryTypes=dict(type="list"), +)) + +required_if = [] +required_one_of = [] +mutually_exclusive = [] +required_together = [] + + +class ActionModule(ActionBase): + def __init__(self, *args, **kwargs): + if not ANSIBLE_UTILS_IS_INSTALLED: + raise AnsibleActionFail( + "ansible.utils is not installed. Execute 'ansible-galaxy collection install ansible.utils'") + super(ActionModule, self).__init__(*args, **kwargs) + self._supports_async = False + self._supports_check_mode = True + self._result = None + + # Checks the supplied parameters against the argument spec for this module + def _check_argspec(self): + aav = AnsibleArgSpecValidator( + data=self._task.args, + schema=dict(argument_spec=argument_spec), + schema_format="argspec", + schema_conditionals=dict( + required_if=required_if, + required_one_of=required_one_of, + mutually_exclusive=mutually_exclusive, + required_together=required_together, + ), + name=self._task.action, + ) + valid, errors, self._task.args = aav.validate() + if not valid: + raise AnsibleActionFail(errors) + + def get_all(self, params): + new_object = {} + if params.get("organizationId") is not None: + new_object["organizationId"] = params.get( + "organizationId") + if params.get("boundaryIds") is not None: + new_object["boundaryIds"] = params.get( + "boundaryIds") + if params.get("ranges") is not None: + new_object["ranges"] = params.get( + "ranges") + if params.get("duration") is not None: + new_object["duration"] = params.get( + "duration") + if params.get("perPage") is not None: + new_object["perPage"] = params.get( + "perPage") + new_object['total_pages'] = params.get( + "total_pages") or 1 + new_object['direction'] = params.get( + "direction") or "next" + if params.get("boundaryTypes") is not None: + new_object["boundaryTypes"] = params.get( + "boundaryTypes") + + return new_object + + def run(self, tmp=None, task_vars=None): + self._task.diff = False + self._result = super(ActionModule, self).run(tmp, task_vars) + self._result["changed"] = False + self._check_argspec() + + self._result.update(dict(meraki_response={})) + + meraki = MERAKI(params=self._task.args) + + response = meraki.exec_meraki( + family="camera", + function='getOrganizationCameraDetectionsHistoryByBoundaryByInterval', + params=self.get_all(self._task.args), + ) + self._result.update(dict(meraki_response=response)) + self._result.update(meraki.exit_json()) + return self._result diff --git a/ansible_collections/cisco/meraki/plugins/action/organizations_camera_permissions_info.py b/ansible_collections/cisco/meraki/plugins/action/organizations_camera_permissions_info.py new file mode 100644 index 000000000..3eb13d08d --- /dev/null +++ b/ansible_collections/cisco/meraki/plugins/action/organizations_camera_permissions_info.py @@ -0,0 +1,102 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +# Copyright (c) 2021, Cisco Systems +# 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 +from ansible.plugins.action import ActionBase +try: + from ansible_collections.ansible.utils.plugins.module_utils.common.argspec_validate import ( + AnsibleArgSpecValidator, + ) +except ImportError: + ANSIBLE_UTILS_IS_INSTALLED = False +else: + ANSIBLE_UTILS_IS_INSTALLED = True +from ansible.errors import AnsibleActionFail +from ansible_collections.cisco.meraki.plugins.plugin_utils.meraki import ( + MERAKI, + meraki_argument_spec, +) + +# Get common arguments specification +argument_spec = meraki_argument_spec() +# Add arguments specific for this module +argument_spec.update(dict( + organizationId=dict(type="str"), + permissionScopeId=dict(type="str"), +)) + +required_if = [] +required_one_of = [] +mutually_exclusive = [] +required_together = [] + + +class ActionModule(ActionBase): + def __init__(self, *args, **kwargs): + if not ANSIBLE_UTILS_IS_INSTALLED: + raise AnsibleActionFail( + "ansible.utils is not installed. Execute 'ansible-galaxy collection install ansible.utils'") + super(ActionModule, self).__init__(*args, **kwargs) + self._supports_async = False + self._supports_check_mode = True + self._result = None + + # Checks the supplied parameters against the argument spec for this module + def _check_argspec(self): + aav = AnsibleArgSpecValidator( + data=self._task.args, + schema=dict(argument_spec=argument_spec), + schema_format="argspec", + schema_conditionals=dict( + required_if=required_if, + required_one_of=required_one_of, + mutually_exclusive=mutually_exclusive, + required_together=required_together, + ), + name=self._task.action, + ) + valid, errors, self._task.args = aav.validate() + if not valid: + raise AnsibleActionFail(errors) + + def get_object(self, params): + new_object = {} + if params.get("organizationId") is not None: + new_object["organizationId"] = params.get( + "organizationId") + if params.get("permissionScopeId") is not None: + new_object["permissionScopeId"] = params.get( + "permissionScopeId") + return new_object + + def run(self, tmp=None, task_vars=None): + self._task.diff = False + self._result = super(ActionModule, self).run(tmp, task_vars) + self._result["changed"] = False + self._check_argspec() + + self._result.update(dict(meraki_response={})) + + meraki = MERAKI(params=self._task.args) + + id = self._task.args.get("permissionScopeId") + if id: + response = meraki.exec_meraki( + family="camera", + function='getOrganizationCameraPermission', + params=self.get_object(self._task.args), + ) + self._result.update(dict(meraki_response=response)) + self._result.update(meraki.exit_json()) + return self._result + if not id: + # NOTE: Does not have a get all method or it is in another action + response = None + meraki.object_modify_result(changed=False, result="Module does not have get all, check arguments of module") + self._result.update(dict(meraki_response=response)) + self._result.update(meraki.exit_json()) + return self._result diff --git a/ansible_collections/cisco/meraki/plugins/action/organizations_camera_roles.py b/ansible_collections/cisco/meraki/plugins/action/organizations_camera_roles.py new file mode 100644 index 000000000..222b2503d --- /dev/null +++ b/ansible_collections/cisco/meraki/plugins/action/organizations_camera_roles.py @@ -0,0 +1,252 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +# Copyright (c) 2021, Cisco Systems +# 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 +from ansible.plugins.action import ActionBase +try: + from ansible_collections.ansible.utils.plugins.module_utils.common.argspec_validate import ( + AnsibleArgSpecValidator, + ) +except ImportError: + ANSIBLE_UTILS_IS_INSTALLED = False +else: + ANSIBLE_UTILS_IS_INSTALLED = True +from ansible.errors import AnsibleActionFail +from ansible_collections.cisco.meraki.plugins.plugin_utils.meraki import ( + MERAKI, + meraki_argument_spec, + meraki_compare_equality, + get_dict_result, +) +from ansible_collections.cisco.meraki.plugins.plugin_utils.exceptions import ( + InconsistentParameters, +) + +# Get common arguments specification +argument_spec = meraki_argument_spec() +# Add arguments specific for this module +argument_spec.update(dict( + state=dict(type="str", default="present", choices=["present", "absent"]), + appliedOnDevices=dict(type="list"), + appliedOnNetworks=dict(type="list"), + appliedOrgWide=dict(type="list"), + name=dict(type="str"), + organizationId=dict(type="str"), +)) + +required_if = [ + ("state", "present", ["name", "organizationId"], True), + ("state", "absent", ["name", "organizationId"], True), +] +required_one_of = [] +mutually_exclusive = [] +required_together = [] + + +class OrganizationsCameraRoles(object): + def __init__(self, params, meraki): + self.meraki = meraki + self.new_object = dict( + appliedOnDevices=params.get("appliedOnDevices"), + appliedOnNetworks=params.get("appliedOnNetworks"), + appliedOrgWide=params.get("appliedOrgWide"), + name=params.get("name"), + organizationId=params.get("organizationId"), + ) + + def get_all_params(self, name=None, id=None): + new_object_params = {} + if self.new_object.get('organizationId') is not None or self.new_object.get('organization_id') is not None: + new_object_params['organizationId'] = self.new_object.get('organizationId') or \ + self.new_object.get('organization_id') + return new_object_params + + def create_params(self): + new_object_params = {} + if self.new_object.get('appliedOnDevices') is not None or self.new_object.get('applied_on_devices') is not None: + new_object_params['appliedOnDevices'] = self.new_object.get('appliedOnDevices') or \ + self.new_object.get('applied_on_devices') + if self.new_object.get('appliedOnNetworks') is not None or self.new_object.get('applied_on_networks') is not None: + new_object_params['appliedOnNetworks'] = self.new_object.get('appliedOnNetworks') or \ + self.new_object.get('applied_on_networks') + if self.new_object.get('appliedOrgWide') is not None or self.new_object.get('applied_org_wide') is not None: + new_object_params['appliedOrgWide'] = self.new_object.get('appliedOrgWide') or \ + self.new_object.get('applied_org_wide') + if self.new_object.get('name') is not None or self.new_object.get('name') is not None: + new_object_params['name'] = self.new_object.get('name') or \ + self.new_object.get('name') + if self.new_object.get('organizationId') is not None or self.new_object.get('organization_id') is not None: + new_object_params['organizationId'] = self.new_object.get('organizationId') or \ + self.new_object.get('organization_id') + return new_object_params + + def get_object_by_name(self, name): + result = None + # NOTE: Does not have a get by name method or it is in another action + try: + items = self.meraki.exec_meraki( + family="camera", + function="getOrganizationCameraRoles", + params=self.get_all_params(name=name), + ) + if isinstance(items, dict): + if 'response' in items: + items = items.get('response') + result = get_dict_result(items, 'name', name) + if result is None: + result = items + except Exception as e: + print("Error: ", e) + result = None + return result + + def get_object_by_id(self, id): + result = None + # NOTE: Does not have a get by id method or it is in another action + try: + items = self.meraki.exec_meraki( + family="camera", + function="getOrganizationCameraRoles", + params=self.get_all_params(id=id), + ) + if isinstance(items, dict): + if 'response' in items: + items = items.get('response') + result = get_dict_result(items, 'id', id) + except Exception as e: + print("Error: ", e) + result = None + return result + + def exists(self): + id_exists = False + name_exists = False + prev_obj = None + o_id = self.new_object.get("id") + name = self.new_object.get("name") + if o_id: + prev_obj = self.get_object_by_id(o_id) + id_exists = prev_obj is not None and isinstance(prev_obj, dict) + if not id_exists and name: + prev_obj = self.get_object_by_name(name) + name_exists = prev_obj is not None and isinstance(prev_obj, dict) + if name_exists: + _id = prev_obj.get("id") + if id_exists and name_exists and o_id != _id: + raise InconsistentParameters( + "The 'id' and 'name' params don't refer to the same object") + if _id: + self.new_object.update(dict(id=_id)) + it_exists = prev_obj is not None and isinstance(prev_obj, dict) + return (it_exists, prev_obj) + + def requires_update(self, current_obj): + requested_obj = self.new_object + + obj_params = [ + ("appliedOnDevices", "appliedOnDevices"), + ("appliedOnNetworks", "appliedOnNetworks"), + ("appliedOrgWide", "appliedOrgWide"), + ("name", "name"), + ("organizationId", "organizationId"), + ] + # Method 1. Params present in request (Ansible) obj are the same as the current (DNAC) params + # If any does not have eq params, it requires update + return any(not meraki_compare_equality(current_obj.get(meraki_param), + requested_obj.get(ansible_param)) + for (meraki_param, ansible_param) in obj_params) + + def create(self): + result = self.meraki.exec_meraki( + family="camera", + function="createOrganizationCameraRole", + params=self.create_params(), + op_modifies=True, + ) + return result + + def update(self): + id = self.new_object.get("id") + name = self.new_object.get("name") + result = None + # NOTE: Does not have update method. What do we do? + return result + + def delete(self): + id = self.new_object.get("id") + name = self.new_object.get("name") + result = None + # NOTE: Does not have delete method. What do we do? + return result + + +class ActionModule(ActionBase): + def __init__(self, *args, **kwargs): + if not ANSIBLE_UTILS_IS_INSTALLED: + raise AnsibleActionFail( + "ansible.utils is not installed. Execute 'ansible-galaxy collection install ansible.utils'") + super(ActionModule, self).__init__(*args, **kwargs) + self._supports_async = False + self._supports_check_mode = False + self._result = None + + # Checks the supplied parameters against the argument spec for this module + def _check_argspec(self): + aav = AnsibleArgSpecValidator( + data=self._task.args, + schema=dict(argument_spec=argument_spec), + schema_format="argspec", + schema_conditionals=dict( + required_if=required_if, + required_one_of=required_one_of, + mutually_exclusive=mutually_exclusive, + required_together=required_together, + ), + name=self._task.action, + ) + valid, errors, self._task.args = aav.validate() + if not valid: + raise AnsibleActionFail(errors) + + def run(self, tmp=None, task_vars=None): + self._task.diff = False + self._result = super(ActionModule, self).run(tmp, task_vars) + self._result["changed"] = False + self._check_argspec() + + meraki = MERAKI(self._task.args) + obj = OrganizationsCameraRoles(self._task.args, meraki) + + state = self._task.args.get("state") + + response = None + + if state == "present": + (obj_exists, prev_obj) = obj.exists() + if obj_exists: + if obj.requires_update(prev_obj): + response = obj.update() + meraki.object_updated() + else: + response = prev_obj + meraki.object_already_present() + else: + response = obj.create() + meraki.object_created() + + elif state == "absent": + (obj_exists, prev_obj) = obj.exists() + if obj_exists: + response = obj.delete() + meraki.object_deleted() + else: + meraki.object_already_absent() + + self._result.update(dict(meraki_response=response)) + self._result.update(meraki.exit_json()) + return self._result diff --git a/ansible_collections/cisco/meraki/plugins/action/organizations_camera_roles_info.py b/ansible_collections/cisco/meraki/plugins/action/organizations_camera_roles_info.py new file mode 100644 index 000000000..2a100b4e2 --- /dev/null +++ b/ansible_collections/cisco/meraki/plugins/action/organizations_camera_roles_info.py @@ -0,0 +1,90 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +# Copyright (c) 2021, Cisco Systems +# 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 +from ansible.plugins.action import ActionBase +try: + from ansible_collections.ansible.utils.plugins.module_utils.common.argspec_validate import ( + AnsibleArgSpecValidator, + ) +except ImportError: + ANSIBLE_UTILS_IS_INSTALLED = False +else: + ANSIBLE_UTILS_IS_INSTALLED = True +from ansible.errors import AnsibleActionFail +from ansible_collections.cisco.meraki.plugins.plugin_utils.meraki import ( + MERAKI, + meraki_argument_spec, +) + +# Get common arguments specification +argument_spec = meraki_argument_spec() +# Add arguments specific for this module +argument_spec.update(dict( + organizationId=dict(type="str"), +)) + +required_if = [] +required_one_of = [] +mutually_exclusive = [] +required_together = [] + + +class ActionModule(ActionBase): + def __init__(self, *args, **kwargs): + if not ANSIBLE_UTILS_IS_INSTALLED: + raise AnsibleActionFail( + "ansible.utils is not installed. Execute 'ansible-galaxy collection install ansible.utils'") + super(ActionModule, self).__init__(*args, **kwargs) + self._supports_async = False + self._supports_check_mode = True + self._result = None + + # Checks the supplied parameters against the argument spec for this module + def _check_argspec(self): + aav = AnsibleArgSpecValidator( + data=self._task.args, + schema=dict(argument_spec=argument_spec), + schema_format="argspec", + schema_conditionals=dict( + required_if=required_if, + required_one_of=required_one_of, + mutually_exclusive=mutually_exclusive, + required_together=required_together, + ), + name=self._task.action, + ) + valid, errors, self._task.args = aav.validate() + if not valid: + raise AnsibleActionFail(errors) + + def get_all(self, params): + new_object = {} + if params.get("organizationId") is not None: + new_object["organizationId"] = params.get( + "organizationId") + + return new_object + + def run(self, tmp=None, task_vars=None): + self._task.diff = False + self._result = super(ActionModule, self).run(tmp, task_vars) + self._result["changed"] = False + self._check_argspec() + + self._result.update(dict(meraki_response={})) + + meraki = MERAKI(params=self._task.args) + + response = meraki.exec_meraki( + family="camera", + function='getOrganizationCameraRoles', + params=self.get_all(self._task.args), + ) + self._result.update(dict(meraki_response=response)) + self._result.update(meraki.exit_json()) + return self._result diff --git a/ansible_collections/cisco/meraki/plugins/action/organizations_claim.py b/ansible_collections/cisco/meraki/plugins/action/organizations_claim.py index 5439a5af8..6f3a8ef92 100644 --- a/ansible_collections/cisco/meraki/plugins/action/organizations_claim.py +++ b/ansible_collections/cisco/meraki/plugins/action/organizations_claim.py @@ -25,9 +25,9 @@ from ansible_collections.cisco.meraki.plugins.plugin_utils.meraki import ( argument_spec = meraki_argument_spec() # Add arguments specific for this module argument_spec.update(dict( + licenses=dict(type="list"), orders=dict(type="list"), serials=dict(type="list"), - licenses=dict(type="list"), organizationId=dict(type="str"), )) @@ -67,9 +67,9 @@ class ActionModule(ActionBase): def get_object(self, params): new_object = dict( + licenses=params.get("licenses"), orders=params.get("orders"), serials=params.get("serials"), - licenses=params.get("licenses"), organizationId=params.get("organizationId"), ) return new_object diff --git a/ansible_collections/cisco/meraki/plugins/action/organizations_config_templates.py b/ansible_collections/cisco/meraki/plugins/action/organizations_config_templates.py index 09dc845b0..1811392e7 100644 --- a/ansible_collections/cisco/meraki/plugins/action/organizations_config_templates.py +++ b/ansible_collections/cisco/meraki/plugins/action/organizations_config_templates.py @@ -32,6 +32,7 @@ argument_spec = meraki_argument_spec() # Add arguments specific for this module argument_spec.update(dict( state=dict(type="str", default="present", choices=["present", "absent"]), + copyFromNetworkId=dict(type="str"), name=dict(type="str"), timeZone=dict(type="str"), organizationId=dict(type="str"), @@ -51,6 +52,7 @@ class OrganizationsConfigTemplates(object): def __init__(self, params, meraki): self.meraki = meraki self.new_object = dict( + copyFromNetworkId=params.get("copyFromNetworkId"), name=params.get("name"), timeZone=params.get("timeZone"), organizationId=params.get("organizationId"), @@ -76,6 +78,9 @@ class OrganizationsConfigTemplates(object): def create_params(self): new_object_params = {} + if self.new_object.get('copyFromNetworkId') is not None or self.new_object.get('copy_from_network_id') is not None: + new_object_params['copyFromNetworkId'] = self.new_object.get('copyFromNetworkId') or \ + self.new_object.get('copy_from_network_id') if self.new_object.get('name') is not None or self.new_object.get('name') is not None: new_object_params['name'] = self.new_object.get('name') or \ self.new_object.get('name') @@ -182,6 +187,7 @@ class OrganizationsConfigTemplates(object): requested_obj = self.new_object obj_params = [ + ("copyFromNetworkId", "copyFromNetworkId"), ("name", "name"), ("timeZone", "timeZone"), ("organizationId", "organizationId"), diff --git a/ansible_collections/cisco/meraki/plugins/action/organizations_config_templates_switch_profiles_ports.py b/ansible_collections/cisco/meraki/plugins/action/organizations_config_templates_switch_profiles_ports.py index 38cd937fc..82963b4b0 100644 --- a/ansible_collections/cisco/meraki/plugins/action/organizations_config_templates_switch_profiles_ports.py +++ b/ansible_collections/cisco/meraki/plugins/action/organizations_config_templates_switch_profiles_ports.py @@ -32,29 +32,29 @@ argument_spec = meraki_argument_spec() # Add arguments specific for this module argument_spec.update(dict( state=dict(type="str", default="present", choices=["present"]), - name=dict(type="str"), - tags=dict(type="list"), - enabled=dict(type="bool"), - poeEnabled=dict(type="bool"), - type=dict(type="str"), - vlan=dict(type="int"), - voiceVlan=dict(type="int"), + accessPolicyNumber=dict(type="int"), + accessPolicyType=dict(type="str"), allowedVlans=dict(type="str"), + daiTrusted=dict(type="bool"), + enabled=dict(type="bool"), + flexibleStackingEnabled=dict(type="bool"), isolationEnabled=dict(type="bool"), - rstpEnabled=dict(type="bool"), - stpGuard=dict(type="str"), linkNegotiation=dict(type="str"), - portScheduleId=dict(type="str"), - udld=dict(type="str"), - accessPolicyType=dict(type="str"), - accessPolicyNumber=dict(type="int"), macAllowList=dict(type="list"), + name=dict(type="str"), + poeEnabled=dict(type="bool"), + portScheduleId=dict(type="str"), + profile=dict(type="dict"), + rstpEnabled=dict(type="bool"), stickyMacAllowList=dict(type="list"), stickyMacAllowListLimit=dict(type="int"), stormControlEnabled=dict(type="bool"), - flexibleStackingEnabled=dict(type="bool"), - daiTrusted=dict(type="bool"), - profile=dict(type="dict"), + stpGuard=dict(type="str"), + tags=dict(type="list"), + type=dict(type="str"), + udld=dict(type="str"), + vlan=dict(type="int"), + voiceVlan=dict(type="int"), organizationId=dict(type="str"), configTemplateId=dict(type="str"), profileId=dict(type="str"), @@ -73,29 +73,29 @@ class OrganizationsConfigTemplatesSwitchProfilesPorts(object): def __init__(self, params, meraki): self.meraki = meraki self.new_object = dict( - name=params.get("name"), - tags=params.get("tags"), - enabled=params.get("enabled"), - poeEnabled=params.get("poeEnabled"), - type=params.get("type"), - vlan=params.get("vlan"), - voiceVlan=params.get("voiceVlan"), + accessPolicyNumber=params.get("accessPolicyNumber"), + accessPolicyType=params.get("accessPolicyType"), allowedVlans=params.get("allowedVlans"), + daiTrusted=params.get("daiTrusted"), + enabled=params.get("enabled"), + flexibleStackingEnabled=params.get("flexibleStackingEnabled"), isolationEnabled=params.get("isolationEnabled"), - rstpEnabled=params.get("rstpEnabled"), - stpGuard=params.get("stpGuard"), linkNegotiation=params.get("linkNegotiation"), - portScheduleId=params.get("portScheduleId"), - udld=params.get("udld"), - accessPolicyType=params.get("accessPolicyType"), - accessPolicyNumber=params.get("accessPolicyNumber"), macAllowList=params.get("macAllowList"), + name=params.get("name"), + poeEnabled=params.get("poeEnabled"), + portScheduleId=params.get("portScheduleId"), + profile=params.get("profile"), + rstpEnabled=params.get("rstpEnabled"), stickyMacAllowList=params.get("stickyMacAllowList"), stickyMacAllowListLimit=params.get("stickyMacAllowListLimit"), stormControlEnabled=params.get("stormControlEnabled"), - flexibleStackingEnabled=params.get("flexibleStackingEnabled"), - daiTrusted=params.get("daiTrusted"), - profile=params.get("profile"), + stpGuard=params.get("stpGuard"), + tags=params.get("tags"), + type=params.get("type"), + udld=params.get("udld"), + vlan=params.get("vlan"), + voiceVlan=params.get("voiceVlan"), organization_id=params.get("organizationId"), config_template_id=params.get("configTemplateId"), profile_id=params.get("profileId"), @@ -133,53 +133,42 @@ class OrganizationsConfigTemplatesSwitchProfilesPorts(object): def update_by_id_params(self): new_object_params = {} - if self.new_object.get('name') is not None or self.new_object.get('name') is not None: - new_object_params['name'] = self.new_object.get('name') or \ - self.new_object.get('name') - if self.new_object.get('tags') is not None or self.new_object.get('tags') is not None: - new_object_params['tags'] = self.new_object.get('tags') or \ - self.new_object.get('tags') - if self.new_object.get('enabled') is not None or self.new_object.get('enabled') is not None: - new_object_params['enabled'] = self.new_object.get('enabled') - if self.new_object.get('poeEnabled') is not None or self.new_object.get('poe_enabled') is not None: - new_object_params['poeEnabled'] = self.new_object.get('poeEnabled') - if self.new_object.get('type') is not None or self.new_object.get('type') is not None: - new_object_params['type'] = self.new_object.get('type') or \ - self.new_object.get('type') - if self.new_object.get('vlan') is not None or self.new_object.get('vlan') is not None: - new_object_params['vlan'] = self.new_object.get('vlan') or \ - self.new_object.get('vlan') - if self.new_object.get('voiceVlan') is not None or self.new_object.get('voice_vlan') is not None: - new_object_params['voiceVlan'] = self.new_object.get('voiceVlan') or \ - self.new_object.get('voice_vlan') + if self.new_object.get('accessPolicyNumber') is not None or self.new_object.get('access_policy_number') is not None: + new_object_params['accessPolicyNumber'] = self.new_object.get('accessPolicyNumber') or \ + self.new_object.get('access_policy_number') + if self.new_object.get('accessPolicyType') is not None or self.new_object.get('access_policy_type') is not None: + new_object_params['accessPolicyType'] = self.new_object.get('accessPolicyType') or \ + self.new_object.get('access_policy_type') if self.new_object.get('allowedVlans') is not None or self.new_object.get('allowed_vlans') is not None: new_object_params['allowedVlans'] = self.new_object.get('allowedVlans') or \ self.new_object.get('allowed_vlans') + if self.new_object.get('daiTrusted') is not None or self.new_object.get('dai_trusted') is not None: + new_object_params['daiTrusted'] = self.new_object.get('daiTrusted') + if self.new_object.get('enabled') is not None or self.new_object.get('enabled') is not None: + new_object_params['enabled'] = self.new_object.get('enabled') + if self.new_object.get('flexibleStackingEnabled') is not None or self.new_object.get('flexible_stacking_enabled') is not None: + new_object_params['flexibleStackingEnabled'] = self.new_object.get('flexibleStackingEnabled') if self.new_object.get('isolationEnabled') is not None or self.new_object.get('isolation_enabled') is not None: new_object_params['isolationEnabled'] = self.new_object.get('isolationEnabled') - if self.new_object.get('rstpEnabled') is not None or self.new_object.get('rstp_enabled') is not None: - new_object_params['rstpEnabled'] = self.new_object.get('rstpEnabled') - if self.new_object.get('stpGuard') is not None or self.new_object.get('stp_guard') is not None: - new_object_params['stpGuard'] = self.new_object.get('stpGuard') or \ - self.new_object.get('stp_guard') if self.new_object.get('linkNegotiation') is not None or self.new_object.get('link_negotiation') is not None: new_object_params['linkNegotiation'] = self.new_object.get('linkNegotiation') or \ self.new_object.get('link_negotiation') - if self.new_object.get('portScheduleId') is not None or self.new_object.get('port_schedule_id') is not None: - new_object_params['portScheduleId'] = self.new_object.get('portScheduleId') or \ - self.new_object.get('port_schedule_id') - if self.new_object.get('udld') is not None or self.new_object.get('udld') is not None: - new_object_params['udld'] = self.new_object.get('udld') or \ - self.new_object.get('udld') - if self.new_object.get('accessPolicyType') is not None or self.new_object.get('access_policy_type') is not None: - new_object_params['accessPolicyType'] = self.new_object.get('accessPolicyType') or \ - self.new_object.get('access_policy_type') - if self.new_object.get('accessPolicyNumber') is not None or self.new_object.get('access_policy_number') is not None: - new_object_params['accessPolicyNumber'] = self.new_object.get('accessPolicyNumber') or \ - self.new_object.get('access_policy_number') if self.new_object.get('macAllowList') is not None or self.new_object.get('mac_allow_list') is not None: new_object_params['macAllowList'] = self.new_object.get('macAllowList') or \ self.new_object.get('mac_allow_list') + if self.new_object.get('name') is not None or self.new_object.get('name') is not None: + new_object_params['name'] = self.new_object.get('name') or \ + self.new_object.get('name') + if self.new_object.get('poeEnabled') is not None or self.new_object.get('poe_enabled') is not None: + new_object_params['poeEnabled'] = self.new_object.get('poeEnabled') + if self.new_object.get('portScheduleId') is not None or self.new_object.get('port_schedule_id') is not None: + new_object_params['portScheduleId'] = self.new_object.get('portScheduleId') or \ + self.new_object.get('port_schedule_id') + if self.new_object.get('profile') is not None or self.new_object.get('profile') is not None: + new_object_params['profile'] = self.new_object.get('profile') or \ + self.new_object.get('profile') + if self.new_object.get('rstpEnabled') is not None or self.new_object.get('rstp_enabled') is not None: + new_object_params['rstpEnabled'] = self.new_object.get('rstpEnabled') if self.new_object.get('stickyMacAllowList') is not None or self.new_object.get('sticky_mac_allow_list') is not None: new_object_params['stickyMacAllowList'] = self.new_object.get('stickyMacAllowList') or \ self.new_object.get('sticky_mac_allow_list') @@ -188,13 +177,24 @@ class OrganizationsConfigTemplatesSwitchProfilesPorts(object): self.new_object.get('sticky_mac_allow_list_limit') if self.new_object.get('stormControlEnabled') is not None or self.new_object.get('storm_control_enabled') is not None: new_object_params['stormControlEnabled'] = self.new_object.get('stormControlEnabled') - if self.new_object.get('flexibleStackingEnabled') is not None or self.new_object.get('flexible_stacking_enabled') is not None: - new_object_params['flexibleStackingEnabled'] = self.new_object.get('flexibleStackingEnabled') - if self.new_object.get('daiTrusted') is not None or self.new_object.get('dai_trusted') is not None: - new_object_params['daiTrusted'] = self.new_object.get('daiTrusted') - if self.new_object.get('profile') is not None or self.new_object.get('profile') is not None: - new_object_params['profile'] = self.new_object.get('profile') or \ - self.new_object.get('profile') + if self.new_object.get('stpGuard') is not None or self.new_object.get('stp_guard') is not None: + new_object_params['stpGuard'] = self.new_object.get('stpGuard') or \ + self.new_object.get('stp_guard') + if self.new_object.get('tags') is not None or self.new_object.get('tags') is not None: + new_object_params['tags'] = self.new_object.get('tags') or \ + self.new_object.get('tags') + if self.new_object.get('type') is not None or self.new_object.get('type') is not None: + new_object_params['type'] = self.new_object.get('type') or \ + self.new_object.get('type') + if self.new_object.get('udld') is not None or self.new_object.get('udld') is not None: + new_object_params['udld'] = self.new_object.get('udld') or \ + self.new_object.get('udld') + if self.new_object.get('vlan') is not None or self.new_object.get('vlan') is not None: + new_object_params['vlan'] = self.new_object.get('vlan') or \ + self.new_object.get('vlan') + if self.new_object.get('voiceVlan') is not None or self.new_object.get('voice_vlan') is not None: + new_object_params['voiceVlan'] = self.new_object.get('voiceVlan') or \ + self.new_object.get('voice_vlan') if self.new_object.get('organizationId') is not None or self.new_object.get('organization_id') is not None: new_object_params['organizationId'] = self.new_object.get('organizationId') or \ self.new_object.get('organization_id') @@ -278,29 +278,29 @@ class OrganizationsConfigTemplatesSwitchProfilesPorts(object): requested_obj = self.new_object obj_params = [ - ("name", "name"), - ("tags", "tags"), - ("enabled", "enabled"), - ("poeEnabled", "poeEnabled"), - ("type", "type"), - ("vlan", "vlan"), - ("voiceVlan", "voiceVlan"), + ("accessPolicyNumber", "accessPolicyNumber"), + ("accessPolicyType", "accessPolicyType"), ("allowedVlans", "allowedVlans"), + ("daiTrusted", "daiTrusted"), + ("enabled", "enabled"), + ("flexibleStackingEnabled", "flexibleStackingEnabled"), ("isolationEnabled", "isolationEnabled"), - ("rstpEnabled", "rstpEnabled"), - ("stpGuard", "stpGuard"), ("linkNegotiation", "linkNegotiation"), - ("portScheduleId", "portScheduleId"), - ("udld", "udld"), - ("accessPolicyType", "accessPolicyType"), - ("accessPolicyNumber", "accessPolicyNumber"), ("macAllowList", "macAllowList"), + ("name", "name"), + ("poeEnabled", "poeEnabled"), + ("portScheduleId", "portScheduleId"), + ("profile", "profile"), + ("rstpEnabled", "rstpEnabled"), ("stickyMacAllowList", "stickyMacAllowList"), ("stickyMacAllowListLimit", "stickyMacAllowListLimit"), ("stormControlEnabled", "stormControlEnabled"), - ("flexibleStackingEnabled", "flexibleStackingEnabled"), - ("daiTrusted", "daiTrusted"), - ("profile", "profile"), + ("stpGuard", "stpGuard"), + ("tags", "tags"), + ("type", "type"), + ("udld", "udld"), + ("vlan", "vlan"), + ("voiceVlan", "voiceVlan"), ("organizationId", "organizationId"), ("configTemplateId", "configTemplateId"), ("profileId", "profileId"), diff --git a/ansible_collections/cisco/meraki/plugins/action/organizations_devices_availabilities_change_history_info.py b/ansible_collections/cisco/meraki/plugins/action/organizations_devices_availabilities_change_history_info.py new file mode 100644 index 000000000..feee0396e --- /dev/null +++ b/ansible_collections/cisco/meraki/plugins/action/organizations_devices_availabilities_change_history_info.py @@ -0,0 +1,136 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +# Copyright (c) 2021, Cisco Systems +# 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 +from ansible.plugins.action import ActionBase +try: + from ansible_collections.ansible.utils.plugins.module_utils.common.argspec_validate import ( + AnsibleArgSpecValidator, + ) +except ImportError: + ANSIBLE_UTILS_IS_INSTALLED = False +else: + ANSIBLE_UTILS_IS_INSTALLED = True +from ansible.errors import AnsibleActionFail +from ansible_collections.cisco.meraki.plugins.plugin_utils.meraki import ( + MERAKI, + meraki_argument_spec, +) + +# Get common arguments specification +argument_spec = meraki_argument_spec() +# Add arguments specific for this module +argument_spec.update(dict( + organizationId=dict(type="str"), + perPage=dict(type="int"), + total_pages=dict(type="int"), + direction=dict(type="str"), + startingAfter=dict(type="str"), + endingBefore=dict(type="str"), + t0=dict(type="str"), + t1=dict(type="str"), + timespan=dict(type="float"), + serials=dict(type="list"), + productTypes=dict(type="list"), + networkIds=dict(type="list"), + statuses=dict(type="list"), +)) + +required_if = [] +required_one_of = [] +mutually_exclusive = [] +required_together = [] + + +class ActionModule(ActionBase): + def __init__(self, *args, **kwargs): + if not ANSIBLE_UTILS_IS_INSTALLED: + raise AnsibleActionFail( + "ansible.utils is not installed. Execute 'ansible-galaxy collection install ansible.utils'") + super(ActionModule, self).__init__(*args, **kwargs) + self._supports_async = False + self._supports_check_mode = True + self._result = None + + # Checks the supplied parameters against the argument spec for this module + def _check_argspec(self): + aav = AnsibleArgSpecValidator( + data=self._task.args, + schema=dict(argument_spec=argument_spec), + schema_format="argspec", + schema_conditionals=dict( + required_if=required_if, + required_one_of=required_one_of, + mutually_exclusive=mutually_exclusive, + required_together=required_together, + ), + name=self._task.action, + ) + valid, errors, self._task.args = aav.validate() + if not valid: + raise AnsibleActionFail(errors) + + def get_all(self, params): + new_object = {} + if params.get("organizationId") is not None: + new_object["organizationId"] = params.get( + "organizationId") + if params.get("perPage") is not None: + new_object["perPage"] = params.get( + "perPage") + new_object['total_pages'] = params.get( + "total_pages") or 1 + new_object['direction'] = params.get( + "direction") or "next" + if params.get("startingAfter") is not None: + new_object["startingAfter"] = params.get( + "startingAfter") + if params.get("endingBefore") is not None: + new_object["endingBefore"] = params.get( + "endingBefore") + if params.get("t0") is not None: + new_object["t0"] = params.get( + "t0") + if params.get("t1") is not None: + new_object["t1"] = params.get( + "t1") + if params.get("timespan") is not None: + new_object["timespan"] = params.get( + "timespan") + if params.get("serials") is not None: + new_object["serials"] = params.get( + "serials") + if params.get("productTypes") is not None: + new_object["productTypes"] = params.get( + "productTypes") + if params.get("networkIds") is not None: + new_object["networkIds"] = params.get( + "networkIds") + if params.get("statuses") is not None: + new_object["statuses"] = params.get( + "statuses") + + return new_object + + def run(self, tmp=None, task_vars=None): + self._task.diff = False + self._result = super(ActionModule, self).run(tmp, task_vars) + self._result["changed"] = False + self._check_argspec() + + self._result.update(dict(meraki_response={})) + + meraki = MERAKI(params=self._task.args) + + response = meraki.exec_meraki( + family="organizations", + function='getOrganizationDevicesAvailabilitiesChangeHistory', + params=self.get_all(self._task.args), + ) + self._result.update(dict(meraki_response=response)) + self._result.update(meraki.exit_json()) + return self._result diff --git a/ansible_collections/cisco/meraki/plugins/action/organizations_devices_boots_history_info.py b/ansible_collections/cisco/meraki/plugins/action/organizations_devices_boots_history_info.py new file mode 100644 index 000000000..53053eb7a --- /dev/null +++ b/ansible_collections/cisco/meraki/plugins/action/organizations_devices_boots_history_info.py @@ -0,0 +1,132 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +# Copyright (c) 2021, Cisco Systems +# 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 +from ansible.plugins.action import ActionBase +try: + from ansible_collections.ansible.utils.plugins.module_utils.common.argspec_validate import ( + AnsibleArgSpecValidator, + ) +except ImportError: + ANSIBLE_UTILS_IS_INSTALLED = False +else: + ANSIBLE_UTILS_IS_INSTALLED = True +from ansible.errors import AnsibleActionFail +from ansible_collections.cisco.meraki.plugins.plugin_utils.meraki import ( + MERAKI, + meraki_argument_spec, +) + +# Get common arguments specification +argument_spec = meraki_argument_spec() +# Add arguments specific for this module +argument_spec.update(dict( + organizationId=dict(type="str"), + t0=dict(type="str"), + t1=dict(type="str"), + timespan=dict(type="float"), + serials=dict(type="list"), + mostRecentPerDevice=dict(type="bool"), + perPage=dict(type="int"), + total_pages=dict(type="int"), + direction=dict(type="str"), + startingAfter=dict(type="str"), + endingBefore=dict(type="str"), + sortOrder=dict(type="str"), +)) + +required_if = [] +required_one_of = [] +mutually_exclusive = [] +required_together = [] + + +class ActionModule(ActionBase): + def __init__(self, *args, **kwargs): + if not ANSIBLE_UTILS_IS_INSTALLED: + raise AnsibleActionFail( + "ansible.utils is not installed. Execute 'ansible-galaxy collection install ansible.utils'") + super(ActionModule, self).__init__(*args, **kwargs) + self._supports_async = False + self._supports_check_mode = True + self._result = None + + # Checks the supplied parameters against the argument spec for this module + def _check_argspec(self): + aav = AnsibleArgSpecValidator( + data=self._task.args, + schema=dict(argument_spec=argument_spec), + schema_format="argspec", + schema_conditionals=dict( + required_if=required_if, + required_one_of=required_one_of, + mutually_exclusive=mutually_exclusive, + required_together=required_together, + ), + name=self._task.action, + ) + valid, errors, self._task.args = aav.validate() + if not valid: + raise AnsibleActionFail(errors) + + def get_all(self, params): + new_object = {} + if params.get("organizationId") is not None: + new_object["organizationId"] = params.get( + "organizationId") + if params.get("t0") is not None: + new_object["t0"] = params.get( + "t0") + if params.get("t1") is not None: + new_object["t1"] = params.get( + "t1") + if params.get("timespan") is not None: + new_object["timespan"] = params.get( + "timespan") + if params.get("serials") is not None: + new_object["serials"] = params.get( + "serials") + if params.get("mostRecentPerDevice") is not None: + new_object["mostRecentPerDevice"] = params.get( + "mostRecentPerDevice") + if params.get("perPage") is not None: + new_object["perPage"] = params.get( + "perPage") + new_object['total_pages'] = params.get( + "total_pages") or 1 + new_object['direction'] = params.get( + "direction") or "next" + if params.get("startingAfter") is not None: + new_object["startingAfter"] = params.get( + "startingAfter") + if params.get("endingBefore") is not None: + new_object["endingBefore"] = params.get( + "endingBefore") + if params.get("sortOrder") is not None: + new_object["sortOrder"] = params.get( + "sortOrder") + + return new_object + + def run(self, tmp=None, task_vars=None): + self._task.diff = False + self._result = super(ActionModule, self).run(tmp, task_vars) + self._result["changed"] = False + self._check_argspec() + + self._result.update(dict(meraki_response={})) + + meraki = MERAKI(params=self._task.args) + + response = meraki.exec_meraki( + family="organizations", + function='getOrganizationDevicesBootsHistory', + params=self.get_all(self._task.args), + ) + self._result.update(dict(meraki_response=response)) + self._result.update(meraki.exit_json()) + return self._result diff --git a/ansible_collections/cisco/meraki/plugins/action/organizations_early_access_features_opt_ins.py b/ansible_collections/cisco/meraki/plugins/action/organizations_early_access_features_opt_ins.py index 7a952168f..b0ebdf793 100644 --- a/ansible_collections/cisco/meraki/plugins/action/organizations_early_access_features_opt_ins.py +++ b/ansible_collections/cisco/meraki/plugins/action/organizations_early_access_features_opt_ins.py @@ -32,8 +32,8 @@ argument_spec = meraki_argument_spec() # Add arguments specific for this module argument_spec.update(dict( state=dict(type="str", default="present", choices=["present", "absent"]), - shortName=dict(type="str"), limitScopeToNetworks=dict(type="list"), + shortName=dict(type="str"), organizationId=dict(type="str"), optInId=dict(type="str"), )) @@ -51,8 +51,8 @@ class OrganizationsEarlyAccessFeaturesOptIns(object): def __init__(self, params, meraki): self.meraki = meraki self.new_object = dict( - shortName=params.get("shortName"), limitScopeToNetworks=params.get("limitScopeToNetworks"), + shortName=params.get("shortName"), organizationId=params.get("organizationId"), optInId=params.get("optInId"), ) @@ -76,12 +76,12 @@ class OrganizationsEarlyAccessFeaturesOptIns(object): def create_params(self): new_object_params = {} - if self.new_object.get('shortName') is not None or self.new_object.get('short_name') is not None: - new_object_params['shortName'] = self.new_object.get('shortName') or \ - self.new_object.get('short_name') if self.new_object.get('limitScopeToNetworks') is not None or self.new_object.get('limit_scope_to_networks') is not None: new_object_params['limitScopeToNetworks'] = self.new_object.get('limitScopeToNetworks') or \ self.new_object.get('limit_scope_to_networks') + if self.new_object.get('shortName') is not None or self.new_object.get('short_name') is not None: + new_object_params['shortName'] = self.new_object.get('shortName') or \ + self.new_object.get('short_name') if self.new_object.get('organizationId') is not None or self.new_object.get('organization_id') is not None: new_object_params['organizationId'] = self.new_object.get('organizationId') or \ self.new_object.get('organization_id') @@ -179,8 +179,8 @@ class OrganizationsEarlyAccessFeaturesOptIns(object): requested_obj = self.new_object obj_params = [ - ("shortName", "shortName"), ("limitScopeToNetworks", "limitScopeToNetworks"), + ("shortName", "shortName"), ("organizationId", "organizationId"), ("optInId", "optInId"), ] diff --git a/ansible_collections/cisco/meraki/plugins/action/organizations_firmware_upgrades_by_device_info.py b/ansible_collections/cisco/meraki/plugins/action/organizations_firmware_upgrades_by_device_info.py index 254770a93..942ee2ecb 100644 --- a/ansible_collections/cisco/meraki/plugins/action/organizations_firmware_upgrades_by_device_info.py +++ b/ansible_collections/cisco/meraki/plugins/action/organizations_firmware_upgrades_by_device_info.py @@ -34,8 +34,8 @@ argument_spec.update(dict( networkIds=dict(type="list"), serials=dict(type="list"), macs=dict(type="list"), - firmwareUpgradeIds=dict(type="list"), firmwareUpgradeBatchIds=dict(type="list"), + upgradeStatuses=dict(type="list"), )) required_if = [] @@ -99,12 +99,12 @@ class ActionModule(ActionBase): if params.get("macs") is not None: new_object["macs"] = params.get( "macs") - if params.get("firmwareUpgradeIds") is not None: - new_object["firmwareUpgradeIds"] = params.get( - "firmwareUpgradeIds") if params.get("firmwareUpgradeBatchIds") is not None: new_object["firmwareUpgradeBatchIds"] = params.get( "firmwareUpgradeBatchIds") + if params.get("upgradeStatuses") is not None: + new_object["upgradeStatuses"] = params.get( + "upgradeStatuses") return new_object diff --git a/ansible_collections/cisco/meraki/plugins/action/organizations_firmware_upgrades_info.py b/ansible_collections/cisco/meraki/plugins/action/organizations_firmware_upgrades_info.py index e8e72f6ce..afe4584e9 100644 --- a/ansible_collections/cisco/meraki/plugins/action/organizations_firmware_upgrades_info.py +++ b/ansible_collections/cisco/meraki/plugins/action/organizations_firmware_upgrades_info.py @@ -26,8 +26,13 @@ argument_spec = meraki_argument_spec() # Add arguments specific for this module argument_spec.update(dict( organizationId=dict(type="str"), + perPage=dict(type="int"), + total_pages=dict(type="int"), + direction=dict(type="str"), + startingAfter=dict(type="str"), + endingBefore=dict(type="str"), status=dict(type="list"), - productType=dict(type="list"), + productTypes=dict(type="list"), )) required_if = [] @@ -69,12 +74,25 @@ class ActionModule(ActionBase): if params.get("organizationId") is not None: new_object["organizationId"] = params.get( "organizationId") + if params.get("perPage") is not None: + new_object["perPage"] = params.get( + "perPage") + new_object['total_pages'] = params.get( + "total_pages") or 1 + new_object['direction'] = params.get( + "direction") or "next" + if params.get("startingAfter") is not None: + new_object["startingAfter"] = params.get( + "startingAfter") + if params.get("endingBefore") is not None: + new_object["endingBefore"] = params.get( + "endingBefore") if params.get("status") is not None: new_object["status"] = params.get( "status") - if params.get("productType") is not None: - new_object["productType"] = params.get( - "productType") + if params.get("productTypes") is not None: + new_object["productTypes"] = params.get( + "productTypes") return new_object diff --git a/ansible_collections/cisco/meraki/plugins/action/organizations_info.py b/ansible_collections/cisco/meraki/plugins/action/organizations_info.py index e7dba48d4..3a48d1c4b 100644 --- a/ansible_collections/cisco/meraki/plugins/action/organizations_info.py +++ b/ansible_collections/cisco/meraki/plugins/action/organizations_info.py @@ -25,6 +25,11 @@ from ansible_collections.cisco.meraki.plugins.plugin_utils.meraki import ( argument_spec = meraki_argument_spec() # Add arguments specific for this module argument_spec.update(dict( + perPage=dict(type="int"), + total_pages=dict(type="int"), + direction=dict(type="str"), + startingAfter=dict(type="str"), + endingBefore=dict(type="str"), organizationId=dict(type="str"), )) @@ -71,6 +76,19 @@ class ActionModule(ActionBase): def get_all(self, params): new_object = {} + if params.get("perPage") is not None: + new_object["perPage"] = params.get( + "perPage") + new_object['total_pages'] = params.get( + "total_pages") or 1 + new_object['direction'] = params.get( + "direction") or "next" + if params.get("startingAfter") is not None: + new_object["startingAfter"] = params.get( + "startingAfter") + if params.get("endingBefore") is not None: + new_object["endingBefore"] = params.get( + "endingBefore") return new_object diff --git a/ansible_collections/cisco/meraki/plugins/action/organizations_insight_monitored_media_servers.py b/ansible_collections/cisco/meraki/plugins/action/organizations_insight_monitored_media_servers.py index 14957d943..dbead6d01 100644 --- a/ansible_collections/cisco/meraki/plugins/action/organizations_insight_monitored_media_servers.py +++ b/ansible_collections/cisco/meraki/plugins/action/organizations_insight_monitored_media_servers.py @@ -32,9 +32,9 @@ argument_spec = meraki_argument_spec() # Add arguments specific for this module argument_spec.update(dict( state=dict(type="str", default="present", choices=["present", "absent"]), - name=dict(type="str"), address=dict(type="str"), bestEffortMonitoringEnabled=dict(type="bool"), + name=dict(type="str"), organizationId=dict(type="str"), monitoredMediaServerId=dict(type="str"), )) @@ -52,9 +52,9 @@ class OrganizationsInsightMonitoredMediaServers(object): def __init__(self, params, meraki): self.meraki = meraki self.new_object = dict( - name=params.get("name"), address=params.get("address"), bestEffortMonitoringEnabled=params.get("bestEffortMonitoringEnabled"), + name=params.get("name"), organizationId=params.get("organizationId"), monitoredMediaServerId=params.get("monitoredMediaServerId"), ) @@ -78,14 +78,14 @@ class OrganizationsInsightMonitoredMediaServers(object): def create_params(self): new_object_params = {} - if self.new_object.get('name') is not None or self.new_object.get('name') is not None: - new_object_params['name'] = self.new_object.get('name') or \ - self.new_object.get('name') if self.new_object.get('address') is not None or self.new_object.get('address') is not None: new_object_params['address'] = self.new_object.get('address') or \ self.new_object.get('address') if self.new_object.get('bestEffortMonitoringEnabled') is not None or self.new_object.get('best_effort_monitoring_enabled') is not None: new_object_params['bestEffortMonitoringEnabled'] = self.new_object.get('bestEffortMonitoringEnabled') + if self.new_object.get('name') is not None or self.new_object.get('name') is not None: + new_object_params['name'] = self.new_object.get('name') or \ + self.new_object.get('name') if self.new_object.get('organizationId') is not None or self.new_object.get('organization_id') is not None: new_object_params['organizationId'] = self.new_object.get('organizationId') or \ self.new_object.get('organization_id') @@ -103,14 +103,14 @@ class OrganizationsInsightMonitoredMediaServers(object): def update_by_id_params(self): new_object_params = {} - if self.new_object.get('name') is not None or self.new_object.get('name') is not None: - new_object_params['name'] = self.new_object.get('name') or \ - self.new_object.get('name') if self.new_object.get('address') is not None or self.new_object.get('address') is not None: new_object_params['address'] = self.new_object.get('address') or \ self.new_object.get('address') if self.new_object.get('bestEffortMonitoringEnabled') is not None or self.new_object.get('best_effort_monitoring_enabled') is not None: new_object_params['bestEffortMonitoringEnabled'] = self.new_object.get('bestEffortMonitoringEnabled') + if self.new_object.get('name') is not None or self.new_object.get('name') is not None: + new_object_params['name'] = self.new_object.get('name') or \ + self.new_object.get('name') if self.new_object.get('organizationId') is not None or self.new_object.get('organization_id') is not None: new_object_params['organizationId'] = self.new_object.get('organizationId') or \ self.new_object.get('organization_id') @@ -188,9 +188,9 @@ class OrganizationsInsightMonitoredMediaServers(object): requested_obj = self.new_object obj_params = [ - ("name", "name"), ("address", "address"), ("bestEffortMonitoringEnabled", "bestEffortMonitoringEnabled"), + ("name", "name"), ("organizationId", "organizationId"), ("monitoredMediaServerId", "monitoredMediaServerId"), ] diff --git a/ansible_collections/cisco/meraki/plugins/action/organizations_inventory_claim.py b/ansible_collections/cisco/meraki/plugins/action/organizations_inventory_claim.py index 5bc648b91..e25a3d67b 100644 --- a/ansible_collections/cisco/meraki/plugins/action/organizations_inventory_claim.py +++ b/ansible_collections/cisco/meraki/plugins/action/organizations_inventory_claim.py @@ -25,9 +25,9 @@ from ansible_collections.cisco.meraki.plugins.plugin_utils.meraki import ( argument_spec = meraki_argument_spec() # Add arguments specific for this module argument_spec.update(dict( + licenses=dict(type="list"), orders=dict(type="list"), serials=dict(type="list"), - licenses=dict(type="list"), organizationId=dict(type="str"), )) @@ -67,9 +67,9 @@ class ActionModule(ActionBase): def get_object(self, params): new_object = dict( + licenses=params.get("licenses"), orders=params.get("orders"), serials=params.get("serials"), - licenses=params.get("licenses"), organizationId=params.get("organizationId"), ) return new_object diff --git a/ansible_collections/cisco/meraki/plugins/action/organizations_inventory_onboarding_cloud_monitoring_export_events.py b/ansible_collections/cisco/meraki/plugins/action/organizations_inventory_onboarding_cloud_monitoring_export_events.py index 11cefb220..6a03ab49f 100644 --- a/ansible_collections/cisco/meraki/plugins/action/organizations_inventory_onboarding_cloud_monitoring_export_events.py +++ b/ansible_collections/cisco/meraki/plugins/action/organizations_inventory_onboarding_cloud_monitoring_export_events.py @@ -26,9 +26,9 @@ argument_spec = meraki_argument_spec() # Add arguments specific for this module argument_spec.update(dict( logEvent=dict(type="str"), - timestamp=dict(type="int"), - targetOS=dict(type="str"), request=dict(type="str"), + targetOS=dict(type="str"), + timestamp=dict(type="int"), organizationId=dict(type="str"), )) @@ -69,9 +69,9 @@ class ActionModule(ActionBase): def get_object(self, params): new_object = dict( logEvent=params.get("logEvent"), - timestamp=params.get("timestamp"), - targetOS=params.get("targetOS"), request=params.get("request"), + targetOS=params.get("targetOS"), + timestamp=params.get("timestamp"), organizationId=params.get("organizationId"), ) return new_object diff --git a/ansible_collections/cisco/meraki/plugins/action/organizations_inventory_onboarding_cloud_monitoring_networks_info.py b/ansible_collections/cisco/meraki/plugins/action/organizations_inventory_onboarding_cloud_monitoring_networks_info.py index 409b7abdb..bf953f272 100644 --- a/ansible_collections/cisco/meraki/plugins/action/organizations_inventory_onboarding_cloud_monitoring_networks_info.py +++ b/ansible_collections/cisco/meraki/plugins/action/organizations_inventory_onboarding_cloud_monitoring_networks_info.py @@ -27,6 +27,7 @@ argument_spec = meraki_argument_spec() argument_spec.update(dict( organizationId=dict(type="str"), deviceType=dict(type="str"), + search=dict(type="str"), perPage=dict(type="int"), total_pages=dict(type="int"), direction=dict(type="str"), @@ -76,6 +77,9 @@ class ActionModule(ActionBase): if params.get("deviceType") is not None: new_object["deviceType"] = params.get( "deviceType") + if params.get("search") is not None: + new_object["search"] = params.get( + "search") if params.get("perPage") is not None: new_object["perPage"] = params.get( "perPage") diff --git a/ansible_collections/cisco/meraki/plugins/action/organizations_login_security.py b/ansible_collections/cisco/meraki/plugins/action/organizations_login_security.py index 64f5ea7b4..d231966d9 100644 --- a/ansible_collections/cisco/meraki/plugins/action/organizations_login_security.py +++ b/ansible_collections/cisco/meraki/plugins/action/organizations_login_security.py @@ -32,19 +32,19 @@ argument_spec = meraki_argument_spec() # Add arguments specific for this module argument_spec.update(dict( state=dict(type="str", default="present", choices=["present"]), - enforcePasswordExpiration=dict(type="bool"), - passwordExpirationDays=dict(type="int"), - enforceDifferentPasswords=dict(type="bool"), - numDifferentPasswords=dict(type="int"), - enforceStrongPasswords=dict(type="bool"), - enforceAccountLockout=dict(type="bool"), accountLockoutAttempts=dict(type="int"), + apiAuthentication=dict(type="dict"), + enforceAccountLockout=dict(type="bool"), + enforceDifferentPasswords=dict(type="bool"), enforceIdleTimeout=dict(type="bool"), - idleTimeoutMinutes=dict(type="int"), - enforceTwoFactorAuth=dict(type="bool"), enforceLoginIpRanges=dict(type="bool"), + enforcePasswordExpiration=dict(type="bool"), + enforceStrongPasswords=dict(type="bool"), + enforceTwoFactorAuth=dict(type="bool"), + idleTimeoutMinutes=dict(type="int"), loginIpRanges=dict(type="list"), - apiAuthentication=dict(type="dict"), + numDifferentPasswords=dict(type="int"), + passwordExpirationDays=dict(type="int"), organizationId=dict(type="str"), )) @@ -60,19 +60,19 @@ class OrganizationsLoginSecurity(object): def __init__(self, params, meraki): self.meraki = meraki self.new_object = dict( - enforcePasswordExpiration=params.get("enforcePasswordExpiration"), - passwordExpirationDays=params.get("passwordExpirationDays"), - enforceDifferentPasswords=params.get("enforceDifferentPasswords"), - numDifferentPasswords=params.get("numDifferentPasswords"), - enforceStrongPasswords=params.get("enforceStrongPasswords"), - enforceAccountLockout=params.get("enforceAccountLockout"), accountLockoutAttempts=params.get("accountLockoutAttempts"), + apiAuthentication=params.get("apiAuthentication"), + enforceAccountLockout=params.get("enforceAccountLockout"), + enforceDifferentPasswords=params.get("enforceDifferentPasswords"), enforceIdleTimeout=params.get("enforceIdleTimeout"), - idleTimeoutMinutes=params.get("idleTimeoutMinutes"), - enforceTwoFactorAuth=params.get("enforceTwoFactorAuth"), enforceLoginIpRanges=params.get("enforceLoginIpRanges"), + enforcePasswordExpiration=params.get("enforcePasswordExpiration"), + enforceStrongPasswords=params.get("enforceStrongPasswords"), + enforceTwoFactorAuth=params.get("enforceTwoFactorAuth"), + idleTimeoutMinutes=params.get("idleTimeoutMinutes"), loginIpRanges=params.get("loginIpRanges"), - apiAuthentication=params.get("apiAuthentication"), + numDifferentPasswords=params.get("numDifferentPasswords"), + passwordExpirationDays=params.get("passwordExpirationDays"), organization_id=params.get("organizationId"), ) @@ -85,38 +85,38 @@ class OrganizationsLoginSecurity(object): def update_all_params(self): new_object_params = {} - if self.new_object.get('enforcePasswordExpiration') is not None or self.new_object.get('enforce_password_expiration') is not None: - new_object_params['enforcePasswordExpiration'] = self.new_object.get('enforcePasswordExpiration') - if self.new_object.get('passwordExpirationDays') is not None or self.new_object.get('password_expiration_days') is not None: - new_object_params['passwordExpirationDays'] = self.new_object.get('passwordExpirationDays') or \ - self.new_object.get('password_expiration_days') - if self.new_object.get('enforceDifferentPasswords') is not None or self.new_object.get('enforce_different_passwords') is not None: - new_object_params['enforceDifferentPasswords'] = self.new_object.get('enforceDifferentPasswords') - if self.new_object.get('numDifferentPasswords') is not None or self.new_object.get('num_different_passwords') is not None: - new_object_params['numDifferentPasswords'] = self.new_object.get('numDifferentPasswords') or \ - self.new_object.get('num_different_passwords') - if self.new_object.get('enforceStrongPasswords') is not None or self.new_object.get('enforce_strong_passwords') is not None: - new_object_params['enforceStrongPasswords'] = self.new_object.get('enforceStrongPasswords') - if self.new_object.get('enforceAccountLockout') is not None or self.new_object.get('enforce_account_lockout') is not None: - new_object_params['enforceAccountLockout'] = self.new_object.get('enforceAccountLockout') if self.new_object.get('accountLockoutAttempts') is not None or self.new_object.get('account_lockout_attempts') is not None: new_object_params['accountLockoutAttempts'] = self.new_object.get('accountLockoutAttempts') or \ self.new_object.get('account_lockout_attempts') + if self.new_object.get('apiAuthentication') is not None or self.new_object.get('api_authentication') is not None: + new_object_params['apiAuthentication'] = self.new_object.get('apiAuthentication') or \ + self.new_object.get('api_authentication') + if self.new_object.get('enforceAccountLockout') is not None or self.new_object.get('enforce_account_lockout') is not None: + new_object_params['enforceAccountLockout'] = self.new_object.get('enforceAccountLockout') + if self.new_object.get('enforceDifferentPasswords') is not None or self.new_object.get('enforce_different_passwords') is not None: + new_object_params['enforceDifferentPasswords'] = self.new_object.get('enforceDifferentPasswords') if self.new_object.get('enforceIdleTimeout') is not None or self.new_object.get('enforce_idle_timeout') is not None: new_object_params['enforceIdleTimeout'] = self.new_object.get('enforceIdleTimeout') + if self.new_object.get('enforceLoginIpRanges') is not None or self.new_object.get('enforce_login_ip_ranges') is not None: + new_object_params['enforceLoginIpRanges'] = self.new_object.get('enforceLoginIpRanges') + if self.new_object.get('enforcePasswordExpiration') is not None or self.new_object.get('enforce_password_expiration') is not None: + new_object_params['enforcePasswordExpiration'] = self.new_object.get('enforcePasswordExpiration') + if self.new_object.get('enforceStrongPasswords') is not None or self.new_object.get('enforce_strong_passwords') is not None: + new_object_params['enforceStrongPasswords'] = self.new_object.get('enforceStrongPasswords') + if self.new_object.get('enforceTwoFactorAuth') is not None or self.new_object.get('enforce_two_factor_auth') is not None: + new_object_params['enforceTwoFactorAuth'] = self.new_object.get('enforceTwoFactorAuth') if self.new_object.get('idleTimeoutMinutes') is not None or self.new_object.get('idle_timeout_minutes') is not None: new_object_params['idleTimeoutMinutes'] = self.new_object.get('idleTimeoutMinutes') or \ self.new_object.get('idle_timeout_minutes') - if self.new_object.get('enforceTwoFactorAuth') is not None or self.new_object.get('enforce_two_factor_auth') is not None: - new_object_params['enforceTwoFactorAuth'] = self.new_object.get('enforceTwoFactorAuth') - if self.new_object.get('enforceLoginIpRanges') is not None or self.new_object.get('enforce_login_ip_ranges') is not None: - new_object_params['enforceLoginIpRanges'] = self.new_object.get('enforceLoginIpRanges') if self.new_object.get('loginIpRanges') is not None or self.new_object.get('login_ip_ranges') is not None: new_object_params['loginIpRanges'] = self.new_object.get('loginIpRanges') or \ self.new_object.get('login_ip_ranges') - if self.new_object.get('apiAuthentication') is not None or self.new_object.get('api_authentication') is not None: - new_object_params['apiAuthentication'] = self.new_object.get('apiAuthentication') or \ - self.new_object.get('api_authentication') + if self.new_object.get('numDifferentPasswords') is not None or self.new_object.get('num_different_passwords') is not None: + new_object_params['numDifferentPasswords'] = self.new_object.get('numDifferentPasswords') or \ + self.new_object.get('num_different_passwords') + if self.new_object.get('passwordExpirationDays') is not None or self.new_object.get('password_expiration_days') is not None: + new_object_params['passwordExpirationDays'] = self.new_object.get('passwordExpirationDays') or \ + self.new_object.get('password_expiration_days') if self.new_object.get('organizationId') is not None or self.new_object.get('organization_id') is not None: new_object_params['organizationId'] = self.new_object.get('organizationId') or \ self.new_object.get('organization_id') @@ -152,7 +152,7 @@ class OrganizationsLoginSecurity(object): id_exists = False name_exists = False o_id = self.new_object.get("id") - name = self.new_object.get("organization_id") + name = self.new_object.get("name") if o_id: prev_obj = self.get_object_by_name(o_id) id_exists = prev_obj is not None and isinstance(prev_obj, dict) @@ -173,18 +173,18 @@ class OrganizationsLoginSecurity(object): requested_obj = self.new_object obj_params = [ - ("enforcePasswordExpiration", "enforcePasswordExpiration"), - ("enforceDifferentPasswords", "enforceDifferentPasswords"), - ("numDifferentPasswords", "numDifferentPasswords"), - ("enforceStrongPasswords", "enforceStrongPasswords"), - ("enforceAccountLockout", "enforceAccountLockout"), ("accountLockoutAttempts", "accountLockoutAttempts"), + ("apiAuthentication", "apiAuthentication"), + ("enforceAccountLockout", "enforceAccountLockout"), + ("enforceDifferentPasswords", "enforceDifferentPasswords"), ("enforceIdleTimeout", "enforceIdleTimeout"), - ("idleTimeoutMinutes", "idleTimeoutMinutes"), - ("enforceTwoFactorAuth", "enforceTwoFactorAuth"), ("enforceLoginIpRanges", "enforceLoginIpRanges"), + ("enforcePasswordExpiration", "enforcePasswordExpiration"), + ("enforceStrongPasswords", "enforceStrongPasswords"), + ("enforceTwoFactorAuth", "enforceTwoFactorAuth"), + ("idleTimeoutMinutes", "idleTimeoutMinutes"), ("loginIpRanges", "loginIpRanges"), - ("apiAuthentication", "apiAuthentication"), + ("numDifferentPasswords", "numDifferentPasswords"), ("organizationId", "organizationId"), ] # Method 1. Params present in request (Ansible) obj are the same as the current (ISE) params diff --git a/ansible_collections/cisco/meraki/plugins/action/organizations_networks_combine.py b/ansible_collections/cisco/meraki/plugins/action/organizations_networks_combine.py index c6d337d78..395cd6597 100644 --- a/ansible_collections/cisco/meraki/plugins/action/organizations_networks_combine.py +++ b/ansible_collections/cisco/meraki/plugins/action/organizations_networks_combine.py @@ -25,9 +25,9 @@ from ansible_collections.cisco.meraki.plugins.plugin_utils.meraki import ( argument_spec = meraki_argument_spec() # Add arguments specific for this module argument_spec.update(dict( + enrollmentString=dict(type="str"), name=dict(type="str"), networkIds=dict(type="list"), - enrollmentString=dict(type="str"), organizationId=dict(type="str"), )) @@ -67,9 +67,9 @@ class ActionModule(ActionBase): def get_object(self, params): new_object = dict( + enrollmentString=params.get("enrollmentString"), name=params.get("name"), networkIds=params.get("networkIds"), - enrollmentString=params.get("enrollmentString"), organizationId=params.get("organizationId"), ) return new_object diff --git a/ansible_collections/cisco/meraki/plugins/action/organizations_openapi_spec_info.py b/ansible_collections/cisco/meraki/plugins/action/organizations_openapi_spec_info.py index 6ad1215dc..2d6bb35ed 100644 --- a/ansible_collections/cisco/meraki/plugins/action/organizations_openapi_spec_info.py +++ b/ansible_collections/cisco/meraki/plugins/action/organizations_openapi_spec_info.py @@ -26,6 +26,7 @@ argument_spec = meraki_argument_spec() # Add arguments specific for this module argument_spec.update(dict( organizationId=dict(type="str"), + version=dict(type="int"), )) required_if = [] @@ -67,6 +68,9 @@ class ActionModule(ActionBase): if params.get("organizationId") is not None: new_object["organizationId"] = params.get( "organizationId") + if params.get("version") is not None: + new_object["version"] = params.get( + "version") return new_object diff --git a/ansible_collections/cisco/meraki/plugins/action/organizations_policy_objects.py b/ansible_collections/cisco/meraki/plugins/action/organizations_policy_objects.py index 6e49366b2..e412ec4d4 100644 --- a/ansible_collections/cisco/meraki/plugins/action/organizations_policy_objects.py +++ b/ansible_collections/cisco/meraki/plugins/action/organizations_policy_objects.py @@ -32,14 +32,14 @@ argument_spec = meraki_argument_spec() # Add arguments specific for this module argument_spec.update(dict( state=dict(type="str", default="present", choices=["present", "absent"]), - name=dict(type="str"), category=dict(type="str"), - type=dict(type="str"), cidr=dict(type="str"), fqdn=dict(type="str"), - mask=dict(type="str"), - ip=dict(type="str"), groupIds=dict(type="list"), + ip=dict(type="str"), + mask=dict(type="str"), + name=dict(type="str"), + type=dict(type="str"), organizationId=dict(type="str"), policyObjectId=dict(type="str"), )) @@ -57,14 +57,14 @@ class OrganizationsPolicyObjects(object): def __init__(self, params, meraki): self.meraki = meraki self.new_object = dict( - name=params.get("name"), category=params.get("category"), - type=params.get("type"), cidr=params.get("cidr"), fqdn=params.get("fqdn"), - mask=params.get("mask"), - ip=params.get("ip"), groupIds=params.get("groupIds"), + ip=params.get("ip"), + mask=params.get("mask"), + name=params.get("name"), + type=params.get("type"), organizationId=params.get("organizationId"), policyObjectId=params.get("policyObjectId"), ) @@ -98,30 +98,30 @@ class OrganizationsPolicyObjects(object): def create_params(self): new_object_params = {} - if self.new_object.get('name') is not None or self.new_object.get('name') is not None: - new_object_params['name'] = self.new_object.get('name') or \ - self.new_object.get('name') if self.new_object.get('category') is not None or self.new_object.get('category') is not None: new_object_params['category'] = self.new_object.get('category') or \ self.new_object.get('category') - if self.new_object.get('type') is not None or self.new_object.get('type') is not None: - new_object_params['type'] = self.new_object.get('type') or \ - self.new_object.get('type') if self.new_object.get('cidr') is not None or self.new_object.get('cidr') is not None: new_object_params['cidr'] = self.new_object.get('cidr') or \ self.new_object.get('cidr') if self.new_object.get('fqdn') is not None or self.new_object.get('fqdn') is not None: new_object_params['fqdn'] = self.new_object.get('fqdn') or \ self.new_object.get('fqdn') - if self.new_object.get('mask') is not None or self.new_object.get('mask') is not None: - new_object_params['mask'] = self.new_object.get('mask') or \ - self.new_object.get('mask') - if self.new_object.get('ip') is not None or self.new_object.get('ip') is not None: - new_object_params['ip'] = self.new_object.get('ip') or \ - self.new_object.get('ip') if self.new_object.get('groupIds') is not None or self.new_object.get('group_ids') is not None: new_object_params['groupIds'] = self.new_object.get('groupIds') or \ self.new_object.get('group_ids') + if self.new_object.get('ip') is not None or self.new_object.get('ip') is not None: + new_object_params['ip'] = self.new_object.get('ip') or \ + self.new_object.get('ip') + if self.new_object.get('mask') is not None or self.new_object.get('mask') is not None: + new_object_params['mask'] = self.new_object.get('mask') or \ + self.new_object.get('mask') + if self.new_object.get('name') is not None or self.new_object.get('name') is not None: + new_object_params['name'] = self.new_object.get('name') or \ + self.new_object.get('name') + if self.new_object.get('type') is not None or self.new_object.get('type') is not None: + new_object_params['type'] = self.new_object.get('type') or \ + self.new_object.get('type') if self.new_object.get('organizationId') is not None or self.new_object.get('organization_id') is not None: new_object_params['organizationId'] = self.new_object.get('organizationId') or \ self.new_object.get('organization_id') @@ -139,24 +139,24 @@ class OrganizationsPolicyObjects(object): def update_by_id_params(self): new_object_params = {} - if self.new_object.get('name') is not None or self.new_object.get('name') is not None: - new_object_params['name'] = self.new_object.get('name') or \ - self.new_object.get('name') if self.new_object.get('cidr') is not None or self.new_object.get('cidr') is not None: new_object_params['cidr'] = self.new_object.get('cidr') or \ self.new_object.get('cidr') if self.new_object.get('fqdn') is not None or self.new_object.get('fqdn') is not None: new_object_params['fqdn'] = self.new_object.get('fqdn') or \ self.new_object.get('fqdn') - if self.new_object.get('mask') is not None or self.new_object.get('mask') is not None: - new_object_params['mask'] = self.new_object.get('mask') or \ - self.new_object.get('mask') - if self.new_object.get('ip') is not None or self.new_object.get('ip') is not None: - new_object_params['ip'] = self.new_object.get('ip') or \ - self.new_object.get('ip') if self.new_object.get('groupIds') is not None or self.new_object.get('group_ids') is not None: new_object_params['groupIds'] = self.new_object.get('groupIds') or \ self.new_object.get('group_ids') + if self.new_object.get('ip') is not None or self.new_object.get('ip') is not None: + new_object_params['ip'] = self.new_object.get('ip') or \ + self.new_object.get('ip') + if self.new_object.get('mask') is not None or self.new_object.get('mask') is not None: + new_object_params['mask'] = self.new_object.get('mask') or \ + self.new_object.get('mask') + if self.new_object.get('name') is not None or self.new_object.get('name') is not None: + new_object_params['name'] = self.new_object.get('name') or \ + self.new_object.get('name') if self.new_object.get('organizationId') is not None or self.new_object.get('organization_id') is not None: new_object_params['organizationId'] = self.new_object.get('organizationId') or \ self.new_object.get('organization_id') @@ -234,14 +234,14 @@ class OrganizationsPolicyObjects(object): requested_obj = self.new_object obj_params = [ - ("name", "name"), ("category", "category"), - ("type", "type"), ("cidr", "cidr"), ("fqdn", "fqdn"), - ("mask", "mask"), - ("ip", "ip"), ("groupIds", "groupIds"), + ("ip", "ip"), + ("mask", "mask"), + ("name", "name"), + ("type", "type"), ("organizationId", "organizationId"), ("policyObjectId", "policyObjectId"), ] diff --git a/ansible_collections/cisco/meraki/plugins/action/organizations_policy_objects_groups.py b/ansible_collections/cisco/meraki/plugins/action/organizations_policy_objects_groups.py index ff6b3f852..7de772a5e 100644 --- a/ansible_collections/cisco/meraki/plugins/action/organizations_policy_objects_groups.py +++ b/ansible_collections/cisco/meraki/plugins/action/organizations_policy_objects_groups.py @@ -32,8 +32,8 @@ argument_spec = meraki_argument_spec() # Add arguments specific for this module argument_spec.update(dict( state=dict(type="str", default="present", choices=["present", "absent"]), - name=dict(type="str"), category=dict(type="str"), + name=dict(type="str"), objectIds=dict(type="list"), organizationId=dict(type="str"), policyObjectGroupId=dict(type="str"), @@ -52,8 +52,8 @@ class OrganizationsPolicyObjectsGroups(object): def __init__(self, params, meraki): self.meraki = meraki self.new_object = dict( - name=params.get("name"), category=params.get("category"), + name=params.get("name"), objectIds=params.get("objectIds"), organizationId=params.get("organizationId"), policyObjectGroupId=params.get("policyObjectGroupId"), @@ -88,12 +88,12 @@ class OrganizationsPolicyObjectsGroups(object): def create_params(self): new_object_params = {} - if self.new_object.get('name') is not None or self.new_object.get('name') is not None: - new_object_params['name'] = self.new_object.get('name') or \ - self.new_object.get('name') if self.new_object.get('category') is not None or self.new_object.get('category') is not None: new_object_params['category'] = self.new_object.get('category') or \ self.new_object.get('category') + if self.new_object.get('name') is not None or self.new_object.get('name') is not None: + new_object_params['name'] = self.new_object.get('name') or \ + self.new_object.get('name') if self.new_object.get('objectIds') is not None or self.new_object.get('object_ids') is not None: new_object_params['objectIds'] = self.new_object.get('objectIds') or \ self.new_object.get('object_ids') @@ -197,8 +197,8 @@ class OrganizationsPolicyObjectsGroups(object): requested_obj = self.new_object obj_params = [ - ("name", "name"), ("category", "category"), + ("name", "name"), ("objectIds", "objectIds"), ("organizationId", "organizationId"), ("policyObjectGroupId", "policyObjectGroupId"), diff --git a/ansible_collections/cisco/meraki/plugins/action/organizations_saml_idps.py b/ansible_collections/cisco/meraki/plugins/action/organizations_saml_idps.py index e557665b9..196750ebf 100644 --- a/ansible_collections/cisco/meraki/plugins/action/organizations_saml_idps.py +++ b/ansible_collections/cisco/meraki/plugins/action/organizations_saml_idps.py @@ -32,8 +32,8 @@ argument_spec = meraki_argument_spec() # Add arguments specific for this module argument_spec.update(dict( state=dict(type="str", default="present", choices=["present", "absent"]), - x509certSha1Fingerprint=dict(type="str"), sloLogoutUrl=dict(type="str"), + x509certSha1Fingerprint=dict(type="str"), organizationId=dict(type="str"), idpId=dict(type="str"), )) @@ -51,8 +51,8 @@ class OrganizationsSamlIdps(object): def __init__(self, params, meraki): self.meraki = meraki self.new_object = dict( - x509certSha1Fingerprint=params.get("x509certSha1Fingerprint"), sloLogoutUrl=params.get("sloLogoutUrl"), + x509certSha1Fingerprint=params.get("x509certSha1Fingerprint"), organizationId=params.get("organizationId"), idpId=params.get("idpId"), ) @@ -76,12 +76,12 @@ class OrganizationsSamlIdps(object): def create_params(self): new_object_params = {} - if self.new_object.get('x509certSha1Fingerprint') is not None or self.new_object.get('x509cert_sha1_fingerprint') is not None: - new_object_params['x509certSha1Fingerprint'] = self.new_object.get('x509certSha1Fingerprint') or \ - self.new_object.get('x509cert_sha1_fingerprint') if self.new_object.get('sloLogoutUrl') is not None or self.new_object.get('slo_logout_url') is not None: new_object_params['sloLogoutUrl'] = self.new_object.get('sloLogoutUrl') or \ self.new_object.get('slo_logout_url') + if self.new_object.get('x509certSha1Fingerprint') is not None or self.new_object.get('x509cert_sha1_fingerprint') is not None: + new_object_params['x509certSha1Fingerprint'] = self.new_object.get('x509certSha1Fingerprint') or \ + self.new_object.get('x509cert_sha1_fingerprint') if self.new_object.get('organizationId') is not None or self.new_object.get('organization_id') is not None: new_object_params['organizationId'] = self.new_object.get('organizationId') or \ self.new_object.get('organization_id') @@ -99,12 +99,12 @@ class OrganizationsSamlIdps(object): def update_by_id_params(self): new_object_params = {} - if self.new_object.get('x509certSha1Fingerprint') is not None or self.new_object.get('x509cert_sha1_fingerprint') is not None: - new_object_params['x509certSha1Fingerprint'] = self.new_object.get('x509certSha1Fingerprint') or \ - self.new_object.get('x509cert_sha1_fingerprint') if self.new_object.get('sloLogoutUrl') is not None or self.new_object.get('slo_logout_url') is not None: new_object_params['sloLogoutUrl'] = self.new_object.get('sloLogoutUrl') or \ self.new_object.get('slo_logout_url') + if self.new_object.get('x509certSha1Fingerprint') is not None or self.new_object.get('x509cert_sha1_fingerprint') is not None: + new_object_params['x509certSha1Fingerprint'] = self.new_object.get('x509certSha1Fingerprint') or \ + self.new_object.get('x509cert_sha1_fingerprint') if self.new_object.get('organizationId') is not None or self.new_object.get('organization_id') is not None: new_object_params['organizationId'] = self.new_object.get('organizationId') or \ self.new_object.get('organization_id') @@ -182,8 +182,8 @@ class OrganizationsSamlIdps(object): requested_obj = self.new_object obj_params = [ - ("x509certSha1Fingerprint", "x509certSha1Fingerprint"), ("sloLogoutUrl", "sloLogoutUrl"), + ("x509certSha1Fingerprint", "x509certSha1Fingerprint"), ("organizationId", "organizationId"), ("idpId", "idpId"), ] diff --git a/ansible_collections/cisco/meraki/plugins/action/organizations_saml_roles.py b/ansible_collections/cisco/meraki/plugins/action/organizations_saml_roles.py index 48dc6dfdb..bfc4a978b 100644 --- a/ansible_collections/cisco/meraki/plugins/action/organizations_saml_roles.py +++ b/ansible_collections/cisco/meraki/plugins/action/organizations_saml_roles.py @@ -32,10 +32,10 @@ argument_spec = meraki_argument_spec() # Add arguments specific for this module argument_spec.update(dict( state=dict(type="str", default="present", choices=["present", "absent"]), - role=dict(type="str"), + networks=dict(type="list"), orgAccess=dict(type="str"), + role=dict(type="str"), tags=dict(type="list"), - networks=dict(type="list"), organizationId=dict(type="str"), samlRoleId=dict(type="str"), )) @@ -53,10 +53,10 @@ class OrganizationsSamlRoles(object): def __init__(self, params, meraki): self.meraki = meraki self.new_object = dict( - role=params.get("role"), + networks=params.get("networks"), orgAccess=params.get("orgAccess"), + role=params.get("role"), tags=params.get("tags"), - networks=params.get("networks"), organizationId=params.get("organizationId"), samlRoleId=params.get("samlRoleId"), ) @@ -80,18 +80,18 @@ class OrganizationsSamlRoles(object): def create_params(self): new_object_params = {} - if self.new_object.get('role') is not None or self.new_object.get('role') is not None: - new_object_params['role'] = self.new_object.get('role') or \ - self.new_object.get('role') + if self.new_object.get('networks') is not None or self.new_object.get('networks') is not None: + new_object_params['networks'] = self.new_object.get('networks') or \ + self.new_object.get('networks') if self.new_object.get('orgAccess') is not None or self.new_object.get('org_access') is not None: new_object_params['orgAccess'] = self.new_object.get('orgAccess') or \ self.new_object.get('org_access') + if self.new_object.get('role') is not None or self.new_object.get('role') is not None: + new_object_params['role'] = self.new_object.get('role') or \ + self.new_object.get('role') if self.new_object.get('tags') is not None or self.new_object.get('tags') is not None: new_object_params['tags'] = self.new_object.get('tags') or \ self.new_object.get('tags') - if self.new_object.get('networks') is not None or self.new_object.get('networks') is not None: - new_object_params['networks'] = self.new_object.get('networks') or \ - self.new_object.get('networks') if self.new_object.get('organizationId') is not None or self.new_object.get('organization_id') is not None: new_object_params['organizationId'] = self.new_object.get('organizationId') or \ self.new_object.get('organization_id') @@ -109,18 +109,18 @@ class OrganizationsSamlRoles(object): def update_by_id_params(self): new_object_params = {} - if self.new_object.get('role') is not None or self.new_object.get('role') is not None: - new_object_params['role'] = self.new_object.get('role') or \ - self.new_object.get('role') + if self.new_object.get('networks') is not None or self.new_object.get('networks') is not None: + new_object_params['networks'] = self.new_object.get('networks') or \ + self.new_object.get('networks') if self.new_object.get('orgAccess') is not None or self.new_object.get('org_access') is not None: new_object_params['orgAccess'] = self.new_object.get('orgAccess') or \ self.new_object.get('org_access') + if self.new_object.get('role') is not None or self.new_object.get('role') is not None: + new_object_params['role'] = self.new_object.get('role') or \ + self.new_object.get('role') if self.new_object.get('tags') is not None or self.new_object.get('tags') is not None: new_object_params['tags'] = self.new_object.get('tags') or \ self.new_object.get('tags') - if self.new_object.get('networks') is not None or self.new_object.get('networks') is not None: - new_object_params['networks'] = self.new_object.get('networks') or \ - self.new_object.get('networks') if self.new_object.get('organizationId') is not None or self.new_object.get('organization_id') is not None: new_object_params['organizationId'] = self.new_object.get('organizationId') or \ self.new_object.get('organization_id') @@ -198,10 +198,10 @@ class OrganizationsSamlRoles(object): requested_obj = self.new_object obj_params = [ - ("role", "role"), + ("networks", "networks"), ("orgAccess", "orgAccess"), + ("role", "role"), ("tags", "tags"), - ("networks", "networks"), ("organizationId", "organizationId"), ("samlRoleId", "samlRoleId"), ] diff --git a/ansible_collections/cisco/meraki/plugins/action/organizations_sm_admins_roles.py b/ansible_collections/cisco/meraki/plugins/action/organizations_sm_admins_roles.py new file mode 100644 index 000000000..4bbf8db98 --- /dev/null +++ b/ansible_collections/cisco/meraki/plugins/action/organizations_sm_admins_roles.py @@ -0,0 +1,256 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +# Copyright (c) 2021, Cisco Systems +# 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 +from ansible.plugins.action import ActionBase +try: + from ansible_collections.ansible.utils.plugins.module_utils.common.argspec_validate import ( + AnsibleArgSpecValidator, + ) +except ImportError: + ANSIBLE_UTILS_IS_INSTALLED = False +else: + ANSIBLE_UTILS_IS_INSTALLED = True +from ansible.errors import AnsibleActionFail +from ansible_collections.cisco.meraki.plugins.plugin_utils.meraki import ( + MERAKI, + meraki_argument_spec, + meraki_compare_equality, + get_dict_result, +) +from ansible_collections.cisco.meraki.plugins.plugin_utils.exceptions import ( + InconsistentParameters, +) + +# Get common arguments specification +argument_spec = meraki_argument_spec() +# Add arguments specific for this module +argument_spec.update(dict( + state=dict(type="str", default="present", choices=["present", "absent"]), + name=dict(type="str"), + scope=dict(type="str"), + tags=dict(type="list"), + organizationId=dict(type="str"), +)) + +required_if = [ + ("state", "present", ["name", "organizationId"], True), + ("state", "absent", ["name", "organizationId"], True), +] +required_one_of = [] +mutually_exclusive = [] +required_together = [] + + +class OrganizationsSmAdminsRoles(object): + def __init__(self, params, meraki): + self.meraki = meraki + self.new_object = dict( + name=params.get("name"), + scope=params.get("scope"), + tags=params.get("tags"), + organizationId=params.get("organizationId"), + ) + + def get_all_params(self, name=None, id=None): + new_object_params = {} + if self.new_object.get('perPage') is not None or self.new_object.get('per_page') is not None: + new_object_params['perPage'] = self.new_object.get('perPage') or \ + self.new_object.get('per_page') + new_object_params['total_pages'] = -1 + if self.new_object.get('startingAfter') is not None or self.new_object.get('starting_after') is not None: + new_object_params['startingAfter'] = self.new_object.get('startingAfter') or \ + self.new_object.get('starting_after') + if self.new_object.get('endingBefore') is not None or self.new_object.get('ending_before') is not None: + new_object_params['endingBefore'] = self.new_object.get('endingBefore') or \ + self.new_object.get('ending_before') + if self.new_object.get('organizationId') is not None or self.new_object.get('organization_id') is not None: + new_object_params['organizationId'] = self.new_object.get('organizationId') or \ + self.new_object.get('organization_id') + return new_object_params + + def create_params(self): + new_object_params = {} + if self.new_object.get('name') is not None or self.new_object.get('name') is not None: + new_object_params['name'] = self.new_object.get('name') or \ + self.new_object.get('name') + if self.new_object.get('scope') is not None or self.new_object.get('scope') is not None: + new_object_params['scope'] = self.new_object.get('scope') or \ + self.new_object.get('scope') + if self.new_object.get('tags') is not None or self.new_object.get('tags') is not None: + new_object_params['tags'] = self.new_object.get('tags') or \ + self.new_object.get('tags') + if self.new_object.get('organizationId') is not None or self.new_object.get('organization_id') is not None: + new_object_params['organizationId'] = self.new_object.get('organizationId') or \ + self.new_object.get('organization_id') + return new_object_params + + def get_object_by_name(self, name): + result = None + # NOTE: Does not have a get by name method or it is in another action + try: + items = self.meraki.exec_meraki( + family="sm", + function="getOrganizationSmAdminsRoles", + params=self.get_all_params(name=name), + ) + if isinstance(items, dict): + if 'response' in items: + items = items.get('response') + result = get_dict_result(items, 'name', name) + if result is None: + result = items + except Exception as e: + print("Error: ", e) + result = None + return result + + def get_object_by_id(self, id): + result = None + # NOTE: Does not have a get by id method or it is in another action + try: + items = self.meraki.exec_meraki( + family="sm", + function="getOrganizationSmAdminsRoles", + params=self.get_all_params(id=id), + ) + if isinstance(items, dict): + if 'response' in items: + items = items.get('response') + result = get_dict_result(items, 'id', id) + except Exception as e: + print("Error: ", e) + result = None + return result + + def exists(self): + id_exists = False + name_exists = False + prev_obj = None + o_id = self.new_object.get("id") + name = self.new_object.get("name") + if o_id: + prev_obj = self.get_object_by_id(o_id) + id_exists = prev_obj is not None and isinstance(prev_obj, dict) + if not id_exists and name: + prev_obj = self.get_object_by_name(name) + name_exists = prev_obj is not None and isinstance(prev_obj, dict) + if name_exists: + _id = prev_obj.get("id") + if id_exists and name_exists and o_id != _id: + raise InconsistentParameters( + "The 'id' and 'name' params don't refer to the same object") + if _id: + self.new_object.update(dict(id=_id)) + it_exists = prev_obj is not None and isinstance(prev_obj, dict) + return (it_exists, prev_obj) + + def requires_update(self, current_obj): + requested_obj = self.new_object + + obj_params = [ + ("name", "name"), + ("scope", "scope"), + ("tags", "tags"), + ("organizationId", "organizationId"), + ] + # Method 1. Params present in request (Ansible) obj are the same as the current (DNAC) params + # If any does not have eq params, it requires update + return any(not meraki_compare_equality(current_obj.get(meraki_param), + requested_obj.get(ansible_param)) + for (meraki_param, ansible_param) in obj_params) + + def create(self): + result = self.meraki.exec_meraki( + family="sm", + function="createOrganizationSmAdminsRole", + params=self.create_params(), + op_modifies=True, + ) + return result + + def update(self): + id = self.new_object.get("id") + name = self.new_object.get("name") + result = None + # NOTE: Does not have update method. What do we do? + return result + + def delete(self): + id = self.new_object.get("id") + name = self.new_object.get("name") + result = None + # NOTE: Does not have delete method. What do we do? + return result + + +class ActionModule(ActionBase): + def __init__(self, *args, **kwargs): + if not ANSIBLE_UTILS_IS_INSTALLED: + raise AnsibleActionFail( + "ansible.utils is not installed. Execute 'ansible-galaxy collection install ansible.utils'") + super(ActionModule, self).__init__(*args, **kwargs) + self._supports_async = False + self._supports_check_mode = False + self._result = None + + # Checks the supplied parameters against the argument spec for this module + def _check_argspec(self): + aav = AnsibleArgSpecValidator( + data=self._task.args, + schema=dict(argument_spec=argument_spec), + schema_format="argspec", + schema_conditionals=dict( + required_if=required_if, + required_one_of=required_one_of, + mutually_exclusive=mutually_exclusive, + required_together=required_together, + ), + name=self._task.action, + ) + valid, errors, self._task.args = aav.validate() + if not valid: + raise AnsibleActionFail(errors) + + def run(self, tmp=None, task_vars=None): + self._task.diff = False + self._result = super(ActionModule, self).run(tmp, task_vars) + self._result["changed"] = False + self._check_argspec() + + meraki = MERAKI(self._task.args) + obj = OrganizationsSmAdminsRoles(self._task.args, meraki) + + state = self._task.args.get("state") + + response = None + + if state == "present": + (obj_exists, prev_obj) = obj.exists() + if obj_exists: + if obj.requires_update(prev_obj): + response = obj.update() + meraki.object_updated() + else: + response = prev_obj + meraki.object_already_present() + else: + response = obj.create() + meraki.object_created() + + elif state == "absent": + (obj_exists, prev_obj) = obj.exists() + if obj_exists: + response = obj.delete() + meraki.object_deleted() + else: + meraki.object_already_absent() + + self._result.update(dict(meraki_response=response)) + self._result.update(meraki.exit_json()) + return self._result diff --git a/ansible_collections/cisco/meraki/plugins/action/organizations_sm_admins_roles_info.py b/ansible_collections/cisco/meraki/plugins/action/organizations_sm_admins_roles_info.py new file mode 100644 index 000000000..297c64b48 --- /dev/null +++ b/ansible_collections/cisco/meraki/plugins/action/organizations_sm_admins_roles_info.py @@ -0,0 +1,108 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +# Copyright (c) 2021, Cisco Systems +# 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 +from ansible.plugins.action import ActionBase +try: + from ansible_collections.ansible.utils.plugins.module_utils.common.argspec_validate import ( + AnsibleArgSpecValidator, + ) +except ImportError: + ANSIBLE_UTILS_IS_INSTALLED = False +else: + ANSIBLE_UTILS_IS_INSTALLED = True +from ansible.errors import AnsibleActionFail +from ansible_collections.cisco.meraki.plugins.plugin_utils.meraki import ( + MERAKI, + meraki_argument_spec, +) + +# Get common arguments specification +argument_spec = meraki_argument_spec() +# Add arguments specific for this module +argument_spec.update(dict( + organizationId=dict(type="str"), + perPage=dict(type="int"), + total_pages=dict(type="int"), + direction=dict(type="str"), + startingAfter=dict(type="str"), + endingBefore=dict(type="str"), +)) + +required_if = [] +required_one_of = [] +mutually_exclusive = [] +required_together = [] + + +class ActionModule(ActionBase): + def __init__(self, *args, **kwargs): + if not ANSIBLE_UTILS_IS_INSTALLED: + raise AnsibleActionFail( + "ansible.utils is not installed. Execute 'ansible-galaxy collection install ansible.utils'") + super(ActionModule, self).__init__(*args, **kwargs) + self._supports_async = False + self._supports_check_mode = True + self._result = None + + # Checks the supplied parameters against the argument spec for this module + def _check_argspec(self): + aav = AnsibleArgSpecValidator( + data=self._task.args, + schema=dict(argument_spec=argument_spec), + schema_format="argspec", + schema_conditionals=dict( + required_if=required_if, + required_one_of=required_one_of, + mutually_exclusive=mutually_exclusive, + required_together=required_together, + ), + name=self._task.action, + ) + valid, errors, self._task.args = aav.validate() + if not valid: + raise AnsibleActionFail(errors) + + def get_all(self, params): + new_object = {} + if params.get("organizationId") is not None: + new_object["organizationId"] = params.get( + "organizationId") + if params.get("perPage") is not None: + new_object["perPage"] = params.get( + "perPage") + new_object['total_pages'] = params.get( + "total_pages") or 1 + new_object['direction'] = params.get( + "direction") or "next" + if params.get("startingAfter") is not None: + new_object["startingAfter"] = params.get( + "startingAfter") + if params.get("endingBefore") is not None: + new_object["endingBefore"] = params.get( + "endingBefore") + + return new_object + + def run(self, tmp=None, task_vars=None): + self._task.diff = False + self._result = super(ActionModule, self).run(tmp, task_vars) + self._result["changed"] = False + self._check_argspec() + + self._result.update(dict(meraki_response={})) + + meraki = MERAKI(params=self._task.args) + + response = meraki.exec_meraki( + family="sm", + function='getOrganizationSmAdminsRoles', + params=self.get_all(self._task.args), + ) + self._result.update(dict(meraki_response=response)) + self._result.update(meraki.exit_json()) + return self._result diff --git a/ansible_collections/cisco/meraki/plugins/action/organizations_sm_sentry_policies_assignments.py b/ansible_collections/cisco/meraki/plugins/action/organizations_sm_sentry_policies_assignments.py new file mode 100644 index 000000000..8e51a06e0 --- /dev/null +++ b/ansible_collections/cisco/meraki/plugins/action/organizations_sm_sentry_policies_assignments.py @@ -0,0 +1,89 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +# Copyright (c) 2021, Cisco Systems +# 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 +from ansible.plugins.action import ActionBase +try: + from ansible_collections.ansible.utils.plugins.module_utils.common.argspec_validate import ( + AnsibleArgSpecValidator, + ) +except ImportError: + ANSIBLE_UTILS_IS_INSTALLED = False +else: + ANSIBLE_UTILS_IS_INSTALLED = True +from ansible.errors import AnsibleActionFail +from ansible_collections.cisco.meraki.plugins.plugin_utils.meraki import ( + MERAKI, + meraki_argument_spec, +) + +# Get common arguements specification +argument_spec = meraki_argument_spec() +# Add arguments specific for this module +argument_spec.update(dict( + items=dict(type="list"), + organizationId=dict(type="str"), +)) + +required_if = [] +required_one_of = [] +mutually_exclusive = [] +required_together = [] + + +class ActionModule(ActionBase): + def __init__(self, *args, **kwargs): + if not ANSIBLE_UTILS_IS_INSTALLED: + raise AnsibleActionFail( + "ansible.utils is not installed. Execute 'ansible-galaxy collection install ansible.utils'") + super(ActionModule, self).__init__(*args, **kwargs) + self._supports_async = False + self._supports_check_mode = False + self._result = None + + # Checks the supplied parameters against the argument spec for this module + def _check_argspec(self): + aav = AnsibleArgSpecValidator( + data=self._task.args, + schema=dict(argument_spec=argument_spec), + schema_format="argspec", + schema_conditionals=dict( + required_if=required_if, + required_one_of=required_one_of, + mutually_exclusive=mutually_exclusive, + required_together=required_together, + ), + name=self._task.action, + ) + valid, errors, self._task.args = aav.validate() + if not valid: + raise AnsibleActionFail(errors) + + def get_object(self, params): + new_object = dict( + items=params.get("items"), + organizationId=params.get("organizationId"), + ) + return new_object + + def run(self, tmp=None, task_vars=None): + self._task.diff = False + self._result = super(ActionModule, self).run(tmp, task_vars) + self._result["changed"] = False + self._check_argspec() + + meraki = MERAKI(params=self._task.args) + + response = meraki.exec_meraki( + family="sm", + function='updateOrganizationSmSentryPoliciesAssignments', + op_modifies=True, + params=self.get_object(self._task.args), + ) + self._result.update(dict(meraki_response=response)) + self._result.update(meraki.exit_json()) + return self._result diff --git a/ansible_collections/cisco/meraki/plugins/action/organizations_sm_sentry_policies_assignments_by_network_info.py b/ansible_collections/cisco/meraki/plugins/action/organizations_sm_sentry_policies_assignments_by_network_info.py new file mode 100644 index 000000000..fdc3bd05d --- /dev/null +++ b/ansible_collections/cisco/meraki/plugins/action/organizations_sm_sentry_policies_assignments_by_network_info.py @@ -0,0 +1,112 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +# Copyright (c) 2021, Cisco Systems +# 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 +from ansible.plugins.action import ActionBase +try: + from ansible_collections.ansible.utils.plugins.module_utils.common.argspec_validate import ( + AnsibleArgSpecValidator, + ) +except ImportError: + ANSIBLE_UTILS_IS_INSTALLED = False +else: + ANSIBLE_UTILS_IS_INSTALLED = True +from ansible.errors import AnsibleActionFail +from ansible_collections.cisco.meraki.plugins.plugin_utils.meraki import ( + MERAKI, + meraki_argument_spec, +) + +# Get common arguments specification +argument_spec = meraki_argument_spec() +# Add arguments specific for this module +argument_spec.update(dict( + organizationId=dict(type="str"), + perPage=dict(type="int"), + total_pages=dict(type="int"), + direction=dict(type="str"), + startingAfter=dict(type="str"), + endingBefore=dict(type="str"), + networkIds=dict(type="list"), +)) + +required_if = [] +required_one_of = [] +mutually_exclusive = [] +required_together = [] + + +class ActionModule(ActionBase): + def __init__(self, *args, **kwargs): + if not ANSIBLE_UTILS_IS_INSTALLED: + raise AnsibleActionFail( + "ansible.utils is not installed. Execute 'ansible-galaxy collection install ansible.utils'") + super(ActionModule, self).__init__(*args, **kwargs) + self._supports_async = False + self._supports_check_mode = True + self._result = None + + # Checks the supplied parameters against the argument spec for this module + def _check_argspec(self): + aav = AnsibleArgSpecValidator( + data=self._task.args, + schema=dict(argument_spec=argument_spec), + schema_format="argspec", + schema_conditionals=dict( + required_if=required_if, + required_one_of=required_one_of, + mutually_exclusive=mutually_exclusive, + required_together=required_together, + ), + name=self._task.action, + ) + valid, errors, self._task.args = aav.validate() + if not valid: + raise AnsibleActionFail(errors) + + def get_all(self, params): + new_object = {} + if params.get("organizationId") is not None: + new_object["organizationId"] = params.get( + "organizationId") + if params.get("perPage") is not None: + new_object["perPage"] = params.get( + "perPage") + new_object['total_pages'] = params.get( + "total_pages") or 1 + new_object['direction'] = params.get( + "direction") or "next" + if params.get("startingAfter") is not None: + new_object["startingAfter"] = params.get( + "startingAfter") + if params.get("endingBefore") is not None: + new_object["endingBefore"] = params.get( + "endingBefore") + if params.get("networkIds") is not None: + new_object["networkIds"] = params.get( + "networkIds") + + return new_object + + def run(self, tmp=None, task_vars=None): + self._task.diff = False + self._result = super(ActionModule, self).run(tmp, task_vars) + self._result["changed"] = False + self._check_argspec() + + self._result.update(dict(meraki_response={})) + + meraki = MERAKI(params=self._task.args) + + response = meraki.exec_meraki( + family="sm", + function='getOrganizationSmSentryPoliciesAssignmentsByNetwork', + params=self.get_all(self._task.args), + ) + self._result.update(dict(meraki_response=response)) + self._result.update(meraki.exit_json()) + return self._result diff --git a/ansible_collections/cisco/meraki/plugins/action/organizations_snmp.py b/ansible_collections/cisco/meraki/plugins/action/organizations_snmp.py index aaf676ee7..4641a02e5 100644 --- a/ansible_collections/cisco/meraki/plugins/action/organizations_snmp.py +++ b/ansible_collections/cisco/meraki/plugins/action/organizations_snmp.py @@ -32,13 +32,13 @@ argument_spec = meraki_argument_spec() # Add arguments specific for this module argument_spec.update(dict( state=dict(type="str", default="present", choices=["present"]), + peerIps=dict(type="list"), v2cEnabled=dict(type="bool"), - v3Enabled=dict(type="bool"), v3AuthMode=dict(type="str"), v3AuthPass=dict(type="str"), + v3Enabled=dict(type="bool"), v3PrivMode=dict(type="str"), v3PrivPass=dict(type="str"), - peerIps=dict(type="list"), organizationId=dict(type="str"), )) @@ -54,13 +54,13 @@ class OrganizationsSnmp(object): def __init__(self, params, meraki): self.meraki = meraki self.new_object = dict( + peerIps=params.get("peerIps"), v2cEnabled=params.get("v2cEnabled"), - v3Enabled=params.get("v3Enabled"), v3AuthMode=params.get("v3AuthMode"), v3AuthPass=params.get("v3AuthPass"), + v3Enabled=params.get("v3Enabled"), v3PrivMode=params.get("v3PrivMode"), v3PrivPass=params.get("v3PrivPass"), - peerIps=params.get("peerIps"), organization_id=params.get("organizationId"), ) @@ -73,25 +73,25 @@ class OrganizationsSnmp(object): def update_all_params(self): new_object_params = {} + if self.new_object.get('peerIps') is not None or self.new_object.get('peer_ips') is not None: + new_object_params['peerIps'] = self.new_object.get('peerIps') or \ + self.new_object.get('peer_ips') if self.new_object.get('v2cEnabled') is not None or self.new_object.get('v2c_enabled') is not None: new_object_params['v2cEnabled'] = self.new_object.get('v2cEnabled') - if self.new_object.get('v3Enabled') is not None or self.new_object.get('v3_enabled') is not None: - new_object_params['v3Enabled'] = self.new_object.get('v3Enabled') if self.new_object.get('v3AuthMode') is not None or self.new_object.get('v3_auth_mode') is not None: new_object_params['v3AuthMode'] = self.new_object.get('v3AuthMode') or \ self.new_object.get('v3_auth_mode') if self.new_object.get('v3AuthPass') is not None or self.new_object.get('v3_auth_pass') is not None: new_object_params['v3AuthPass'] = self.new_object.get('v3AuthPass') or \ self.new_object.get('v3_auth_pass') + if self.new_object.get('v3Enabled') is not None or self.new_object.get('v3_enabled') is not None: + new_object_params['v3Enabled'] = self.new_object.get('v3Enabled') if self.new_object.get('v3PrivMode') is not None or self.new_object.get('v3_priv_mode') is not None: new_object_params['v3PrivMode'] = self.new_object.get('v3PrivMode') or \ self.new_object.get('v3_priv_mode') if self.new_object.get('v3PrivPass') is not None or self.new_object.get('v3_priv_pass') is not None: new_object_params['v3PrivPass'] = self.new_object.get('v3PrivPass') or \ self.new_object.get('v3_priv_pass') - if self.new_object.get('peerIps') is not None or self.new_object.get('peer_ips') is not None: - new_object_params['peerIps'] = self.new_object.get('peerIps') or \ - self.new_object.get('peer_ips') if self.new_object.get('organizationId') is not None or self.new_object.get('organization_id') is not None: new_object_params['organizationId'] = self.new_object.get('organizationId') or \ self.new_object.get('organization_id') @@ -148,13 +148,13 @@ class OrganizationsSnmp(object): requested_obj = self.new_object obj_params = [ + ("peerIps", "peerIps"), ("v2cEnabled", "v2cEnabled"), - ("v3Enabled", "v3Enabled"), ("v3AuthMode", "v3AuthMode"), ("v3AuthPass", "v3AuthPass"), + ("v3Enabled", "v3Enabled"), ("v3PrivMode", "v3PrivMode"), ("v3PrivPass", "v3PrivPass"), - ("peerIps", "peerIps"), ("organizationId", "organizationId"), ] # Method 1. Params present in request (Ansible) obj are the same as the current (ISE) params diff --git a/ansible_collections/cisco/meraki/plugins/action/organizations_summary_top_networks_by_status_info.py b/ansible_collections/cisco/meraki/plugins/action/organizations_summary_top_networks_by_status_info.py new file mode 100644 index 000000000..c7091e152 --- /dev/null +++ b/ansible_collections/cisco/meraki/plugins/action/organizations_summary_top_networks_by_status_info.py @@ -0,0 +1,108 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +# Copyright (c) 2021, Cisco Systems +# 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 +from ansible.plugins.action import ActionBase +try: + from ansible_collections.ansible.utils.plugins.module_utils.common.argspec_validate import ( + AnsibleArgSpecValidator, + ) +except ImportError: + ANSIBLE_UTILS_IS_INSTALLED = False +else: + ANSIBLE_UTILS_IS_INSTALLED = True +from ansible.errors import AnsibleActionFail +from ansible_collections.cisco.meraki.plugins.plugin_utils.meraki import ( + MERAKI, + meraki_argument_spec, +) + +# Get common arguments specification +argument_spec = meraki_argument_spec() +# Add arguments specific for this module +argument_spec.update(dict( + organizationId=dict(type="str"), + perPage=dict(type="int"), + total_pages=dict(type="int"), + direction=dict(type="str"), + startingAfter=dict(type="str"), + endingBefore=dict(type="str"), +)) + +required_if = [] +required_one_of = [] +mutually_exclusive = [] +required_together = [] + + +class ActionModule(ActionBase): + def __init__(self, *args, **kwargs): + if not ANSIBLE_UTILS_IS_INSTALLED: + raise AnsibleActionFail( + "ansible.utils is not installed. Execute 'ansible-galaxy collection install ansible.utils'") + super(ActionModule, self).__init__(*args, **kwargs) + self._supports_async = False + self._supports_check_mode = True + self._result = None + + # Checks the supplied parameters against the argument spec for this module + def _check_argspec(self): + aav = AnsibleArgSpecValidator( + data=self._task.args, + schema=dict(argument_spec=argument_spec), + schema_format="argspec", + schema_conditionals=dict( + required_if=required_if, + required_one_of=required_one_of, + mutually_exclusive=mutually_exclusive, + required_together=required_together, + ), + name=self._task.action, + ) + valid, errors, self._task.args = aav.validate() + if not valid: + raise AnsibleActionFail(errors) + + def get_all(self, params): + new_object = {} + if params.get("organizationId") is not None: + new_object["organizationId"] = params.get( + "organizationId") + if params.get("perPage") is not None: + new_object["perPage"] = params.get( + "perPage") + new_object['total_pages'] = params.get( + "total_pages") or 1 + new_object['direction'] = params.get( + "direction") or "next" + if params.get("startingAfter") is not None: + new_object["startingAfter"] = params.get( + "startingAfter") + if params.get("endingBefore") is not None: + new_object["endingBefore"] = params.get( + "endingBefore") + + return new_object + + def run(self, tmp=None, task_vars=None): + self._task.diff = False + self._result = super(ActionModule, self).run(tmp, task_vars) + self._result["changed"] = False + self._check_argspec() + + self._result.update(dict(meraki_response={})) + + meraki = MERAKI(params=self._task.args) + + response = meraki.exec_meraki( + family="organizations", + function='getOrganizationSummaryTopNetworksByStatus', + params=self.get_all(self._task.args), + ) + self._result.update(dict(meraki_response=response)) + self._result.update(meraki.exit_json()) + return self._result diff --git a/ansible_collections/cisco/meraki/plugins/action/organizations_webhooks_callbacks_statuses_info.py b/ansible_collections/cisco/meraki/plugins/action/organizations_webhooks_callbacks_statuses_info.py new file mode 100644 index 000000000..868d02371 --- /dev/null +++ b/ansible_collections/cisco/meraki/plugins/action/organizations_webhooks_callbacks_statuses_info.py @@ -0,0 +1,102 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +# Copyright (c) 2021, Cisco Systems +# 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 +from ansible.plugins.action import ActionBase +try: + from ansible_collections.ansible.utils.plugins.module_utils.common.argspec_validate import ( + AnsibleArgSpecValidator, + ) +except ImportError: + ANSIBLE_UTILS_IS_INSTALLED = False +else: + ANSIBLE_UTILS_IS_INSTALLED = True +from ansible.errors import AnsibleActionFail +from ansible_collections.cisco.meraki.plugins.plugin_utils.meraki import ( + MERAKI, + meraki_argument_spec, +) + +# Get common arguments specification +argument_spec = meraki_argument_spec() +# Add arguments specific for this module +argument_spec.update(dict( + organizationId=dict(type="str"), + callbackId=dict(type="str"), +)) + +required_if = [] +required_one_of = [] +mutually_exclusive = [] +required_together = [] + + +class ActionModule(ActionBase): + def __init__(self, *args, **kwargs): + if not ANSIBLE_UTILS_IS_INSTALLED: + raise AnsibleActionFail( + "ansible.utils is not installed. Execute 'ansible-galaxy collection install ansible.utils'") + super(ActionModule, self).__init__(*args, **kwargs) + self._supports_async = False + self._supports_check_mode = True + self._result = None + + # Checks the supplied parameters against the argument spec for this module + def _check_argspec(self): + aav = AnsibleArgSpecValidator( + data=self._task.args, + schema=dict(argument_spec=argument_spec), + schema_format="argspec", + schema_conditionals=dict( + required_if=required_if, + required_one_of=required_one_of, + mutually_exclusive=mutually_exclusive, + required_together=required_together, + ), + name=self._task.action, + ) + valid, errors, self._task.args = aav.validate() + if not valid: + raise AnsibleActionFail(errors) + + def get_object(self, params): + new_object = {} + if params.get("organizationId") is not None: + new_object["organizationId"] = params.get( + "organizationId") + if params.get("callbackId") is not None: + new_object["callbackId"] = params.get( + "callbackId") + return new_object + + def run(self, tmp=None, task_vars=None): + self._task.diff = False + self._result = super(ActionModule, self).run(tmp, task_vars) + self._result["changed"] = False + self._check_argspec() + + self._result.update(dict(meraki_response={})) + + meraki = MERAKI(params=self._task.args) + + id = self._task.args.get("callbackId") + if id: + response = meraki.exec_meraki( + family="organizations", + function='getOrganizationWebhooksCallbacksStatus', + params=self.get_object(self._task.args), + ) + self._result.update(dict(meraki_response=response)) + self._result.update(meraki.exit_json()) + return self._result + if not id: + # NOTE: Does not have a get all method or it is in another action + response = None + meraki.object_modify_result(changed=False, result="Module does not have get all, check arguments of module") + self._result.update(dict(meraki_response=response)) + self._result.update(meraki.exit_json()) + return self._result diff --git a/ansible_collections/cisco/meraki/plugins/action/organizations_wireless_devices_channel_utilization_by_device_info.py b/ansible_collections/cisco/meraki/plugins/action/organizations_wireless_devices_channel_utilization_by_device_info.py new file mode 100644 index 000000000..5d78f5a98 --- /dev/null +++ b/ansible_collections/cisco/meraki/plugins/action/organizations_wireless_devices_channel_utilization_by_device_info.py @@ -0,0 +1,132 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +# Copyright (c) 2021, Cisco Systems +# 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 +from ansible.plugins.action import ActionBase +try: + from ansible_collections.ansible.utils.plugins.module_utils.common.argspec_validate import ( + AnsibleArgSpecValidator, + ) +except ImportError: + ANSIBLE_UTILS_IS_INSTALLED = False +else: + ANSIBLE_UTILS_IS_INSTALLED = True +from ansible.errors import AnsibleActionFail +from ansible_collections.cisco.meraki.plugins.plugin_utils.meraki import ( + MERAKI, + meraki_argument_spec, +) + +# Get common arguments specification +argument_spec = meraki_argument_spec() +# Add arguments specific for this module +argument_spec.update(dict( + organizationId=dict(type="str"), + networkIds=dict(type="list"), + serials=dict(type="list"), + perPage=dict(type="int"), + total_pages=dict(type="int"), + direction=dict(type="str"), + startingAfter=dict(type="str"), + endingBefore=dict(type="str"), + t0=dict(type="str"), + t1=dict(type="str"), + timespan=dict(type="float"), + interval=dict(type="int"), +)) + +required_if = [] +required_one_of = [] +mutually_exclusive = [] +required_together = [] + + +class ActionModule(ActionBase): + def __init__(self, *args, **kwargs): + if not ANSIBLE_UTILS_IS_INSTALLED: + raise AnsibleActionFail( + "ansible.utils is not installed. Execute 'ansible-galaxy collection install ansible.utils'") + super(ActionModule, self).__init__(*args, **kwargs) + self._supports_async = False + self._supports_check_mode = True + self._result = None + + # Checks the supplied parameters against the argument spec for this module + def _check_argspec(self): + aav = AnsibleArgSpecValidator( + data=self._task.args, + schema=dict(argument_spec=argument_spec), + schema_format="argspec", + schema_conditionals=dict( + required_if=required_if, + required_one_of=required_one_of, + mutually_exclusive=mutually_exclusive, + required_together=required_together, + ), + name=self._task.action, + ) + valid, errors, self._task.args = aav.validate() + if not valid: + raise AnsibleActionFail(errors) + + def get_all(self, params): + new_object = {} + if params.get("organizationId") is not None: + new_object["organizationId"] = params.get( + "organizationId") + if params.get("networkIds") is not None: + new_object["networkIds"] = params.get( + "networkIds") + if params.get("serials") is not None: + new_object["serials"] = params.get( + "serials") + if params.get("perPage") is not None: + new_object["perPage"] = params.get( + "perPage") + new_object['total_pages'] = params.get( + "total_pages") or 1 + new_object['direction'] = params.get( + "direction") or "next" + if params.get("startingAfter") is not None: + new_object["startingAfter"] = params.get( + "startingAfter") + if params.get("endingBefore") is not None: + new_object["endingBefore"] = params.get( + "endingBefore") + if params.get("t0") is not None: + new_object["t0"] = params.get( + "t0") + if params.get("t1") is not None: + new_object["t1"] = params.get( + "t1") + if params.get("timespan") is not None: + new_object["timespan"] = params.get( + "timespan") + if params.get("interval") is not None: + new_object["interval"] = params.get( + "interval") + + return new_object + + def run(self, tmp=None, task_vars=None): + self._task.diff = False + self._result = super(ActionModule, self).run(tmp, task_vars) + self._result["changed"] = False + self._check_argspec() + + self._result.update(dict(meraki_response={})) + + meraki = MERAKI(params=self._task.args) + + response = meraki.exec_meraki( + family="wireless", + function='getOrganizationWirelessDevicesChannelUtilizationByDevice', + params=self.get_all(self._task.args), + ) + self._result.update(dict(meraki_response=response)) + self._result.update(meraki.exit_json()) + return self._result diff --git a/ansible_collections/cisco/meraki/plugins/action/organizations_wireless_devices_channel_utilization_by_network_info.py b/ansible_collections/cisco/meraki/plugins/action/organizations_wireless_devices_channel_utilization_by_network_info.py new file mode 100644 index 000000000..fb57fd52f --- /dev/null +++ b/ansible_collections/cisco/meraki/plugins/action/organizations_wireless_devices_channel_utilization_by_network_info.py @@ -0,0 +1,132 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +# Copyright (c) 2021, Cisco Systems +# 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 +from ansible.plugins.action import ActionBase +try: + from ansible_collections.ansible.utils.plugins.module_utils.common.argspec_validate import ( + AnsibleArgSpecValidator, + ) +except ImportError: + ANSIBLE_UTILS_IS_INSTALLED = False +else: + ANSIBLE_UTILS_IS_INSTALLED = True +from ansible.errors import AnsibleActionFail +from ansible_collections.cisco.meraki.plugins.plugin_utils.meraki import ( + MERAKI, + meraki_argument_spec, +) + +# Get common arguments specification +argument_spec = meraki_argument_spec() +# Add arguments specific for this module +argument_spec.update(dict( + organizationId=dict(type="str"), + networkIds=dict(type="list"), + serials=dict(type="list"), + perPage=dict(type="int"), + total_pages=dict(type="int"), + direction=dict(type="str"), + startingAfter=dict(type="str"), + endingBefore=dict(type="str"), + t0=dict(type="str"), + t1=dict(type="str"), + timespan=dict(type="float"), + interval=dict(type="int"), +)) + +required_if = [] +required_one_of = [] +mutually_exclusive = [] +required_together = [] + + +class ActionModule(ActionBase): + def __init__(self, *args, **kwargs): + if not ANSIBLE_UTILS_IS_INSTALLED: + raise AnsibleActionFail( + "ansible.utils is not installed. Execute 'ansible-galaxy collection install ansible.utils'") + super(ActionModule, self).__init__(*args, **kwargs) + self._supports_async = False + self._supports_check_mode = True + self._result = None + + # Checks the supplied parameters against the argument spec for this module + def _check_argspec(self): + aav = AnsibleArgSpecValidator( + data=self._task.args, + schema=dict(argument_spec=argument_spec), + schema_format="argspec", + schema_conditionals=dict( + required_if=required_if, + required_one_of=required_one_of, + mutually_exclusive=mutually_exclusive, + required_together=required_together, + ), + name=self._task.action, + ) + valid, errors, self._task.args = aav.validate() + if not valid: + raise AnsibleActionFail(errors) + + def get_all(self, params): + new_object = {} + if params.get("organizationId") is not None: + new_object["organizationId"] = params.get( + "organizationId") + if params.get("networkIds") is not None: + new_object["networkIds"] = params.get( + "networkIds") + if params.get("serials") is not None: + new_object["serials"] = params.get( + "serials") + if params.get("perPage") is not None: + new_object["perPage"] = params.get( + "perPage") + new_object['total_pages'] = params.get( + "total_pages") or 1 + new_object['direction'] = params.get( + "direction") or "next" + if params.get("startingAfter") is not None: + new_object["startingAfter"] = params.get( + "startingAfter") + if params.get("endingBefore") is not None: + new_object["endingBefore"] = params.get( + "endingBefore") + if params.get("t0") is not None: + new_object["t0"] = params.get( + "t0") + if params.get("t1") is not None: + new_object["t1"] = params.get( + "t1") + if params.get("timespan") is not None: + new_object["timespan"] = params.get( + "timespan") + if params.get("interval") is not None: + new_object["interval"] = params.get( + "interval") + + return new_object + + def run(self, tmp=None, task_vars=None): + self._task.diff = False + self._result = super(ActionModule, self).run(tmp, task_vars) + self._result["changed"] = False + self._check_argspec() + + self._result.update(dict(meraki_response={})) + + meraki = MERAKI(params=self._task.args) + + response = meraki.exec_meraki( + family="wireless", + function='getOrganizationWirelessDevicesChannelUtilizationByNetwork', + params=self.get_all(self._task.args), + ) + self._result.update(dict(meraki_response=response)) + self._result.update(meraki.exit_json()) + return self._result diff --git a/ansible_collections/cisco/meraki/plugins/action/organizations_wireless_devices_channel_utilization_history_by_device_by_interval_info.py b/ansible_collections/cisco/meraki/plugins/action/organizations_wireless_devices_channel_utilization_history_by_device_by_interval_info.py new file mode 100644 index 000000000..9bd73d0b2 --- /dev/null +++ b/ansible_collections/cisco/meraki/plugins/action/organizations_wireless_devices_channel_utilization_history_by_device_by_interval_info.py @@ -0,0 +1,132 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +# Copyright (c) 2021, Cisco Systems +# 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 +from ansible.plugins.action import ActionBase +try: + from ansible_collections.ansible.utils.plugins.module_utils.common.argspec_validate import ( + AnsibleArgSpecValidator, + ) +except ImportError: + ANSIBLE_UTILS_IS_INSTALLED = False +else: + ANSIBLE_UTILS_IS_INSTALLED = True +from ansible.errors import AnsibleActionFail +from ansible_collections.cisco.meraki.plugins.plugin_utils.meraki import ( + MERAKI, + meraki_argument_spec, +) + +# Get common arguments specification +argument_spec = meraki_argument_spec() +# Add arguments specific for this module +argument_spec.update(dict( + organizationId=dict(type="str"), + networkIds=dict(type="list"), + serials=dict(type="list"), + perPage=dict(type="int"), + total_pages=dict(type="int"), + direction=dict(type="str"), + startingAfter=dict(type="str"), + endingBefore=dict(type="str"), + t0=dict(type="str"), + t1=dict(type="str"), + timespan=dict(type="float"), + interval=dict(type="int"), +)) + +required_if = [] +required_one_of = [] +mutually_exclusive = [] +required_together = [] + + +class ActionModule(ActionBase): + def __init__(self, *args, **kwargs): + if not ANSIBLE_UTILS_IS_INSTALLED: + raise AnsibleActionFail( + "ansible.utils is not installed. Execute 'ansible-galaxy collection install ansible.utils'") + super(ActionModule, self).__init__(*args, **kwargs) + self._supports_async = False + self._supports_check_mode = True + self._result = None + + # Checks the supplied parameters against the argument spec for this module + def _check_argspec(self): + aav = AnsibleArgSpecValidator( + data=self._task.args, + schema=dict(argument_spec=argument_spec), + schema_format="argspec", + schema_conditionals=dict( + required_if=required_if, + required_one_of=required_one_of, + mutually_exclusive=mutually_exclusive, + required_together=required_together, + ), + name=self._task.action, + ) + valid, errors, self._task.args = aav.validate() + if not valid: + raise AnsibleActionFail(errors) + + def get_all(self, params): + new_object = {} + if params.get("organizationId") is not None: + new_object["organizationId"] = params.get( + "organizationId") + if params.get("networkIds") is not None: + new_object["networkIds"] = params.get( + "networkIds") + if params.get("serials") is not None: + new_object["serials"] = params.get( + "serials") + if params.get("perPage") is not None: + new_object["perPage"] = params.get( + "perPage") + new_object['total_pages'] = params.get( + "total_pages") or 1 + new_object['direction'] = params.get( + "direction") or "next" + if params.get("startingAfter") is not None: + new_object["startingAfter"] = params.get( + "startingAfter") + if params.get("endingBefore") is not None: + new_object["endingBefore"] = params.get( + "endingBefore") + if params.get("t0") is not None: + new_object["t0"] = params.get( + "t0") + if params.get("t1") is not None: + new_object["t1"] = params.get( + "t1") + if params.get("timespan") is not None: + new_object["timespan"] = params.get( + "timespan") + if params.get("interval") is not None: + new_object["interval"] = params.get( + "interval") + + return new_object + + def run(self, tmp=None, task_vars=None): + self._task.diff = False + self._result = super(ActionModule, self).run(tmp, task_vars) + self._result["changed"] = False + self._check_argspec() + + self._result.update(dict(meraki_response={})) + + meraki = MERAKI(params=self._task.args) + + response = meraki.exec_meraki( + family="wireless", + function='getOrganizationWirelessDevicesChannelUtilizationHistoryByDeviceByInterval', + params=self.get_all(self._task.args), + ) + self._result.update(dict(meraki_response=response)) + self._result.update(meraki.exit_json()) + return self._result diff --git a/ansible_collections/cisco/meraki/plugins/action/organizations_wireless_devices_channel_utilization_history_by_network_by_interval_info.py b/ansible_collections/cisco/meraki/plugins/action/organizations_wireless_devices_channel_utilization_history_by_network_by_interval_info.py new file mode 100644 index 000000000..872cc59be --- /dev/null +++ b/ansible_collections/cisco/meraki/plugins/action/organizations_wireless_devices_channel_utilization_history_by_network_by_interval_info.py @@ -0,0 +1,132 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +# Copyright (c) 2021, Cisco Systems +# 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 +from ansible.plugins.action import ActionBase +try: + from ansible_collections.ansible.utils.plugins.module_utils.common.argspec_validate import ( + AnsibleArgSpecValidator, + ) +except ImportError: + ANSIBLE_UTILS_IS_INSTALLED = False +else: + ANSIBLE_UTILS_IS_INSTALLED = True +from ansible.errors import AnsibleActionFail +from ansible_collections.cisco.meraki.plugins.plugin_utils.meraki import ( + MERAKI, + meraki_argument_spec, +) + +# Get common arguments specification +argument_spec = meraki_argument_spec() +# Add arguments specific for this module +argument_spec.update(dict( + organizationId=dict(type="str"), + networkIds=dict(type="list"), + serials=dict(type="list"), + perPage=dict(type="int"), + total_pages=dict(type="int"), + direction=dict(type="str"), + startingAfter=dict(type="str"), + endingBefore=dict(type="str"), + t0=dict(type="str"), + t1=dict(type="str"), + timespan=dict(type="float"), + interval=dict(type="int"), +)) + +required_if = [] +required_one_of = [] +mutually_exclusive = [] +required_together = [] + + +class ActionModule(ActionBase): + def __init__(self, *args, **kwargs): + if not ANSIBLE_UTILS_IS_INSTALLED: + raise AnsibleActionFail( + "ansible.utils is not installed. Execute 'ansible-galaxy collection install ansible.utils'") + super(ActionModule, self).__init__(*args, **kwargs) + self._supports_async = False + self._supports_check_mode = True + self._result = None + + # Checks the supplied parameters against the argument spec for this module + def _check_argspec(self): + aav = AnsibleArgSpecValidator( + data=self._task.args, + schema=dict(argument_spec=argument_spec), + schema_format="argspec", + schema_conditionals=dict( + required_if=required_if, + required_one_of=required_one_of, + mutually_exclusive=mutually_exclusive, + required_together=required_together, + ), + name=self._task.action, + ) + valid, errors, self._task.args = aav.validate() + if not valid: + raise AnsibleActionFail(errors) + + def get_all(self, params): + new_object = {} + if params.get("organizationId") is not None: + new_object["organizationId"] = params.get( + "organizationId") + if params.get("networkIds") is not None: + new_object["networkIds"] = params.get( + "networkIds") + if params.get("serials") is not None: + new_object["serials"] = params.get( + "serials") + if params.get("perPage") is not None: + new_object["perPage"] = params.get( + "perPage") + new_object['total_pages'] = params.get( + "total_pages") or 1 + new_object['direction'] = params.get( + "direction") or "next" + if params.get("startingAfter") is not None: + new_object["startingAfter"] = params.get( + "startingAfter") + if params.get("endingBefore") is not None: + new_object["endingBefore"] = params.get( + "endingBefore") + if params.get("t0") is not None: + new_object["t0"] = params.get( + "t0") + if params.get("t1") is not None: + new_object["t1"] = params.get( + "t1") + if params.get("timespan") is not None: + new_object["timespan"] = params.get( + "timespan") + if params.get("interval") is not None: + new_object["interval"] = params.get( + "interval") + + return new_object + + def run(self, tmp=None, task_vars=None): + self._task.diff = False + self._result = super(ActionModule, self).run(tmp, task_vars) + self._result["changed"] = False + self._check_argspec() + + self._result.update(dict(meraki_response={})) + + meraki = MERAKI(params=self._task.args) + + response = meraki.exec_meraki( + family="wireless", + function='getOrganizationWirelessDevicesChannelUtilizationHistoryByNetworkByInterval', + params=self.get_all(self._task.args), + ) + self._result.update(dict(meraki_response=response)) + self._result.update(meraki.exit_json()) + return self._result diff --git a/ansible_collections/cisco/meraki/plugins/action/organizations_wireless_devices_packet_loss_by_client_info.py b/ansible_collections/cisco/meraki/plugins/action/organizations_wireless_devices_packet_loss_by_client_info.py new file mode 100644 index 000000000..772ffac1a --- /dev/null +++ b/ansible_collections/cisco/meraki/plugins/action/organizations_wireless_devices_packet_loss_by_client_info.py @@ -0,0 +1,136 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +# Copyright (c) 2021, Cisco Systems +# 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 +from ansible.plugins.action import ActionBase +try: + from ansible_collections.ansible.utils.plugins.module_utils.common.argspec_validate import ( + AnsibleArgSpecValidator, + ) +except ImportError: + ANSIBLE_UTILS_IS_INSTALLED = False +else: + ANSIBLE_UTILS_IS_INSTALLED = True +from ansible.errors import AnsibleActionFail +from ansible_collections.cisco.meraki.plugins.plugin_utils.meraki import ( + MERAKI, + meraki_argument_spec, +) + +# Get common arguments specification +argument_spec = meraki_argument_spec() +# Add arguments specific for this module +argument_spec.update(dict( + organizationId=dict(type="str"), + networkIds=dict(type="list"), + ssids=dict(type="list"), + bands=dict(type="list"), + macs=dict(type="list"), + perPage=dict(type="int"), + total_pages=dict(type="int"), + direction=dict(type="str"), + startingAfter=dict(type="str"), + endingBefore=dict(type="str"), + t0=dict(type="str"), + t1=dict(type="str"), + timespan=dict(type="float"), +)) + +required_if = [] +required_one_of = [] +mutually_exclusive = [] +required_together = [] + + +class ActionModule(ActionBase): + def __init__(self, *args, **kwargs): + if not ANSIBLE_UTILS_IS_INSTALLED: + raise AnsibleActionFail( + "ansible.utils is not installed. Execute 'ansible-galaxy collection install ansible.utils'") + super(ActionModule, self).__init__(*args, **kwargs) + self._supports_async = False + self._supports_check_mode = True + self._result = None + + # Checks the supplied parameters against the argument spec for this module + def _check_argspec(self): + aav = AnsibleArgSpecValidator( + data=self._task.args, + schema=dict(argument_spec=argument_spec), + schema_format="argspec", + schema_conditionals=dict( + required_if=required_if, + required_one_of=required_one_of, + mutually_exclusive=mutually_exclusive, + required_together=required_together, + ), + name=self._task.action, + ) + valid, errors, self._task.args = aav.validate() + if not valid: + raise AnsibleActionFail(errors) + + def get_all(self, params): + new_object = {} + if params.get("organizationId") is not None: + new_object["organizationId"] = params.get( + "organizationId") + if params.get("networkIds") is not None: + new_object["networkIds"] = params.get( + "networkIds") + if params.get("ssids") is not None: + new_object["ssids"] = params.get( + "ssids") + if params.get("bands") is not None: + new_object["bands"] = params.get( + "bands") + if params.get("macs") is not None: + new_object["macs"] = params.get( + "macs") + if params.get("perPage") is not None: + new_object["perPage"] = params.get( + "perPage") + new_object['total_pages'] = params.get( + "total_pages") or 1 + new_object['direction'] = params.get( + "direction") or "next" + if params.get("startingAfter") is not None: + new_object["startingAfter"] = params.get( + "startingAfter") + if params.get("endingBefore") is not None: + new_object["endingBefore"] = params.get( + "endingBefore") + if params.get("t0") is not None: + new_object["t0"] = params.get( + "t0") + if params.get("t1") is not None: + new_object["t1"] = params.get( + "t1") + if params.get("timespan") is not None: + new_object["timespan"] = params.get( + "timespan") + + return new_object + + def run(self, tmp=None, task_vars=None): + self._task.diff = False + self._result = super(ActionModule, self).run(tmp, task_vars) + self._result["changed"] = False + self._check_argspec() + + self._result.update(dict(meraki_response={})) + + meraki = MERAKI(params=self._task.args) + + response = meraki.exec_meraki( + family="wireless", + function='getOrganizationWirelessDevicesPacketLossByClient', + params=self.get_all(self._task.args), + ) + self._result.update(dict(meraki_response=response)) + self._result.update(meraki.exit_json()) + return self._result diff --git a/ansible_collections/cisco/meraki/plugins/action/organizations_wireless_devices_packet_loss_by_device_info.py b/ansible_collections/cisco/meraki/plugins/action/organizations_wireless_devices_packet_loss_by_device_info.py new file mode 100644 index 000000000..beef87f14 --- /dev/null +++ b/ansible_collections/cisco/meraki/plugins/action/organizations_wireless_devices_packet_loss_by_device_info.py @@ -0,0 +1,136 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +# Copyright (c) 2021, Cisco Systems +# 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 +from ansible.plugins.action import ActionBase +try: + from ansible_collections.ansible.utils.plugins.module_utils.common.argspec_validate import ( + AnsibleArgSpecValidator, + ) +except ImportError: + ANSIBLE_UTILS_IS_INSTALLED = False +else: + ANSIBLE_UTILS_IS_INSTALLED = True +from ansible.errors import AnsibleActionFail +from ansible_collections.cisco.meraki.plugins.plugin_utils.meraki import ( + MERAKI, + meraki_argument_spec, +) + +# Get common arguments specification +argument_spec = meraki_argument_spec() +# Add arguments specific for this module +argument_spec.update(dict( + organizationId=dict(type="str"), + networkIds=dict(type="list"), + serials=dict(type="list"), + ssids=dict(type="list"), + bands=dict(type="list"), + perPage=dict(type="int"), + total_pages=dict(type="int"), + direction=dict(type="str"), + startingAfter=dict(type="str"), + endingBefore=dict(type="str"), + t0=dict(type="str"), + t1=dict(type="str"), + timespan=dict(type="float"), +)) + +required_if = [] +required_one_of = [] +mutually_exclusive = [] +required_together = [] + + +class ActionModule(ActionBase): + def __init__(self, *args, **kwargs): + if not ANSIBLE_UTILS_IS_INSTALLED: + raise AnsibleActionFail( + "ansible.utils is not installed. Execute 'ansible-galaxy collection install ansible.utils'") + super(ActionModule, self).__init__(*args, **kwargs) + self._supports_async = False + self._supports_check_mode = True + self._result = None + + # Checks the supplied parameters against the argument spec for this module + def _check_argspec(self): + aav = AnsibleArgSpecValidator( + data=self._task.args, + schema=dict(argument_spec=argument_spec), + schema_format="argspec", + schema_conditionals=dict( + required_if=required_if, + required_one_of=required_one_of, + mutually_exclusive=mutually_exclusive, + required_together=required_together, + ), + name=self._task.action, + ) + valid, errors, self._task.args = aav.validate() + if not valid: + raise AnsibleActionFail(errors) + + def get_all(self, params): + new_object = {} + if params.get("organizationId") is not None: + new_object["organizationId"] = params.get( + "organizationId") + if params.get("networkIds") is not None: + new_object["networkIds"] = params.get( + "networkIds") + if params.get("serials") is not None: + new_object["serials"] = params.get( + "serials") + if params.get("ssids") is not None: + new_object["ssids"] = params.get( + "ssids") + if params.get("bands") is not None: + new_object["bands"] = params.get( + "bands") + if params.get("perPage") is not None: + new_object["perPage"] = params.get( + "perPage") + new_object['total_pages'] = params.get( + "total_pages") or 1 + new_object['direction'] = params.get( + "direction") or "next" + if params.get("startingAfter") is not None: + new_object["startingAfter"] = params.get( + "startingAfter") + if params.get("endingBefore") is not None: + new_object["endingBefore"] = params.get( + "endingBefore") + if params.get("t0") is not None: + new_object["t0"] = params.get( + "t0") + if params.get("t1") is not None: + new_object["t1"] = params.get( + "t1") + if params.get("timespan") is not None: + new_object["timespan"] = params.get( + "timespan") + + return new_object + + def run(self, tmp=None, task_vars=None): + self._task.diff = False + self._result = super(ActionModule, self).run(tmp, task_vars) + self._result["changed"] = False + self._check_argspec() + + self._result.update(dict(meraki_response={})) + + meraki = MERAKI(params=self._task.args) + + response = meraki.exec_meraki( + family="wireless", + function='getOrganizationWirelessDevicesPacketLossByDevice', + params=self.get_all(self._task.args), + ) + self._result.update(dict(meraki_response=response)) + self._result.update(meraki.exit_json()) + return self._result diff --git a/ansible_collections/cisco/meraki/plugins/action/organizations_wireless_devices_packet_loss_by_network_info.py b/ansible_collections/cisco/meraki/plugins/action/organizations_wireless_devices_packet_loss_by_network_info.py new file mode 100644 index 000000000..b871a3539 --- /dev/null +++ b/ansible_collections/cisco/meraki/plugins/action/organizations_wireless_devices_packet_loss_by_network_info.py @@ -0,0 +1,136 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +# Copyright (c) 2021, Cisco Systems +# 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 +from ansible.plugins.action import ActionBase +try: + from ansible_collections.ansible.utils.plugins.module_utils.common.argspec_validate import ( + AnsibleArgSpecValidator, + ) +except ImportError: + ANSIBLE_UTILS_IS_INSTALLED = False +else: + ANSIBLE_UTILS_IS_INSTALLED = True +from ansible.errors import AnsibleActionFail +from ansible_collections.cisco.meraki.plugins.plugin_utils.meraki import ( + MERAKI, + meraki_argument_spec, +) + +# Get common arguments specification +argument_spec = meraki_argument_spec() +# Add arguments specific for this module +argument_spec.update(dict( + organizationId=dict(type="str"), + networkIds=dict(type="list"), + serials=dict(type="list"), + ssids=dict(type="list"), + bands=dict(type="list"), + perPage=dict(type="int"), + total_pages=dict(type="int"), + direction=dict(type="str"), + startingAfter=dict(type="str"), + endingBefore=dict(type="str"), + t0=dict(type="str"), + t1=dict(type="str"), + timespan=dict(type="float"), +)) + +required_if = [] +required_one_of = [] +mutually_exclusive = [] +required_together = [] + + +class ActionModule(ActionBase): + def __init__(self, *args, **kwargs): + if not ANSIBLE_UTILS_IS_INSTALLED: + raise AnsibleActionFail( + "ansible.utils is not installed. Execute 'ansible-galaxy collection install ansible.utils'") + super(ActionModule, self).__init__(*args, **kwargs) + self._supports_async = False + self._supports_check_mode = True + self._result = None + + # Checks the supplied parameters against the argument spec for this module + def _check_argspec(self): + aav = AnsibleArgSpecValidator( + data=self._task.args, + schema=dict(argument_spec=argument_spec), + schema_format="argspec", + schema_conditionals=dict( + required_if=required_if, + required_one_of=required_one_of, + mutually_exclusive=mutually_exclusive, + required_together=required_together, + ), + name=self._task.action, + ) + valid, errors, self._task.args = aav.validate() + if not valid: + raise AnsibleActionFail(errors) + + def get_all(self, params): + new_object = {} + if params.get("organizationId") is not None: + new_object["organizationId"] = params.get( + "organizationId") + if params.get("networkIds") is not None: + new_object["networkIds"] = params.get( + "networkIds") + if params.get("serials") is not None: + new_object["serials"] = params.get( + "serials") + if params.get("ssids") is not None: + new_object["ssids"] = params.get( + "ssids") + if params.get("bands") is not None: + new_object["bands"] = params.get( + "bands") + if params.get("perPage") is not None: + new_object["perPage"] = params.get( + "perPage") + new_object['total_pages'] = params.get( + "total_pages") or 1 + new_object['direction'] = params.get( + "direction") or "next" + if params.get("startingAfter") is not None: + new_object["startingAfter"] = params.get( + "startingAfter") + if params.get("endingBefore") is not None: + new_object["endingBefore"] = params.get( + "endingBefore") + if params.get("t0") is not None: + new_object["t0"] = params.get( + "t0") + if params.get("t1") is not None: + new_object["t1"] = params.get( + "t1") + if params.get("timespan") is not None: + new_object["timespan"] = params.get( + "timespan") + + return new_object + + def run(self, tmp=None, task_vars=None): + self._task.diff = False + self._result = super(ActionModule, self).run(tmp, task_vars) + self._result["changed"] = False + self._check_argspec() + + self._result.update(dict(meraki_response={})) + + meraki = MERAKI(params=self._task.args) + + response = meraki.exec_meraki( + family="wireless", + function='getOrganizationWirelessDevicesPacketLossByNetwork', + params=self.get_all(self._task.args), + ) + self._result.update(dict(meraki_response=response)) + self._result.update(meraki.exit_json()) + return self._result diff --git a/ansible_collections/cisco/meraki/plugins/modules/administered_identities_me_info.py b/ansible_collections/cisco/meraki/plugins/modules/administered_identities_me_info.py index 05a8f14d8..7f833e0d8 100644 --- a/ansible_collections/cisco/meraki/plugins/modules/administered_identities_me_info.py +++ b/ansible_collections/cisco/meraki/plugins/modules/administered_identities_me_info.py @@ -67,22 +67,22 @@ meraki_response: type: dict sample: > { - "name": "string", - "email": "string", - "lastUsedDashboardAt": "string", "authentication": { - "mode": "string", "api": { "key": { "created": true } }, - "twoFactor": { + "mode": "string", + "saml": { "enabled": true }, - "saml": { + "twoFactor": { "enabled": true } - } + }, + "email": "string", + "lastUsedDashboardAt": "string", + "name": "string" } """ diff --git a/ansible_collections/cisco/meraki/plugins/modules/administered_licensing_subscription_entitlements_info.py b/ansible_collections/cisco/meraki/plugins/modules/administered_licensing_subscription_entitlements_info.py new file mode 100644 index 000000000..64b91eae9 --- /dev/null +++ b/ansible_collections/cisco/meraki/plugins/modules/administered_licensing_subscription_entitlements_info.py @@ -0,0 +1,83 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- + +# Copyright (c) 2021, Cisco Systems +# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) + +DOCUMENTATION = r""" +--- +module: administered_licensing_subscription_entitlements_info +short_description: Information module for administered _licensing _subscription _entitlements +description: +- Get all administered _licensing _subscription _entitlements. +- Retrieve the list of purchasable entitlements. +version_added: '2.18.0' +extends_documentation_fragment: + - cisco.meraki.module_info +author: Francisco Munoz (@fmunoz) +options: + headers: + description: Additional headers. + type: dict + skus: + description: + - Skus query parameter. Filter to entitlements with the specified SKUs. + elements: str + type: list +requirements: +- meraki >= 2.4.9 +- python >= 3.5 +seealso: +- name: Cisco Meraki documentation for licensing getAdministeredLicensingSubscriptionEntitlements + description: Complete reference of the getAdministeredLicensingSubscriptionEntitlements API. + link: https://developer.cisco.com/meraki/api-v1/#!get-administered-licensing-subscription-entitlements +notes: + - SDK Method used are + licensing.Licensing.get_administered_licensing_subscription_entitlements, + + - Paths used are + get /administered/licensing/subscription/entitlements, +""" + +EXAMPLES = r""" +- name: Get all administered _licensing _subscription _entitlements + cisco.meraki.administered_licensing_subscription_entitlements_info: + meraki_api_key: "{{meraki_api_key}}" + meraki_base_url: "{{meraki_base_url}}" + meraki_single_request_timeout: "{{meraki_single_request_timeout}}" + meraki_certificate_path: "{{meraki_certificate_path}}" + meraki_requests_proxy: "{{meraki_requests_proxy}}" + meraki_wait_on_rate_limit: "{{meraki_wait_on_rate_limit}}" + meraki_nginx_429_retry_wait_time: "{{meraki_nginx_429_retry_wait_time}}" + meraki_action_batch_retry_wait_time: "{{meraki_action_batch_retry_wait_time}}" + meraki_retry_4xx_error: "{{meraki_retry_4xx_error}}" + meraki_retry_4xx_error_wait_time: "{{meraki_retry_4xx_error_wait_time}}" + meraki_maximum_retries: "{{meraki_maximum_retries}}" + meraki_output_log: "{{meraki_output_log}}" + meraki_log_file_prefix: "{{meraki_log_file_prefix}}" + meraki_log_path: "{{meraki_log_path}}" + meraki_print_console: "{{meraki_print_console}}" + meraki_suppress_logging: "{{meraki_suppress_logging}}" + meraki_simulate: "{{meraki_simulate}}" + meraki_be_geo_id: "{{meraki_be_geo_id}}" + meraki_use_iterator_for_get_pages: "{{meraki_use_iterator_for_get_pages}}" + meraki_inherit_logging_config: "{{meraki_inherit_logging_config}}" + skus: [] + register: result + +""" +RETURN = r""" +meraki_response: + description: A dictionary or list with the response returned by the Cisco Meraki Python SDK + returned: always + type: dict + sample: > + { + "featureTier": "string", + "isAddOn": true, + "name": "string", + "productClass": "string", + "productType": "string", + "sku": "string" + } +""" diff --git a/ansible_collections/cisco/meraki/plugins/modules/administered_licensing_subscription_subscriptions_bind.py b/ansible_collections/cisco/meraki/plugins/modules/administered_licensing_subscription_subscriptions_bind.py new file mode 100644 index 000000000..7ab09dfcf --- /dev/null +++ b/ansible_collections/cisco/meraki/plugins/modules/administered_licensing_subscription_subscriptions_bind.py @@ -0,0 +1,95 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- + +# Copyright (c) 2021, Cisco Systems +# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) + +DOCUMENTATION = r""" +--- +module: administered_licensing_subscription_subscriptions_bind +short_description: Resource module for administered _licensing _subscription _subscriptions _bind +description: +- Manage operation create of the resource administered _licensing _subscription _subscriptions _bind. +- Bind networks to a subscription. +version_added: '2.18.0' +extends_documentation_fragment: + - cisco.meraki.module +author: Francisco Munoz (@fmunoz) +options: + networkIds: + description: List of network ids to bind to the subscription. + elements: str + type: list + subscriptionId: + description: SubscriptionId path parameter. Subscription ID. + type: str +requirements: +- meraki >= 2.4.9 +- python >= 3.5 +seealso: +- name: Cisco Meraki documentation for licensing bindAdministeredLicensingSubscriptionSubscription + description: Complete reference of the bindAdministeredLicensingSubscriptionSubscription API. + link: https://developer.cisco.com/meraki/api-v1/#!bind-administered-licensing-subscription-subscription +notes: + - SDK Method used are + licensing.Licensing.bind_administered_licensing_subscription_subscription, + + - Paths used are + post /administered/licensing/subscription/subscriptions/{subscriptionId}/bind, +""" + +EXAMPLES = r""" +- name: Create + cisco.meraki.administered_licensing_subscription_subscriptions_bind: + meraki_api_key: "{{meraki_api_key}}" + meraki_base_url: "{{meraki_base_url}}" + meraki_single_request_timeout: "{{meraki_single_request_timeout}}" + meraki_certificate_path: "{{meraki_certificate_path}}" + meraki_requests_proxy: "{{meraki_requests_proxy}}" + meraki_wait_on_rate_limit: "{{meraki_wait_on_rate_limit}}" + meraki_nginx_429_retry_wait_time: "{{meraki_nginx_429_retry_wait_time}}" + meraki_action_batch_retry_wait_time: "{{meraki_action_batch_retry_wait_time}}" + meraki_retry_4xx_error: "{{meraki_retry_4xx_error}}" + meraki_retry_4xx_error_wait_time: "{{meraki_retry_4xx_error_wait_time}}" + meraki_maximum_retries: "{{meraki_maximum_retries}}" + meraki_output_log: "{{meraki_output_log}}" + meraki_log_file_prefix: "{{meraki_log_file_prefix}}" + meraki_log_path: "{{meraki_log_path}}" + meraki_print_console: "{{meraki_print_console}}" + meraki_suppress_logging: "{{meraki_suppress_logging}}" + meraki_simulate: "{{meraki_simulate}}" + meraki_be_geo_id: "{{meraki_be_geo_id}}" + meraki_use_iterator_for_get_pages: "{{meraki_use_iterator_for_get_pages}}" + meraki_inherit_logging_config: "{{meraki_inherit_logging_config}}" + networkIds: + - L_1234 + - N_5678 + subscriptionId: string + validate: true + +""" +RETURN = r""" +meraki_response: + description: A dictionary or list with the response returned by the Cisco Meraki Python SDK + returned: always + type: dict + sample: > + { + "errors": [ + "string" + ], + "insufficientEntitlements": [ + { + "quantity": 0, + "sku": "string" + } + ], + "networks": [ + { + "id": "string", + "name": "string" + } + ], + "subscriptionId": "string" + } +""" diff --git a/ansible_collections/cisco/meraki/plugins/modules/administered_licensing_subscription_subscriptions_claim.py b/ansible_collections/cisco/meraki/plugins/modules/administered_licensing_subscription_subscriptions_claim.py new file mode 100644 index 000000000..9049fb0f2 --- /dev/null +++ b/ansible_collections/cisco/meraki/plugins/modules/administered_licensing_subscription_subscriptions_claim.py @@ -0,0 +1,112 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- + +# Copyright (c) 2021, Cisco Systems +# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) + +DOCUMENTATION = r""" +--- +module: administered_licensing_subscription_subscriptions_claim +short_description: Resource module for administered _licensing _subscription _subscriptions _claim +description: +- Manage operation create of the resource administered _licensing _subscription _subscriptions _claim. +- Claim a subscription into an organization. +version_added: '2.18.0' +extends_documentation_fragment: + - cisco.meraki.module +author: Francisco Munoz (@fmunoz) +options: + claimKey: + description: The subscription's claim key. + type: str + description: + description: Extra details or notes about the subscription. + type: str + name: + description: Friendly name to identify the subscription. + type: str + organizationId: + description: The id of the organization claiming the subscription. + type: str +requirements: +- meraki >= 2.4.9 +- python >= 3.5 +seealso: +- name: Cisco Meraki documentation for licensing claimAdministeredLicensingSubscriptionSubscriptions + description: Complete reference of the claimAdministeredLicensingSubscriptionSubscriptions API. + link: https://developer.cisco.com/meraki/api-v1/#!claim-administered-licensing-subscription-subscriptions +notes: + - SDK Method used are + licensing.Licensing.claim_administered_licensing_subscription_subscriptions, + + - Paths used are + post /administered/licensing/subscription/subscriptions/claim, +""" + +EXAMPLES = r""" +- name: Create + cisco.meraki.administered_licensing_subscription_subscriptions_claim: + meraki_api_key: "{{meraki_api_key}}" + meraki_base_url: "{{meraki_base_url}}" + meraki_single_request_timeout: "{{meraki_single_request_timeout}}" + meraki_certificate_path: "{{meraki_certificate_path}}" + meraki_requests_proxy: "{{meraki_requests_proxy}}" + meraki_wait_on_rate_limit: "{{meraki_wait_on_rate_limit}}" + meraki_nginx_429_retry_wait_time: "{{meraki_nginx_429_retry_wait_time}}" + meraki_action_batch_retry_wait_time: "{{meraki_action_batch_retry_wait_time}}" + meraki_retry_4xx_error: "{{meraki_retry_4xx_error}}" + meraki_retry_4xx_error_wait_time: "{{meraki_retry_4xx_error_wait_time}}" + meraki_maximum_retries: "{{meraki_maximum_retries}}" + meraki_output_log: "{{meraki_output_log}}" + meraki_log_file_prefix: "{{meraki_log_file_prefix}}" + meraki_log_path: "{{meraki_log_path}}" + meraki_print_console: "{{meraki_print_console}}" + meraki_suppress_logging: "{{meraki_suppress_logging}}" + meraki_simulate: "{{meraki_simulate}}" + meraki_be_geo_id: "{{meraki_be_geo_id}}" + meraki_use_iterator_for_get_pages: "{{meraki_use_iterator_for_get_pages}}" + meraki_inherit_logging_config: "{{meraki_inherit_logging_config}}" + claimKey: S2345-6789A-BCDEF-GHJKM + description: Subscription for all main offices + name: Corporate subscription + organizationId: '12345678910' + validate: true + +""" +RETURN = r""" +meraki_response: + description: A dictionary or list with the response returned by the Cisco Meraki Python SDK + returned: always + type: dict + sample: > + { + "counts": { + "networks": 0, + "seats": { + "assigned": 0, + "available": 0, + "limit": 0 + } + }, + "description": "string", + "endDate": "string", + "entitlements": [ + { + "seats": { + "assigned": 0, + "available": 0, + "limit": 0 + }, + "sku": "string" + } + ], + "name": "string", + "productTypes": [ + "string" + ], + "startDate": "string", + "status": "string", + "subscriptionId": "string", + "webOrderId": "string" + } +""" diff --git a/ansible_collections/cisco/meraki/plugins/modules/administered_licensing_subscription_subscriptions_claim_key_validate.py b/ansible_collections/cisco/meraki/plugins/modules/administered_licensing_subscription_subscriptions_claim_key_validate.py new file mode 100644 index 000000000..578a9603c --- /dev/null +++ b/ansible_collections/cisco/meraki/plugins/modules/administered_licensing_subscription_subscriptions_claim_key_validate.py @@ -0,0 +1,99 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- + +# Copyright (c) 2021, Cisco Systems +# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) + +DOCUMENTATION = r""" +--- +module: administered_licensing_subscription_subscriptions_claim_key_validate +short_description: Resource module for administered _licensing _subscription _subscriptions _claimkey _validate +description: +- Manage operation create of the resource administered _licensing _subscription _subscriptions _claimkey _validate. +- Find a subscription by claim key. Returns 400 if the key has already been claimed. +version_added: '2.18.0' +extends_documentation_fragment: + - cisco.meraki.module +author: Francisco Munoz (@fmunoz) +options: + claimKey: + description: The subscription's claim key. + type: str +requirements: +- meraki >= 2.4.9 +- python >= 3.5 +seealso: +- name: Cisco Meraki documentation for licensing validateAdministeredLicensingSubscriptionSubscriptionsClaimKey + description: Complete reference of the validateAdministeredLicensingSubscriptionSubscriptionsClaimKey API. + link: https://developer.cisco.com/meraki/api-v1/#!validate-administered-licensing-subscription-subscriptions-claim-key +notes: + - SDK Method used are + licensing.Licensing.validate_administered_licensing_subscription_subscriptions_claim_key, + + - Paths used are + post /administered/licensing/subscription/subscriptions/claimKey/validate, +""" + +EXAMPLES = r""" +- name: Create + cisco.meraki.administered_licensing_subscription_subscriptions_claim_key_validate: + meraki_api_key: "{{meraki_api_key}}" + meraki_base_url: "{{meraki_base_url}}" + meraki_single_request_timeout: "{{meraki_single_request_timeout}}" + meraki_certificate_path: "{{meraki_certificate_path}}" + meraki_requests_proxy: "{{meraki_requests_proxy}}" + meraki_wait_on_rate_limit: "{{meraki_wait_on_rate_limit}}" + meraki_nginx_429_retry_wait_time: "{{meraki_nginx_429_retry_wait_time}}" + meraki_action_batch_retry_wait_time: "{{meraki_action_batch_retry_wait_time}}" + meraki_retry_4xx_error: "{{meraki_retry_4xx_error}}" + meraki_retry_4xx_error_wait_time: "{{meraki_retry_4xx_error_wait_time}}" + meraki_maximum_retries: "{{meraki_maximum_retries}}" + meraki_output_log: "{{meraki_output_log}}" + meraki_log_file_prefix: "{{meraki_log_file_prefix}}" + meraki_log_path: "{{meraki_log_path}}" + meraki_print_console: "{{meraki_print_console}}" + meraki_suppress_logging: "{{meraki_suppress_logging}}" + meraki_simulate: "{{meraki_simulate}}" + meraki_be_geo_id: "{{meraki_be_geo_id}}" + meraki_use_iterator_for_get_pages: "{{meraki_use_iterator_for_get_pages}}" + meraki_inherit_logging_config: "{{meraki_inherit_logging_config}}" + claimKey: S2345-6789A-BCDEF-GHJKM + +""" +RETURN = r""" +meraki_response: + description: A dictionary or list with the response returned by the Cisco Meraki Python SDK + returned: always + type: dict + sample: > + { + "counts": { + "networks": 0, + "seats": { + "assigned": 0, + "available": 0, + "limit": 0 + } + }, + "description": "string", + "endDate": "string", + "entitlements": [ + { + "seats": { + "assigned": 0, + "available": 0, + "limit": 0 + }, + "sku": "string" + } + ], + "name": "string", + "productTypes": [ + "string" + ], + "startDate": "string", + "status": "string", + "subscriptionId": "string", + "webOrderId": "string" + } +""" diff --git a/ansible_collections/cisco/meraki/plugins/modules/administered_licensing_subscription_subscriptions_compliance_statuses_info.py b/ansible_collections/cisco/meraki/plugins/modules/administered_licensing_subscription_subscriptions_compliance_statuses_info.py new file mode 100644 index 000000000..08c0dfca8 --- /dev/null +++ b/ansible_collections/cisco/meraki/plugins/modules/administered_licensing_subscription_subscriptions_compliance_statuses_info.py @@ -0,0 +1,107 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- + +# Copyright (c) 2021, Cisco Systems +# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) + +DOCUMENTATION = r""" +--- +module: administered_licensing_subscription_subscriptions_compliance_statuses_info +short_description: Information module for administered _licensing _subscription _subscriptions _compliance _statuses +description: +- Get all administered _licensing _subscription _subscriptions _compliance _statuses. +- Get compliance status for requested subscriptions. +version_added: '2.18.0' +extends_documentation_fragment: + - cisco.meraki.module_info +author: Francisco Munoz (@fmunoz) +options: + headers: + description: Additional headers. + type: dict + organizationIds: + description: + - OrganizationIds query parameter. Organizations to get subscription compliance information for. + elements: str + type: list + subscriptionIds: + description: + - SubscriptionIds query parameter. Subscription ids. + elements: str + type: list +requirements: +- meraki >= 2.4.9 +- python >= 3.5 +seealso: +- name: Cisco Meraki documentation for licensing getAdministeredLicensingSubscriptionSubscriptionsComplianceStatuses + description: Complete reference of the getAdministeredLicensingSubscriptionSubscriptionsComplianceStatuses API. + link: https://developer.cisco.com/meraki/api-v1/#!get-administered-licensing-subscription-subscriptions-compliance-statuses +notes: + - SDK Method used are + licensing.Licensing.get_administered_licensing_subscription_subscriptions_compliance_statuses, + + - Paths used are + get /administered/licensing/subscription/subscriptions/compliance/statuses, +""" + +EXAMPLES = r""" +- name: Get all administered _licensing _subscription _subscriptions _compliance _statuses + cisco.meraki.administered_licensing_subscription_subscriptions_compliance_statuses_info: + meraki_api_key: "{{meraki_api_key}}" + meraki_base_url: "{{meraki_base_url}}" + meraki_single_request_timeout: "{{meraki_single_request_timeout}}" + meraki_certificate_path: "{{meraki_certificate_path}}" + meraki_requests_proxy: "{{meraki_requests_proxy}}" + meraki_wait_on_rate_limit: "{{meraki_wait_on_rate_limit}}" + meraki_nginx_429_retry_wait_time: "{{meraki_nginx_429_retry_wait_time}}" + meraki_action_batch_retry_wait_time: "{{meraki_action_batch_retry_wait_time}}" + meraki_retry_4xx_error: "{{meraki_retry_4xx_error}}" + meraki_retry_4xx_error_wait_time: "{{meraki_retry_4xx_error_wait_time}}" + meraki_maximum_retries: "{{meraki_maximum_retries}}" + meraki_output_log: "{{meraki_output_log}}" + meraki_log_file_prefix: "{{meraki_log_file_prefix}}" + meraki_log_path: "{{meraki_log_path}}" + meraki_print_console: "{{meraki_print_console}}" + meraki_suppress_logging: "{{meraki_suppress_logging}}" + meraki_simulate: "{{meraki_simulate}}" + meraki_be_geo_id: "{{meraki_be_geo_id}}" + meraki_use_iterator_for_get_pages: "{{meraki_use_iterator_for_get_pages}}" + meraki_inherit_logging_config: "{{meraki_inherit_logging_config}}" + organizationIds: [] + subscriptionIds: [] + register: result + +""" +RETURN = r""" +meraki_response: + description: A dictionary or list with the response returned by the Cisco Meraki Python SDK + returned: always + type: list + elements: dict + sample: > + [ + { + "subscription": { + "id": "string", + "name": "string", + "status": "string" + }, + "violations": { + "byProductClass": [ + { + "gracePeriodEndsAt": "string", + "missing": { + "entitlements": [ + { + "quantity": 0, + "sku": "string" + } + ] + }, + "productClass": "string" + } + ] + } + } + ] +""" diff --git a/ansible_collections/cisco/meraki/plugins/modules/administered_licensing_subscription_subscriptions_info.py b/ansible_collections/cisco/meraki/plugins/modules/administered_licensing_subscription_subscriptions_info.py new file mode 100644 index 000000000..f60343cd7 --- /dev/null +++ b/ansible_collections/cisco/meraki/plugins/modules/administered_licensing_subscription_subscriptions_info.py @@ -0,0 +1,164 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- + +# Copyright (c) 2021, Cisco Systems +# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) + +DOCUMENTATION = r""" +--- +module: administered_licensing_subscription_subscriptions_info +short_description: Information module for administered _licensing _subscription _subscriptions +description: +- Get all administered _licensing _subscription _subscriptions. +- List available subscriptions. +version_added: '2.18.0' +extends_documentation_fragment: + - cisco.meraki.module_info + - cisco.meraki.module_info_pagination +author: Francisco Munoz (@fmunoz) +options: + headers: + description: Additional headers. + type: dict + perPage: + description: + - PerPage query parameter. The number of entries per page returned. Acceptable range is 3 - 1000. Default is 1000. + type: int + startingAfter: + description: + - > + StartingAfter query parameter. A token used by the server to indicate the start of the page. Often this is a + timestamp or an ID but it is not limited to those. This parameter should not be defined by client + applications. The link for the first, last, prev, or next page in the HTTP Link header should define it. + type: str + endingBefore: + description: + - > + EndingBefore query parameter. A token used by the server to indicate the end of the page. Often this is a + timestamp or an ID but it is not limited to those. This parameter should not be defined by client + applications. The link for the first, last, prev, or next page in the HTTP Link header should define it. + type: str + subscriptionIds: + description: + - SubscriptionIds query parameter. List of subscription ids to fetch. + elements: str + type: list + organizationIds: + description: + - OrganizationIds query parameter. Organizations to get associated subscriptions for. + elements: str + type: list + statuses: + description: + - Statuses query parameter. List of statuses that returned subscriptions can have. + elements: str + type: list + productTypes: + description: + - ProductTypes query parameter. List of product types that returned subscriptions need to have entitlements for. + elements: str + type: list + startDate: + description: + - > + StartDate query parameter. Filter subscriptions by start date, ISO 8601 format. To filter with a range of + dates, use 'startDate