diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-26 04:05:56 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-26 04:05:56 +0000 |
commit | 67c6a4d1dccb62159b9d9b2dea4e2f487446e276 (patch) | |
tree | 9ccbb35137f480bbbdb899accbda52a8135d3416 /ansible_collections/cisco/aci | |
parent | Adding upstream version 9.4.0+dfsg. (diff) | |
download | ansible-67c6a4d1dccb62159b9d9b2dea4e2f487446e276.tar.xz ansible-67c6a4d1dccb62159b9d9b2dea4e2f487446e276.zip |
Adding upstream version 9.5.1+dfsg.upstream/9.5.1+dfsg
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'ansible_collections/cisco/aci')
518 files changed, 51874 insertions, 4272 deletions
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 }, { @@ -176,10 +176,17 @@ "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 }, { @@ -218,24 +239,52 @@ "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 }, { @@ -316,31 +379,52 @@ "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 }, { @@ -372,6 +456,13 @@ "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", "chksum_type": "sha256", @@ -386,6 +477,13 @@ "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", "chksum_type": "sha256", @@ -393,6 +491,13 @@ "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", "chksum_type": "sha256", @@ -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 }, { @@ -449,6 +554,13 @@ "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", "chksum_type": "sha256", @@ -463,6 +575,13 @@ "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", "chksum_type": "sha256", @@ -487,7 +606,7 @@ "name": "plugins/modules/aci_vmm_controller.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "bf296cd7457a775c3ac07f5a1c902b2f498a85eb4c50193289dedc42eea12d93", + "chksum_sha256": "9775c2e58de346c098000bee99bd4bc0e9c8d06a4fb9978dc774a069bec4f0b2", "format": 1 }, { @@ -498,6 +617,20 @@ "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", "chksum_type": "sha256", @@ -512,6 +645,20 @@ "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", "chksum_type": "sha256", @@ -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 }, { @@ -596,17 +771,24 @@ "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 }, { @@ -631,6 +834,13 @@ "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", "chksum_type": "sha256", @@ -645,6 +855,20 @@ "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", "chksum_type": "sha256", @@ -652,10 +876,31 @@ "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 }, { @@ -708,6 +953,13 @@ "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", "chksum_type": "sha256", @@ -722,6 +974,20 @@ "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", "chksum_type": "sha256", @@ -764,10 +1030,31 @@ "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 }, { @@ -932,17 +1233,24 @@ "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 }, { @@ -974,6 +1289,13 @@ "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", "chksum_type": "sha256", @@ -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 }, { @@ -1030,6 +1352,20 @@ "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", "chksum_type": "sha256", @@ -1037,6 +1373,13 @@ "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", "chksum_type": "sha256", @@ -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 }, { @@ -1086,10 +1436,17 @@ "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 }, { @@ -1163,6 +1520,13 @@ "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", "chksum_type": "sha256", @@ -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 }, { @@ -1191,31 +1555,45 @@ "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 }, { @@ -1240,24 +1632,31 @@ "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 }, { @@ -1268,10 +1667,17 @@ "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 }, { @@ -1331,6 +1744,13 @@ "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", "chksum_type": "sha256", @@ -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 }, { @@ -1464,17 +1898,31 @@ "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 }, { @@ -1541,10 +1989,17 @@ "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 }, { @@ -1555,10 +2010,17 @@ "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,6 +2290,62 @@ "format": 1 }, { + "name": "tests/integration/targets/aci_interface_policy_bfd_multihop", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, + "format": 1 + }, + { + "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_interface_policy_bfd_multihop/tasks/main.yml", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "13685e99580f38026105872fd095aefaf2ad3072a73d5d07caee1184ff619ab9", + "format": 1 + }, + { + "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_bd_rogue_exception_mac", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, + "format": 1 + }, + { + "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_bd_rogue_exception_mac/tasks/main.yml", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "55b888d0fe8243a6398c041b0db8b151b6141d1046b5ff8afb6759125c5ec07a", + "format": 1 + }, + { + "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_bulk_static_binding_to_epg", "ftype": "dir", "chksum_type": null, @@ -1845,7 +2363,7 @@ "name": "tests/integration/targets/aci_bulk_static_binding_to_epg/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "84e94677beff76de0840bf516a363281e8d41b2a554137af618f7e8c6263565a", + "chksum_sha256": "cf36d796d11e1be1d26ee74dd9c1be0313d9bdbe7a01e43d1c6ea6d52ee1a0c3", "format": 1 }, { @@ -1873,7 +2391,7 @@ "name": "tests/integration/targets/aci_maintenance_group/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "b844b65db6cdf1934a6533e89a7591f20bc6dd2304acfe5706fe7dd1e1fb7426", + "chksum_sha256": "6b13d9e01f2962b086bc0b12da836dcc8d519d337576c6891b584f700ae10ec8", "format": 1 }, { @@ -1901,7 +2419,7 @@ "name": "tests/integration/targets/aci_tenant_span_src_group_src/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "6c33688aae7482df41385b622a6d728446eabff9a7cb45a9c4a4ca51dc71bba7", + "chksum_sha256": "7139efd1e06fd2c557e9a85d95dc8651ca591abb6c4fbeb2aee894f32e659318", "format": 1 }, { @@ -1912,6 +2430,34 @@ "format": 1 }, { + "name": "tests/integration/targets/aci_interface_policy_hsrp", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, + "format": 1 + }, + { + "name": "tests/integration/targets/aci_interface_policy_hsrp/tasks", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, + "format": 1 + }, + { + "name": "tests/integration/targets/aci_interface_policy_hsrp/tasks/main.yml", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "724f468049beb27adba5873b65d3a200a257d150e56cb97853a347dcbf7a5ead", + "format": 1 + }, + { + "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_policy_leaf_fc_policy_group", "ftype": "dir", "chksum_type": null, @@ -1929,7 +2475,7 @@ "name": "tests/integration/targets/aci_interface_policy_leaf_fc_policy_group/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "fe1b3e59b230ed7f25bdf7c813f197dfa66e1ed964995b17dff7768416ddbe45", + "chksum_sha256": "620c371219707b5ba9ffb3c48b07c390a2f4af7c54b534e3a9102af89e670a9d", "format": 1 }, { @@ -1957,7 +2503,7 @@ "name": "tests/integration/targets/aci_firmware_source/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "ef4e251bc843d4ceafc9ea063dc76b6c03e8db36b2287a197f58aa80bcc768f7", + "chksum_sha256": "0520dbc50b4c79c2d60b38da8781dcfdc287f22c3db3e262257c5533e605e669", "format": 1 }, { @@ -1968,6 +2514,34 @@ "format": 1 }, { + "name": "tests/integration/targets/aci_fabric_pod", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, + "format": 1 + }, + { + "name": "tests/integration/targets/aci_fabric_pod/tasks", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, + "format": 1 + }, + { + "name": "tests/integration/targets/aci_fabric_pod/tasks/main.yml", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "fc1722266ff691d548e29d744fd1c9d37751b754ae88cdd66fcaa86442ba7c57", + "format": 1 + }, + { + "name": "tests/integration/targets/aci_fabric_pod/aliases", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "616f27a9a7bb49e561ef3782330e18d1a8cea3840e3166e798796684dd546a69", + "format": 1 + }, + { "name": "tests/integration/targets/aci_access_port_block_to_access_port", "ftype": "dir", "chksum_type": null, @@ -1985,7 +2559,7 @@ "name": "tests/integration/targets/aci_access_port_block_to_access_port/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "1828323aa38b65382a6861d3940dd3e18c5811e8884a0c9a498b1c20474fd17d", + "chksum_sha256": "2ea0d9197777664d16d11dae2a33cfea35346472a092eda6748ceb0eb445d1d1", "format": 1 }, { @@ -2013,7 +2587,7 @@ "name": "tests/integration/targets/aci_interface_selector_to_switch_policy_leaf_profile/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "b55c642e8532b93e41194dc38d6cc027358149c993e391ec8f4cb2f648609900", + "chksum_sha256": "78d89115835ad9d3ef9534e0a1d408b71c1a3207fb20f0a5250f14aafb72283a", "format": 1 }, { @@ -2041,7 +2615,7 @@ "name": "tests/integration/targets/aci_filter_entry/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "e61460bafe4da68c7fde6ba4f048add6429fe9019de9ed587a21cf24c5f1272f", + "chksum_sha256": "3f32421512afce6c2ed052d4af39f0baa18c51356e9095cb4916b848a63a389e", "format": 1 }, { @@ -2052,6 +2626,34 @@ "format": 1 }, { + "name": "tests/integration/targets/aci_l3out_hsrp_group", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, + "format": 1 + }, + { + "name": "tests/integration/targets/aci_l3out_hsrp_group/tasks", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, + "format": 1 + }, + { + "name": "tests/integration/targets/aci_l3out_hsrp_group/tasks/main.yml", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "0fbdf79f543ac0ae48c297878fcdc6aa3dc752afa61fc7be1997a39cb6f3067b", + "format": 1 + }, + { + "name": "tests/integration/targets/aci_l3out_hsrp_group/aliases", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "616f27a9a7bb49e561ef3782330e18d1a8cea3840e3166e798796684dd546a69", + "format": 1 + }, + { "name": "tests/integration/targets/aci_interface_config", "ftype": "dir", "chksum_type": null, @@ -2069,7 +2671,7 @@ "name": "tests/integration/targets/aci_interface_config/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "949614da80caa4cd9533e7063e8a4d6dfc08e3ae6da70672209b7df2d1b60346", + "chksum_sha256": "bdd483a3e9175b7e37640176f4e41bd2cfe3cde64ca27da979e28ac8b6468bcb", "format": 1 }, { @@ -2097,7 +2699,7 @@ "name": "tests/integration/targets/aci_vlan_pool_encap_block/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "c27de4117ad90e8466f98e511ff516843648ee8da6fe25645a9f8ae87b25768d", + "chksum_sha256": "d03d3b2b81b15d6fa8735ef96833fdbecde52f5eadfd84df553832dd2447da9c", "format": 1 }, { @@ -2108,6 +2710,62 @@ "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_dhcp_option_policy/tasks", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, + "format": 1 + }, + { + "name": "tests/integration/targets/aci_dhcp_option_policy/tasks/main.yml", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "7d51eff57f9862977b125ef675a893b9cb4c8c067c808a84f965927c92b4a244", + "format": 1 + }, + { + "name": "tests/integration/targets/aci_dhcp_option_policy/aliases", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "616f27a9a7bb49e561ef3782330e18d1a8cea3840e3166e798796684dd546a69", + "format": 1 + }, + { + "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_l3out_floating_svi_path_secondary_ip/tasks", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, + "format": 1 + }, + { + "name": "tests/integration/targets/aci_l3out_floating_svi_path_secondary_ip/tasks/main.yml", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "6c15f6cf851cd65ac515fbe2681160fd34b056634ae78e1ac1b28d5793417f2e", + "format": 1 + }, + { + "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_vmm_uplink_container", "ftype": "dir", "chksum_type": null, @@ -2125,7 +2783,7 @@ "name": "tests/integration/targets/aci_vmm_uplink_container/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "16a798f367b375064bf56f5113576979bd3e867d689d1696301dcd1c5b4fb283", + "chksum_sha256": "cda2b2dcf9fc277d187ddc01c25fb43bb6685e248ec5eb65098d34b6a84853f1", "format": 1 }, { @@ -2153,21 +2811,21 @@ "name": "tests/integration/targets/aci_vlan_pool/tasks/dynamic.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "cb73f26a0209ab1499cd932c8b01114d50ea77426c3405114e1d7c57e8edafa3", + "chksum_sha256": "91bc67bd296c556bf94eebf42fc939c98eb5adfbe92e87191beff06f7168f6e5", "format": 1 }, { "name": "tests/integration/targets/aci_vlan_pool/tasks/static.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "391806200ff6ffcf6ecfda748cff3a28825c1092401cad52f1e6afcfeeb83237", + "chksum_sha256": "2dd127083ff68df0a3dbf696db8d8a40a79d047f4a293c3c403699627c6e60e2", "format": 1 }, { "name": "tests/integration/targets/aci_vlan_pool/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "f16539e51468e18e77f6105b1a4ba847f1e6a28a08d652e17fa40144606db4f4", + "chksum_sha256": "4433286af63fcd50848bc5106316ba8688e2225d955a458bc98def951922b3c1", "format": 1 }, { @@ -2195,7 +2853,7 @@ "name": "tests/integration/targets/aci_cloud_epg/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "082ad8f9777a3cb4cf019ed7b3a750e0eaa4ecea0e67d63c17230ab77a184b79", + "chksum_sha256": "ed75fbb318aef76412f7528ffa101f5a74a831bf17e1291b14069f42d0171a76", "format": 1 }, { @@ -2206,6 +2864,34 @@ "format": 1 }, { + "name": "tests/integration/targets/aci_netflow_monitor_to_exporter", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, + "format": 1 + }, + { + "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_netflow_monitor_to_exporter/tasks/main.yml", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "ada8730c4ef724c2092ded8a260928e5640f2c4808b87629eb881e6b25c5301d", + "format": 1 + }, + { + "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_cloud_external_epg_selector", "ftype": "dir", "chksum_type": null, @@ -2223,7 +2909,7 @@ "name": "tests/integration/targets/aci_cloud_external_epg_selector/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "cba2fe77659c826449cd65ed0443e521f7b9179ee1fe78d2b4e67cc3c8785e86", + "chksum_sha256": "2b0932f5ada60334771a611b14a4a5816f740aad0da9ab6b831056fe4c359bce", "format": 1 }, { @@ -2251,7 +2937,7 @@ "name": "tests/integration/targets/aci_cloud_aws_provider/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "30e2c31b5ad7f73e6b909478f13fa19357504a1e3bd9c27f27869f29df0bf874", + "chksum_sha256": "6efafcee986c6011fa8411217eba7a81d6a026421ec055cbe2cf92c731c7a098", "format": 1 }, { @@ -2272,7 +2958,7 @@ "name": "tests/integration/targets/aci_domain_to_encap_pool/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "e1408a04b604992172d9ee514d16d3b1c83f089191656bd4e20516d1c39e16fd", + "chksum_sha256": "63db0c5f71279ef78cce75034fc4561bdcf605172cff877d7d8a2a3fec12e98c", "format": 1 }, { @@ -2300,7 +2986,7 @@ "name": "tests/integration/targets/aci_interface_policy_mcp/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "deef48fee05f5fb8bc48390e26b4cff4871bcdcfb06d94fba77a01bcdae94bb6", + "chksum_sha256": "329f5419253eab113bd4faa25f4a99af32251af723460d8e707c4d8db32f2aca", "format": 1 }, { @@ -2328,7 +3014,7 @@ "name": "tests/integration/targets/aci_match_rule/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "e5084a752a4704a990bb9d8ca629d47d0447209e5cbc8dac92439a9048f96758", + "chksum_sha256": "ea173a9f9c9f72d041027ffffbfb2112baf709dbf032674b3cc258489d4f8cbc", "format": 1 }, { @@ -2356,7 +3042,7 @@ "name": "tests/integration/targets/aci_ntp_server/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "5e745be684046cdde7cd23c7da4d4a96be89ee0b538f65f0047178393194c1c0", + "chksum_sha256": "951b435ff39db19906bbaf323b9bee3b807a2d581e8665dc0361e719f6478ac7", "format": 1 }, { @@ -2384,7 +3070,7 @@ "name": "tests/integration/targets/aci_l3out_logical_interface_vpc_member/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "e76de28c039ecd85e495e2077a838631707c5d7b1547ec8e0cc892a0637cb62a", + "chksum_sha256": "315a59b0363d15adf5c69ed52b58f1ff42f2b1d07e298c6cf841f1fab4bd17cf", "format": 1 }, { @@ -2412,7 +3098,7 @@ "name": "tests/integration/targets/aci_snmp_client_group/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "fcca2775acfaa05479b5b5e430c68be81f2c3aa7e6bd7494c820ee2d19c23eed", + "chksum_sha256": "26b1f825dfd08e37204f64729e2abbcb7c0e300e2cfaa45cba0ded048db4db34", "format": 1 }, { @@ -2440,7 +3126,7 @@ "name": "tests/integration/targets/aci_interface_description/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "dab564ccaffb75fb23e7ebe92e423733dd8db80e0907f2cbb2c7ab63ef9b53f7", + "chksum_sha256": "541b55bf33113e77644761cde93b2d85dd0fcfa7312d3cc79c4e9f647fd579c1", "format": 1 }, { @@ -2451,6 +3137,62 @@ "format": 1 }, { + "name": "tests/integration/targets/aci_bgp_route_summarization_policy", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, + "format": 1 + }, + { + "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_bgp_route_summarization_policy/tasks/main.yml", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "5942305ac9e0bb1d890ef8526e12637256e9f4ddffb2f9594d745d1e9273cd4f", + "format": 1 + }, + { + "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_l3out_dhcp_relay_label", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, + "format": 1 + }, + { + "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_l3out_dhcp_relay_label/tasks/main.yml", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "2c58052c4366f9fc07db66e74f2e1a3f40a591029c9667fe8a6f7c3ed3885892", + "format": 1 + }, + { + "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_dns_provider", "ftype": "dir", "chksum_type": null, @@ -2468,7 +3210,7 @@ "name": "tests/integration/targets/aci_dns_provider/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "8deb0048459357964c22ea4ceeddc9581317b58e9bb61d833430069f67d63368", + "chksum_sha256": "75a48c8e2feb076b93f0ce76fcee1bf7029b7189021cb88262a734a1a013606f", "format": 1 }, { @@ -2496,7 +3238,7 @@ "name": "tests/integration/targets/aci_fabric_wide_settings/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "148d337c86ab59cfab9434d4d23959de9a7fc4f2cac867d7af9f9e4e52d02e9b", + "chksum_sha256": "647a1cc95af3bbe86822436a1dc0db0cb0e3093ab4f80fb21cb0da08906144f4", "format": 1 }, { @@ -2524,7 +3266,7 @@ "name": "tests/integration/targets/aci_esg_contract_master/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "510fa4b0b76ac202ef3b090ae4fc78e5f3b8875e58ceeada92412884b53be1a1", + "chksum_sha256": "a67a0f25727f1bd1d90a50924b7767d9a26b3b4d06df8d099a039c5e5b5d2dd8", "format": 1 }, { @@ -2552,7 +3294,7 @@ "name": "tests/integration/targets/aci_access_port_to_interface_policy_leaf_profile/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "d3ed26b1f2e6331c513718899de4606dadb3f837d724946a54b2347e2bea6684", + "chksum_sha256": "b4a134d633ad0572114d5e0184929adb9b33612c543b99899c7fc9d88f13d3e1", "format": 1 }, { @@ -2580,7 +3322,7 @@ "name": "tests/integration/targets/aci_cloud_vpn_gateway/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "bbd695fc212060f340e99ae563176ae49654bbefa01bb6e093789633e899e090", + "chksum_sha256": "10acde1e59189c19db818fa973107ba1dcb5723f327a224441e701eb52415c45", "format": 1 }, { @@ -2591,6 +3333,62 @@ "format": 1 }, { + "name": "tests/integration/targets/aci_aaa_security_default_settings", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, + "format": 1 + }, + { + "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_aaa_security_default_settings/tasks/main.yml", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "7c8afd97006fcf68327261fb0f59141dce9ee8f24b9865b7c5fbd1d4004490e0", + "format": 1 + }, + { + "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_access_spine_interface_profile", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, + "format": 1 + }, + { + "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_access_spine_interface_profile/tasks/main.yml", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "d5789ff7ae5e73b5e920cd7c0ff63889a6865dae9d5c5d52b39080a268a0e1cf", + "format": 1 + }, + { + "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_interface_policy_fc", "ftype": "dir", "chksum_type": null, @@ -2608,7 +3406,7 @@ "name": "tests/integration/targets/aci_interface_policy_fc/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "b2d68e0c3e83127354a824682dc77c62a7a8f7aff69dae9f125c6b068265358f", + "chksum_sha256": "2a0710b51cc7591636bcfbcf98523e8c90c7d6471d2d4a34614bca90df7dc9b5", "format": 1 }, { @@ -2636,7 +3434,7 @@ "name": "tests/integration/targets/aci_bd/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "348510483344aa212bc086073b923408e66d0487d42869dab01039ef52dddc0f", + "chksum_sha256": "b688f78a537ecbe5c93b7137442c2648250bb083e35ff3200ad74e8805bed8f1", "format": 1 }, { @@ -2664,7 +3462,7 @@ "name": "tests/integration/targets/aci_snmp_community_policy/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "1f55bd655ca008656898bca31cb24e3c3fb8c4c9857ac5e4344a9cfcbc173f5b", + "chksum_sha256": "b0a52e2028b3b6a122141571a294359f4ae704805d26c68e2810a6c2e28d25c8", "format": 1 }, { @@ -2692,7 +3490,7 @@ "name": "tests/integration/targets/aci_access_span_dst_group/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "de5e15422dbac4ba028abd5422c3f9fe32fb5bf2cbdbd11658a3be4f44b3160e", + "chksum_sha256": "ba4a2a1bc6f8b8fcd6fb658c770e22a84302cf1128d04d0e7a4bd3eaf48b4a09", "format": 1 }, { @@ -2703,6 +3501,62 @@ "format": 1 }, { + "name": "tests/integration/targets/aci_node_block", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, + "format": 1 + }, + { + "name": "tests/integration/targets/aci_node_block/tasks", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, + "format": 1 + }, + { + "name": "tests/integration/targets/aci_node_block/tasks/main.yml", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "9b674a47283e025b415b1517afa141a7a2cb47989f8dc4428801a9dcfceee21e", + "format": 1 + }, + { + "name": "tests/integration/targets/aci_node_block/aliases", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "616f27a9a7bb49e561ef3782330e18d1a8cea3840e3166e798796684dd546a69", + "format": 1 + }, + { + "name": "tests/integration/targets/aci_fabric_external_connection_profile", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, + "format": 1 + }, + { + "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_fabric_external_connection_profile/tasks/main.yml", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "75f507b1660e5210c8087024f86683df8970405cac3e9588881761cc35bd4b2e", + "format": 1 + }, + { + "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_config_snapshot", "ftype": "dir", "chksum_type": null, @@ -2720,7 +3574,7 @@ "name": "tests/integration/targets/aci_config_snapshot/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "0a799646b1dbd9af66d8df8679820cf8605a7cb64de234e8c88d3d4eaf7f0502", + "chksum_sha256": "ffaf6e7f0074f0cc2c13d5de9c6ba0694d99bb7b99be2ca416cc479c4fd41ce3", "format": 1 }, { @@ -2769,7 +3623,7 @@ "name": "tests/integration/targets/aci_access_span_src_group/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "bb9a24d78c38d7e0bff38cdcf51520f0deb18fa0679bc58856121caa71564413", + "chksum_sha256": "44d4f6f7286395d4b69df747e208f1d70a52a04b68572920c740fdf92faf8d81", "format": 1 }, { @@ -2797,7 +3651,7 @@ "name": "tests/integration/targets/aci_interface_policy_leaf_breakout_port_group/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "2a419d08da733f8a710fcce36d358c3a792435145c4da5ea9f359ec3126c9509", + "chksum_sha256": "ab95d13dd9a4034c23cbafb5a903a342482cce5002617efc9bae7d96676cb7a0", "format": 1 }, { @@ -2825,7 +3679,7 @@ "name": "tests/integration/targets/aci_fabric_switch_policy_group/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "9c2e6fd65a9f000cb521b0321fef521255c8b9374f987213d23836db32ae3b7b", + "chksum_sha256": "0563dc17cad8b553217c1a11c55df9d481539c9f7c76b0a012d21f9e45508320", "format": 1 }, { @@ -2836,6 +3690,62 @@ "format": 1 }, { + "name": "tests/integration/targets/aci_action_rule_additional_communities", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, + "format": 1 + }, + { + "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_action_rule_additional_communities/tasks/main.yml", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "50dc2f6089cf26d9dae4ae3858760d006dee474d8772e3aa8b99c6f005a293bd", + "format": 1 + }, + { + "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_access_spine_interface_selector", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, + "format": 1 + }, + { + "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_access_spine_interface_selector/tasks/main.yml", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "b0bcd1f6790dbbfc417b4d06bc77bdecd380b2278065e2bac73a115ec8c92d17", + "format": 1 + }, + { + "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_ap", "ftype": "dir", "chksum_type": null, @@ -2853,7 +3763,7 @@ "name": "tests/integration/targets/aci_ap/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "180f2222d7fab150d26b1f94088d5edb070178d1bdf4bc198c0d24588d32b331", + "chksum_sha256": "075ea0bef5ce28a4ba9132f3faca6f08d54c4d519820e8acdb7eb29078f4e9ef", "format": 1 }, { @@ -2881,7 +3791,7 @@ "name": "tests/integration/targets/aci_interface_policy_lldp/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "3c2094fbab84d87ce85c8e69e2b7c5b37f906d95eb36578b4c39ade77eb46e35", + "chksum_sha256": "4fc7ace04cc0c032fe5d143344bbd1efe79e4383dae59962e0fe265a28ecd04d", "format": 1 }, { @@ -2909,7 +3819,7 @@ "name": "tests/integration/targets/aci_access_span_src_group_src_path/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "a01cd09447143359ef684d14444f762e33d2c56d9afb6cad3263989678be66bd", + "chksum_sha256": "65adaca0033acf98b08766fdc5743e33aa947639f324dcf7ac2bad8ef4f6c6b0", "format": 1 }, { @@ -2920,6 +3830,34 @@ "format": 1 }, { + "name": "tests/integration/targets/aci_netflow_monitor_policy", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, + "format": 1 + }, + { + "name": "tests/integration/targets/aci_netflow_monitor_policy/tasks", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, + "format": 1 + }, + { + "name": "tests/integration/targets/aci_netflow_monitor_policy/tasks/main.yml", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "812cecdf3a9c2d60c7f12e79df107e590d0be6ad4900c932dd2d3bd8bd1b5bf7", + "format": 1 + }, + { + "name": "tests/integration/targets/aci_netflow_monitor_policy/aliases", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "616f27a9a7bb49e561ef3782330e18d1a8cea3840e3166e798796684dd546a69", + "format": 1 + }, + { "name": "tests/integration/targets/aci_interface_policy_l2", "ftype": "dir", "chksum_type": null, @@ -2937,7 +3875,7 @@ "name": "tests/integration/targets/aci_interface_policy_l2/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "9ca36be150a08cbb8940d974c1a6ee059739fd0728b539ffcee805426964bfe8", + "chksum_sha256": "1b93975510336d9fe01777e4d386dda4f9e2a5e65d812fde144039577ed6d030", "format": 1 }, { @@ -2965,7 +3903,7 @@ "name": "tests/integration/targets/aci_l3out_route_tag_policy/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "2c1e76ca9add4ba716db7e406f1d4cfca1487881d5264dbc4a0057c9a3a26502", + "chksum_sha256": "6e154f6c8fb59f20af72b610e90d2c4b624c3ec72b0c5db14b31850325abaa70", "format": 1 }, { @@ -2993,7 +3931,7 @@ "name": "tests/integration/targets/aci_esg_ip_subnet_selector/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "d1cf6174d2cf27cf9488644f407736c4139424cf52efdbf951713b7b511ca3ad", + "chksum_sha256": "784db6c69ed7752334eeba70e235637730f04f76649d8dee8802dc2265a68036", "format": 1 }, { @@ -3004,6 +3942,62 @@ "format": 1 }, { + "name": "tests/integration/targets/aci_access_switch_policy_group", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, + "format": 1 + }, + { + "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_access_switch_policy_group/tasks/main.yml", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "a96c613da3cfcb8d4877a515c47a85c5611941611aa6f6d5b5b8acd383bd1048", + "format": 1 + }, + { + "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_interface_policy_eigrp", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, + "format": 1 + }, + { + "name": "tests/integration/targets/aci_interface_policy_eigrp/tasks", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, + "format": 1 + }, + { + "name": "tests/integration/targets/aci_interface_policy_eigrp/tasks/main.yml", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "21ef50711ac13abe3fe324cb574e510d8552751d4745af7dc4704a5e740f56bb", + "format": 1 + }, + { + "name": "tests/integration/targets/aci_interface_policy_eigrp/aliases", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "616f27a9a7bb49e561ef3782330e18d1a8cea3840e3166e798796684dd546a69", + "format": 1 + }, + { "name": "tests/integration/targets/aci_fabric_span_src_group_src_node", "ftype": "dir", "chksum_type": null, @@ -3021,7 +4015,7 @@ "name": "tests/integration/targets/aci_fabric_span_src_group_src_node/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "8ef543f2ea69f83824459c15f967cee7dc2d8b553a613d42ba58c794cbc71f9c", + "chksum_sha256": "740872eb37c6af94636ad16b317b0ff68d99c18975f41c2cf09b83ac4999cdb7", "format": 1 }, { @@ -3049,7 +4043,7 @@ "name": "tests/integration/targets/aci_fabric_pod_selector/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "142a54f5ea8d61ca6a19bd8caf6a851799de963b6d41d427acb6205bf00fe0ab", + "chksum_sha256": "acf9ceb102cdf9dd068fe5fb2d251b723c1800d1878f9a9232a49a25e1533b08", "format": 1 }, { @@ -3077,7 +4071,7 @@ "name": "tests/integration/targets/aci_bd_subnet/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "860384656ad549aa29df90bc8684d04ba250a9bdcbd50625c4db12a8da6c5b7a", + "chksum_sha256": "c85f1df14defc8594e85dab41d012f478841a580c2b4bbd63584d0fc52517897", "format": 1 }, { @@ -3105,7 +4099,7 @@ "name": "tests/integration/targets/aci_access_span_src_group_src/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "9dc18d120ffb94f5d068e0d153497a8cf5be32366a8b698b62f0d59bfa40fa6c", + "chksum_sha256": "5cafc8dd677930fd24fe7c90eaa2506bf9e169b3c5642d708ebe9ab6b3833197", "format": 1 }, { @@ -3133,7 +4127,7 @@ "name": "tests/integration/targets/aci_aaa_ssh_auth/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "68ea72c2bead2faabb228d2fb91146165c519371bc46ad550c6a5fcb573588cf", + "chksum_sha256": "272463007e5206c3bb50044a00296247d115f393bdd411ca8486a7f2b58d8cec", "format": 1 }, { @@ -3158,6 +4152,41 @@ "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_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": "edf2582d6c826c327514d6dc3ca831527542282cc6558396cf9dad006d930508", + "format": 1 + }, + { + "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_system_banner", "ftype": "dir", "chksum_type": null, @@ -3175,7 +4204,7 @@ "name": "tests/integration/targets/aci_system_banner/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "6055791dda8f2b3c4fa18573d3b704229cda2a6b817f3b8984fd46475d97652f", + "chksum_sha256": "c3dfe182aa2cc04090da103aec29a93790275b8cbd966453c688f70adf95887e", "format": 1 }, { @@ -3203,7 +4232,7 @@ "name": "tests/integration/targets/aci_interface_blacklist/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "4d3c6bde54b9a5c3b7c01058b41a3cb7e055425062699463733b0d2bbd0efca4", + "chksum_sha256": "7e86f9f41542e3e6c9a14533ee6eaad79e234ecb97450ed72c8af934930ec2b9", "format": 1 }, { @@ -3231,7 +4260,7 @@ "name": "tests/integration/targets/aci_interface_policy_leaf_profile_fex_policy_group/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "e9f5cff01edb38af15d9db2e2b6a19fb889e6a911dd1c079ddbd2355eea58784", + "chksum_sha256": "14bd6dbb8fbe95f5005695ef99617f07f339fb400d4cb0c58a3f95b406b24980", "format": 1 }, { @@ -3259,7 +4288,7 @@ "name": "tests/integration/targets/aci_syslog_remote_dest/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "8cdde3499fe651dad5bd9afc73a318d9b2ccbe1ba1bed3d7e3e2829268484373", + "chksum_sha256": "329bb76f7ef5d3580e95ed6b3b97ac3b9a608b5a6535d8897ea48a6d1ef8f9d4", "format": 1 }, { @@ -3287,7 +4316,7 @@ "name": "tests/integration/targets/aci_vzany_to_contract/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "184e773934f91f4af9a47fe4cc619c0db3f569e95c2b4af41f50e0712c4f056c", + "chksum_sha256": "393485c2f5a01f6af10d1304437784bcfa89f1b000aa39275bb25b3f137c288e", "format": 1 }, { @@ -3315,7 +4344,7 @@ "name": "tests/integration/targets/aci_fabric_leaf_switch_assoc/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "52a606163c2d5b8fde2b7e6024867432468613edb00589d077468cffd51582c2", + "chksum_sha256": "6a2fb0ef7a000a6222909878c191e8abfba89b6b049f6ab1fca1765dbdb70435", "format": 1 }, { @@ -3343,7 +4372,7 @@ "name": "tests/integration/targets/aci_contract/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "1d8de08f6d94f24732d428571352d0729799c4060c1ec71ffb98dddafc30ee7e", + "chksum_sha256": "6c3d695d9cc94bfb6edb9c98da462c4129f2ba7a72d57f3ccbb7fc2e993d2cbe", "format": 1 }, { @@ -3371,7 +4400,7 @@ "name": "tests/integration/targets/aci_node_mgmt_epg/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "6cc139d0048870bfc25135df76cc9e9489214e42af5ff369491469ecedc7d1ac", + "chksum_sha256": "fc7475fc26e0422513ff3607cc7d961f22351dd5feab56321731796a812341f2", "format": 1 }, { @@ -3382,6 +4411,62 @@ "format": 1 }, { + "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_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": "7478cb13ebcf26986773947a04936f91cb724ad1d780e8061eb8664e7bc9d42c", + "format": 1 + }, + { + "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_pim_route_map_entry", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, + "format": 1 + }, + { + "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_pim_route_map_entry/tasks/main.yml", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "f5d9d462368cb9b72d836aca6dfda0ba5fa4d4845a74e4475ffe2f2cd6d36eb5", + "format": 1 + }, + { + "name": "tests/integration/targets/aci_pim_route_map_entry/aliases", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "616f27a9a7bb49e561ef3782330e18d1a8cea3840e3166e798796684dd546a69", + "format": 1 + }, + { "name": "tests/integration/targets/aci_l3out_logical_node_profile", "ftype": "dir", "chksum_type": null, @@ -3399,7 +4484,7 @@ "name": "tests/integration/targets/aci_l3out_logical_node_profile/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "5ec5e65d1465e02637d52d5bb09fdbe4fda23bd1531dd1c7bcf63a3e6daf69d2", + "chksum_sha256": "e01c83bb926d73f2696b0c80aa32ef57ada9421d70edcfa28fabf2d28c1a88cc", "format": 1 }, { @@ -3427,7 +4512,7 @@ "name": "tests/integration/targets/aci_l3out/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "c085a58785b7e4539654e0254479dd8585f5ed9d94005772e2cff7b02db13e50", + "chksum_sha256": "f2f3db1f45a197eb63ee2abf69d3846e003169bc8a005a7f4d8d8f2ceaafb6c8", "format": 1 }, { @@ -3455,7 +4540,7 @@ "name": "tests/integration/targets/aci_epg_monitoring_policy/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "cd7cb391b571c4b8294030393cd288334b14eee8c1f88bf678776f8cc60e7440", + "chksum_sha256": "24b071e6239b75d757f3e3f4f781d02ac2cb5c8e115c6c1ceda273d0cc1fdd58", "format": 1 }, { @@ -3483,7 +4568,7 @@ "name": "tests/integration/targets/aci_interface_policy_leaf_policy_group/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "8821f0cf43e9a9d1f5d8965fc4b38f78a75d62d1b599a74a4dff8546e9866919", + "chksum_sha256": "dd96b5ca42b731af07e3ea81b610077b65049ffdb61b0410c595939c626394f8", "format": 1 }, { @@ -3494,6 +4579,55 @@ "format": 1 }, { + "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_fabric_management_access_https_cipher/tasks", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, + "format": 1 + }, + { + "name": "tests/integration/targets/aci_fabric_management_access_https_cipher/tasks/main.yml", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "354499d076d51762359bc6754bf7a3419a8adcf808c5a531e7a3ed5d3bdb8576", + "format": 1 + }, + { + "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_fabric_management_access_https_cipher/pki", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, + "format": 1 + }, + { + "name": "tests/integration/targets/aci_fabric_management_access_https_cipher/pki/admin.crt", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "f97928b2cd1ce43cfe9ae9bbf47a40b858a749c4c3f25a7ec02898611f4fee90", + "format": 1 + }, + { + "name": "tests/integration/targets/aci_fabric_management_access_https_cipher/pki/admin.key", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "947c1b5a6c419641d4b2c8492b91f2d71588958666aeceeffb1f878460b1d256", + "format": 1 + }, + { "name": "tests/integration/targets/aci_match_route_destination", "ftype": "dir", "chksum_type": null, @@ -3511,7 +4645,7 @@ "name": "tests/integration/targets/aci_match_route_destination/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "85f354ddd29b16e87aaa87111e966a120a6c6003d9a20426900be897c2920a87", + "chksum_sha256": "2f4b74df3f41c9c953b17a5507582414ef917228a975b2cdfea50f9f1bfe0a60", "format": 1 }, { @@ -3522,6 +4656,69 @@ "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, @@ -3539,7 +4736,7 @@ "name": "tests/integration/targets/aci_lookup_interface_range/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "2dcf9c4f3ee3490c49c1231b11d66fc565c936109235e174d452d072b4b02dcc", + "chksum_sha256": "221de56e6663fa2dceb813ad609f945c98710d6fbcadcae7c5a33e4a7b6e9051", "format": 1 }, { @@ -3550,6 +4747,62 @@ "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, @@ -3567,7 +4820,7 @@ "name": "tests/integration/targets/aci_vmm_controller/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "3b4854c79b639f404cb9aa8636019081e6bb5c8084848e5d81757537d28f3c5f", + "chksum_sha256": "5a3cd55149d7f96da70469e19735ab3c66f1035b7c16c408e012d9abf0e8585c", "format": 1 }, { @@ -3595,7 +4848,7 @@ "name": "tests/integration/targets/aci_match_community_factor/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "85b19ffcc7f1722664426544bc85648f722f8cda85876e702b651174a6d6c251", + "chksum_sha256": "88bfb2ad054c03baaa0deb48b1ca92378c2861e268f405f01eeb24367ea803ba", "format": 1 }, { @@ -3606,6 +4859,34 @@ "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, @@ -3623,7 +4904,7 @@ "name": "tests/integration/targets/aci_interface_policy_spine_policy_group/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "70e00aa9a7355ec778b136a583b71ac3211f5cd0a37e4574b5b9f421f99ab6ea", + "chksum_sha256": "f549bb6df8c4bb50f2b90e7396eb1821f6bcdc1b73692e7086e84918fd4a71fd", "format": 1 }, { @@ -3651,7 +4932,7 @@ "name": "tests/integration/targets/aci_contract_subject_to_service_graph/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "715f1489683ba74fed4c3301e483f8ceeec58119bcbf765eab406b134d7954c6", + "chksum_sha256": "adc631affae75b956ad1706c342768534435020288b484e5b9206e15f577723a", "format": 1 }, { @@ -3679,7 +4960,7 @@ "name": "tests/integration/targets/aci_l3out_extepg_to_contract/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "89289a10d688f0af43ab79066c1bf433d8117b54cc8d3cf02bda857edd507699", + "chksum_sha256": "c4235e10fba80f4cfa51414d789fc641b110a586ce680758fc473008c16679d4", "format": 1 }, { @@ -3707,7 +4988,7 @@ "name": "tests/integration/targets/aci_esg_tag_selector/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "19d6518c1375739ee95c6016e97bfa1aab3da1e6db19429ce9d89006c5236d63", + "chksum_sha256": "e8737e49c607fc4ea8d3e1be17786d980145bac3a8a47b37e342852dbd35b19e", "format": 1 }, { @@ -3718,6 +4999,34 @@ "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, @@ -3735,7 +5044,7 @@ "name": "tests/integration/targets/aci_taboo_contract/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "8108b12b09f191cd13cbf4c5fc15132979a8a64fc070ccdd1f3053b4fcc05180", + "chksum_sha256": "cccae803763b432f0e46dd690c1246c7890f0c15d43afb738aed1f5e7aec2f4f", "format": 1 }, { @@ -3763,7 +5072,7 @@ "name": "tests/integration/targets/aci_domain_to_vlan_pool/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "7f14fc189439710b1e57a89af9ba53d34850b8b289c59207b9239d73cd0edabd", + "chksum_sha256": "1be874b2846aa8cc3262e2fd72f54e4be879ed8cf182f3455dbdfb821ea3fd52", "format": 1 }, { @@ -3774,6 +5083,62 @@ "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, @@ -3791,7 +5156,7 @@ "name": "tests/integration/targets/aci_epg_to_domain/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "2aa9a7c427ad9d6d2aeb1c9454537ec1df404ca85a1c0a2da43412816fe0d2ff", + "chksum_sha256": "e532d3cb3ba4bfd61a9743796bee3e77a7f8dba5432ca556eee75acd28e7d259", "format": 1 }, { @@ -3819,7 +5184,7 @@ "name": "tests/integration/targets/aci_dhcp_relay_provider/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "3bcac5486e000d2c50ae9d748e6ac6870227c67671d6d43603f272f198adb317", + "chksum_sha256": "8ce53bdb5cb776c76480212771310300dfc3914a788b5f4e5dce7c1422c6be0b", "format": 1 }, { @@ -3847,7 +5212,7 @@ "name": "tests/integration/targets/aci_fabric_node_control/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "be5b110f64ea6906839446cb0d79b30222fda3a9f4afb9da7cbb10bc75944898", + "chksum_sha256": "c59e43442f0f1a1ee20a22249c7719a051efb76b4cf8475aa6038021089d613d", "format": 1 }, { @@ -3875,7 +5240,7 @@ "name": "tests/integration/targets/aci_interface_policy_cdp/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "4392aea7e298d85716756da20857a58467bbda2b4f92d1d711ed1b6fd368325c", + "chksum_sha256": "151d65b7a851eecaa7b3d3e57a8b3cb04900087f5104825a83d63a104d775a6a", "format": 1 }, { @@ -3903,7 +5268,7 @@ "name": "tests/integration/targets/aci_fabric_switch_block/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "423c915493cf75de78c63b152093ddf0066dfd04327a79384c753ddaf3c99ca6", + "chksum_sha256": "875c4f67b25a7e8f915926dd63b1ffc62c8b60e6a68245e9e3b4a44a4115854f", "format": 1 }, { @@ -3931,14 +5296,14 @@ "name": "tests/integration/targets/aci_tenant/tasks/httpapi_connection.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "af2e683ad88998f1ff8062ded1c66873ce24f38165afca72d36356e435e295b5", + "chksum_sha256": "374084c2e47bb24fb55ccd963f962ca99de7504897e53b6cfeb68ba75710f5b1", "format": 1 }, { "name": "tests/integration/targets/aci_tenant/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "6a0620f26d77dee85bcf88b1bdc61aaadc57fd04daafaa6bd91cc8a0898ac507", + "chksum_sha256": "768148a4cfb5ac46096dae214c9301edbd62409cb29273417f1d7de9e4a9e79a", "format": 1 }, { @@ -4036,7 +5401,7 @@ "name": "tests/integration/targets/aci_maintenance_group_node/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "b342a36b963e0b3001e11800be162c1faf958dc1bdfa552f32b928c516a532ed", + "chksum_sha256": "6c2130d1314c7e5258b0c06ae27a187d652eb0aa01a363ed46bb88180ce981d0", "format": 1 }, { @@ -4047,6 +5412,34 @@ "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, @@ -4064,7 +5457,7 @@ "name": "tests/integration/targets/aci_syslog_group/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "b19762539379f2b450c6fa4619679431461b7820a2fd498c76164f476241726b", + "chksum_sha256": "6c8d18b7d1b934e886e32960bab072793cb8c9fb411a974b322940bdb47ec526", "format": 1 }, { @@ -4075,6 +5468,34 @@ "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, @@ -4092,7 +5513,7 @@ "name": "tests/integration/targets/aci_route_control_profile/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "f5c0118b53e4cab847d81acd60edfba3e5f58a263aa32f980ccce6c9240a2f09", + "chksum_sha256": "4a9deefee3a9c978912c3fed74ab40f13a922f5b409c7ffc5c8cdca6468a488f", "format": 1 }, { @@ -4120,7 +5541,7 @@ "name": "tests/integration/targets/aci_snmp_client/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "b6aeebb21b6c1e350325f298e3cd1d98615dc2a5d12916783b06c259fccd0357", + "chksum_sha256": "8319763fc884a440954ec4ccebe9ee9250e6273ea234f8fb664d8886cc2b74e7", "format": 1 }, { @@ -4148,7 +5569,7 @@ "name": "tests/integration/targets/aci_aep/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "e77d10440880f6638ea10d90eb11baf49ad2c213760740ae224fb7582ce5410f", + "chksum_sha256": "2b7837cc64a41aee8dc2ec18b18dee00bca0a01508cc459c420554f4351744a6", "format": 1 }, { @@ -4176,7 +5597,7 @@ "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 }, { @@ -4187,6 +5608,62 @@ "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, @@ -4204,7 +5681,7 @@ "name": "tests/integration/targets/aci_interface_policy_link_level/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "760f5c21dc389db02d3e809c5761fa869934dfd6867fbbcdf11fcbe511a9c931", + "chksum_sha256": "2e4dfc8c97a7056dd048fe03ac4f32e085b6660d1cfe5a6d8c02a72742824a84", "format": 1 }, { @@ -4215,6 +5692,34 @@ "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, @@ -4232,7 +5737,7 @@ "name": "tests/integration/targets/aci_l3out_extsubnet/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "ff51702c2b61e04d0852925417f2632ca2ad77476c87fbc3e3bf26e841fb9b40", + "chksum_sha256": "23e36fefcac51193152a60816eef04e25f51414c89ee8e0a777e5021b8811295", "format": 1 }, { @@ -4260,7 +5765,7 @@ "name": "tests/integration/targets/aci_l2out/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "ac1d2a1e71906e0bcf422d680dd720508431daae4c1717c57834105e79a3aef4", + "chksum_sha256": "a5b42d2c95354d21b03b1c93d0ca9ae8420ab88925e83fa5e41de036bdc42360", "format": 1 }, { @@ -4271,6 +5776,83 @@ "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, @@ -4288,7 +5870,7 @@ "name": "tests/integration/targets/aci_interface_policy_port_channel/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "dd6ca5c9bc1c622ad186c3081434eb5d82f61d82e756e9a7731fbe39a85a1c26", + "chksum_sha256": "5d15555a235b9bce54b5a236b904fd2abc03d7c77a5676a78b133701747294a3", "format": 1 }, { @@ -4316,7 +5898,7 @@ "name": "tests/integration/targets/aci_match_community_regex_term/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "a317a7798696e01a0bbcea910360a73b59f03c9fcf0946a8f0e1566daaa222cb", + "chksum_sha256": "816f883819fca9605b5d08fbec656564a659d6dae12519f744a1f38e1733ab1f", "format": 1 }, { @@ -4344,7 +5926,7 @@ "name": "tests/integration/targets/aci_snmp_policy/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "14124ae8544f77657abd5db831e7226aaf9b752363d4751ba05943ca8fc9c1ec", + "chksum_sha256": "924e49b0662472fe0e67ab72404819c5e00523f51b37715f28a805cce6b2a850", "format": 1 }, { @@ -4372,7 +5954,7 @@ "name": "tests/integration/targets/aci_fabric_pod_policy_group/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "bb70c203bf4447030ac385ca1f63408f7cb2bba098a457badaa46ad73907101d", + "chksum_sha256": "a34f5d541f3fa84f488c3fae897cffd7e1352728a4807fa86557cd326e4d8a7f", "format": 1 }, { @@ -4400,7 +5982,7 @@ "name": "tests/integration/targets/aci_ntp_policy/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "b7c1c21fd27b102bebe4468763f63901b5c66ba04ebbd3dd1fc4f030ab2a46d8", + "chksum_sha256": "f120f96885c5c81468280e9eb51a4d2b03ece33638eb1f42519861aba2218383", "format": 1 }, { @@ -4428,42 +6010,42 @@ "name": "tests/integration/targets/aci_domain/tasks/vmm-vmware.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "068ef4d1d8671df9f8ba54f51483cb29a08a42adcd5227ae345b0c87bce5e5b8", + "chksum_sha256": "6aabcd7a0fa4ef86f4b4c5c68364d8a30e707f34a42e97ead2a2de68d10beb45", "format": 1 }, { "name": "tests/integration/targets/aci_domain/tasks/l2dom.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "04dbec0678323daf3a87d3170ff98a41a8d38a5db26e8772f7d36e406a9d4483", + "chksum_sha256": "29ec89ad1eba9d7ffafe36e5488d2a4533ad529cfa813093416fedd3826dd06a", "format": 1 }, { "name": "tests/integration/targets/aci_domain/tasks/fc.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "c04c71cae5fcd512f2e5203c57129582bf1f0b55c74a9dcd4c57dcdc8856fc7a", + "chksum_sha256": "e8c8bc20d452d9b3209ac08186558f5dece49357afe9a609734aebae7f2e1fe7", "format": 1 }, { "name": "tests/integration/targets/aci_domain/tasks/phys.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "36fae3df4197ffba49ff83256a05c2c952247e974a052c94d3882dc693cdc80a", + "chksum_sha256": "adf84c74f9c21856cf21f498b7c905652911b00c7016733b2b49f4a13ff93a15", "format": 1 }, { "name": "tests/integration/targets/aci_domain/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "8094a133d927bf97b43ccdc714c7b8b962af676a11e616f205f21e605f27f1e9", + "chksum_sha256": "38a72f6c96f2b5bd47da5764a219da47054b0814d0944001539679311a9d3758", "format": 1 }, { "name": "tests/integration/targets/aci_domain/tasks/l3dom.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "28068851b310e83f51c3d025c5cddf8fb4acc6466ed5873cfa47279140d655d5", + "chksum_sha256": "567c158639220dfb536539f8f2175fd0c2af80036285c5e9bd31a9c6ad2530e9", "format": 1 }, { @@ -4474,6 +6056,34 @@ "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, @@ -4491,7 +6101,7 @@ "name": "tests/integration/targets/aci_l2out_logical_interface_path/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "1165e2174890eb8cb16b1404bb45f4e8f5d8ef28cf70e482ef1ff2406644a38c", + "chksum_sha256": "d6c73e292a940421447e8428d9f80684516667ea75a511d3f1556487cd266fb6", "format": 1 }, { @@ -4519,7 +6129,7 @@ "name": "tests/integration/targets/aci_l2out_logical_interface_profile/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "b14eacd51921ac498aaff06bce4e881310cbcdbd8498f3b89a493ce4c9a198e1", + "chksum_sha256": "2cc00f299f8ea22792ca39143101fd8e7bed11cb289d6fc0efdd352100872b8b", "format": 1 }, { @@ -4547,7 +6157,7 @@ "name": "tests/integration/targets/aci_l3out_extepg/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "e3cc46789ecac2e9636478d437fac86b9006cc9f2ed504961fe2f0e110e1c69d", + "chksum_sha256": "c836365750e7a249888a36db8674bb739727dc37aec16cdfd25f55d0a90e916e", "format": 1 }, { @@ -4575,7 +6185,7 @@ "name": "tests/integration/targets/aci_aaa_custom_privilege/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "87e9446b4626d0ef82702c19eae28f33bac7ec595b4bea916317b7938ef1964f", + "chksum_sha256": "9baf4665c6e36079e351b72403afb38fd7cd55b82d6a8d421be615bfbcede9e1", "format": 1 }, { @@ -4603,7 +6213,7 @@ "name": "tests/integration/targets/aci_fabric_scheduler/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "704b7c6e84833030f155e856359f86d7166319df9f4595a463c2662ad048218d", + "chksum_sha256": "dbb8e5f043a9f5dee464af5ac5dabab28801bf0b87845d2923b988925dbea1fd", "format": 1 }, { @@ -4631,7 +6241,7 @@ "name": "tests/integration/targets/aci_fabric_span_src_group/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "8b252a0ada511e83d47a0b183a5aa1bb06a30296081f84cb99af94e26077d70e", + "chksum_sha256": "1349d691b2fe6da11dd0a944676e957265253af30d5c87af537934ed86b5a770", "format": 1 }, { @@ -4659,7 +6269,7 @@ "name": "tests/integration/targets/aci_firmware_group/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "f2fd0c9c021e33ae4d4fec5ce9ffce4128b16c2d8ca1b67595954a50f59694db", + "chksum_sha256": "baff773fe422ff7682c90ffc9464dcab4d4cbd96fc264934a9b9fac31efaa425", "format": 1 }, { @@ -4687,7 +6297,7 @@ "name": "tests/integration/targets/aci_epg_to_contract/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "6938a58d3e50e6dd47797f38b2d79024e680245d4fd40872b9732813c123b7d6", + "chksum_sha256": "b4c20198391e11c0ea0b8bdea508d71f9f947ed99bb6c920b29aa8eb1e99a07d", "format": 1 }, { @@ -4715,7 +6325,7 @@ "name": "tests/integration/targets/aci_interface_policy_leaf_profile/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "9b6457997e6b2e8e018cfa0bebfe2028134acfd44522c7e222a3ffb7910219e3", + "chksum_sha256": "fffdbacbdff26e734a2a5e76421e7190bc469d5d30e4fa5faacf788dd51647f7", "format": 1 }, { @@ -4743,7 +6353,7 @@ "name": "tests/integration/targets/aci_bd_to_l3out/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "ae0c2f1524cebfd9d304242f67006adfcf029fe89ba8376ad1f27e53305d37de", + "chksum_sha256": "5ec695e014db0f6c557988a54ce858da4e8bf30cbce5b8bafe3888ff3046fe4f", "format": 1 }, { @@ -4754,6 +6364,55 @@ "format": 1 }, { + "name": "tests/integration/targets/aci_aaa_key_ring", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, + "format": 1 + }, + { + "name": "tests/integration/targets/aci_aaa_key_ring/tasks", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, + "format": 1 + }, + { + "name": "tests/integration/targets/aci_aaa_key_ring/tasks/main.yml", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "96483c17928f4da918cea3324f23ecb083eaf820af2d4c0748e334ed42340c93", + "format": 1 + }, + { + "name": "tests/integration/targets/aci_aaa_key_ring/aliases", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "616f27a9a7bb49e561ef3782330e18d1a8cea3840e3166e798796684dd546a69", + "format": 1 + }, + { + "name": "tests/integration/targets/aci_aaa_key_ring/pki", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, + "format": 1 + }, + { + "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, @@ -4771,7 +6430,7 @@ "name": "tests/integration/targets/aci_fabric_span_dst_group/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "89f09f54b34b4070853e81358c3bfc5afcac772fec7c242cb6f4712960118340", + "chksum_sha256": "01015ad80e8bffebdc43dbbe5c3d7dea2a8d3e72a443f1b40b322048d1640608", "format": 1 }, { @@ -4799,7 +6458,7 @@ "name": "tests/integration/targets/aci_bgp_best_path_policy/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "bd01f327bd89e5f470bd0b9fc80e2a0246c42a9fd91de72285f6bca6aee14b85", + "chksum_sha256": "4869d34c6a9ec2f31b1a9e2992fd0c7ff2db1b05fe820e47be8a7f51bb3e574c", "format": 1 }, { @@ -4827,7 +6486,7 @@ "name": "tests/integration/targets/aci_fabric_node/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "11155626d26d8df736b01f6b694e7724cfb3edf8a1690474e77deda7bdbc0c1f", + "chksum_sha256": "312722a6556b1633da341e02bb311cda8fdd4774085b2bb886dc7ed892cd80fc", "format": 1 }, { @@ -4838,6 +6497,34 @@ "format": 1 }, { + "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_epg_useg_attribute_block_statement/tasks", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, + "format": 1 + }, + { + "name": "tests/integration/targets/aci_epg_useg_attribute_block_statement/tasks/main.yml", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "1b3e8a671dda2ec261dbc4084d65ff05654f61c79970a944fdf2f4760a312860", + "format": 1 + }, + { + "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_aep_to_domain", "ftype": "dir", "chksum_type": null, @@ -4855,7 +6542,7 @@ "name": "tests/integration/targets/aci_aep_to_domain/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "52a218b485aa23a4981d67fbbf2c7e7dd9c344f16e5fc19904f839f1f2d22dc2", + "chksum_sha256": "ef617648cf3b092fa334cb5b9a1cab0ed9b086b86598304306e33ec576ac0664", "format": 1 }, { @@ -4883,7 +6570,7 @@ "name": "tests/integration/targets/aci_dns_domain/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "5942d788bbbef1eacb07ff15c38c50de8c3f2f7dc6e80edd5efebcc193c1e1c4", + "chksum_sha256": "d7d7eab519cd4192a61605b934bb4c813872671117802804effd3732fd11531a", "format": 1 }, { @@ -4918,7 +6605,7 @@ "name": "tests/integration/targets/aci_encap_pool_range/tasks/vlan.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "345dbde8c63f84017b7eb34c35f034e9743ca0f185eddd3f7949671295488150", + "chksum_sha256": "194dffc2cabbf408c5039de01f0f01f0b5419538e6fde4b3d3e564d42ec8e5dd", "format": 1 }, { @@ -4932,7 +6619,7 @@ "name": "tests/integration/targets/aci_encap_pool_range/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "cade19307a5a902a3c840480d82e00ffd71173f3ca0ba5ba59d5c74cd8864085", + "chksum_sha256": "0018ba019fdc1fbff1df694d0a1e190b58b73682a8c63c93ac5143d0e2018f48", "format": 1 }, { @@ -4960,7 +6647,7 @@ "name": "tests/integration/targets/aci_aep_to_epg/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "a1e627a67befe9cc0f6faa1de4d1379e5ebde380bc124e285d153a7b5e7cae74", + "chksum_sha256": "da9bc3dc1d400e410025b424cd743b07e0cb4626de5372b2d495ddc702e1631d", "format": 1 }, { @@ -4988,7 +6675,7 @@ "name": "tests/integration/targets/aci_contract_export/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "194beab695bfb110bce199c3815786ae800384b41469a8dcb64bb724a5d34596", + "chksum_sha256": "9218e7b208662c098c4ebae5c850aa48872bb16daeed28d1d18895c8df68049f", "format": 1 }, { @@ -4999,6 +6686,34 @@ "format": 1 }, { + "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": "58c3b602a17925f8950bcda6c8244d12af1a72ddce3dd5f61b83ae32c4093994", + "format": 1 + }, + { + "name": "tests/integration/targets/aci_dhcp_option/aliases", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "616f27a9a7bb49e561ef3782330e18d1a8cea3840e3166e798796684dd546a69", + "format": 1 + }, + { "name": "tests/integration/targets/aci_tenant_ep_retention_policy", "ftype": "dir", "chksum_type": null, @@ -5016,7 +6731,7 @@ "name": "tests/integration/targets/aci_tenant_ep_retention_policy/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "843240370cdf77e385f381e5046df7655f88a4eb9843237c37b1d2b7339fd25e", + "chksum_sha256": "0e296f21257f52e78b0a77f0b832de6ebf7dadcaadc78c66d7ca322e146b286d", "format": 1 }, { @@ -5044,7 +6759,7 @@ "name": "tests/integration/targets/aci_interface_policy_ospf/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "9b9ba9779d76f78bb5e11c9486b65c3153fecae854844ff74734ffff8233002b", + "chksum_sha256": "27505847c69378b6d211c17fdee3a50f1057277c4eff07938949b3a264eadac3", "format": 1 }, { @@ -5055,6 +6770,34 @@ "format": 1 }, { + "name": "tests/integration/targets/aci_fabric_pod_profile", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, + "format": 1 + }, + { + "name": "tests/integration/targets/aci_fabric_pod_profile/tasks", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, + "format": 1 + }, + { + "name": "tests/integration/targets/aci_fabric_pod_profile/tasks/main.yml", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "23809735df7d7fe9bba12a715c73f150afca71eb6ed0f0eb7de21d90734eef1f", + "format": 1 + }, + { + "name": "tests/integration/targets/aci_fabric_pod_profile/aliases", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "616f27a9a7bb49e561ef3782330e18d1a8cea3840e3166e798796684dd546a69", + "format": 1 + }, + { "name": "tests/integration/targets/aci_tenant_span_src_group_to_dst_group", "ftype": "dir", "chksum_type": null, @@ -5072,7 +6815,7 @@ "name": "tests/integration/targets/aci_tenant_span_src_group_to_dst_group/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "74533cc1bb596adff756c3a691a9445e1f5c96655e6544426cd0e02e524207ac", + "chksum_sha256": "0f3e66721b1b44eec6526d09c3b4eac25012d866b3b91876d96c8bdf17314e38", "format": 1 }, { @@ -5083,6 +6826,34 @@ "format": 1 }, { + "name": "tests/integration/targets/aci_qos_dot1p_class", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, + "format": 1 + }, + { + "name": "tests/integration/targets/aci_qos_dot1p_class/tasks", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, + "format": 1 + }, + { + "name": "tests/integration/targets/aci_qos_dot1p_class/tasks/main.yml", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "d0c72b681c2d1e8907202f51dab724b455d84cf449fe3ddf8a06b12668650c9f", + "format": 1 + }, + { + "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_leaf_profile", "ftype": "dir", "chksum_type": null, @@ -5100,7 +6871,7 @@ "name": "tests/integration/targets/aci_fabric_leaf_profile/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "f41af177548f2ec1a66e496a62bc8fbe1e48098e48a20efd6f4fd27572722298", + "chksum_sha256": "0f6034365b07c13b284182fc8630c472055da2610e1d2b45959f4da55315acd0", "format": 1 }, { @@ -5128,7 +6899,7 @@ "name": "tests/integration/targets/aci_dhcp_relay/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "773df8a3cfbfbaf68a2c5de6619e9bf1ce6026d7f45b2e45c0025c4dd9ad6d1f", + "chksum_sha256": "ef953d743a99f4d89d3f095aa890c946aabc18555658b6c58dc29ebe19e8598a", "format": 1 }, { @@ -5156,7 +6927,7 @@ "name": "tests/integration/targets/aci_esg_epg_selector/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "37aaf2c1c23852f9bcf49957b45617ba513ed8218a3a7be31ee5f425bfd4cec6", + "chksum_sha256": "e983ab11ab93391be56423cb95cc3dd5a5f15af14d643c2f5444b63d8c038a61", "format": 1 }, { @@ -5184,7 +6955,7 @@ "name": "tests/integration/targets/aci_cloud_provider/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "d1b78c7fd6417e2c36752f6971e733888d0ac8386a10333ea1070bae55695fd2", + "chksum_sha256": "2f68d8433cc59f8a13c5d3ac288654986ee1f988b7266667aa9d1e5166cd462b", "format": 1 }, { @@ -5212,7 +6983,7 @@ "name": "tests/integration/targets/aci_l3out_bgp_peer/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "b58713b299f63cbc303b82df604713e8c1cf2702ed61b5b178461fad4c36e190", + "chksum_sha256": "59fe840ce233545a7a3565066949c258e4bab20372ccf9d6ccf0afc6a859c5fd", "format": 1 }, { @@ -5240,7 +7011,7 @@ "name": "tests/integration/targets/aci_esg/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "1caf56ec2b7f2e62fe63f79d6e2d0245b7013c18435a4614e88755423a16567e", + "chksum_sha256": "fe8d3096f7c246f57362d15eca011da984636a020c2078c2f11e78233797fdf2", "format": 1 }, { @@ -5268,7 +7039,7 @@ "name": "tests/integration/targets/aci_bgp_rr_node/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "ca6e2261d1df22ddd407932d30f07f324d995264a5f5b198a11a4f5dff9b9c63", + "chksum_sha256": "67668eb013645c8804596c2e49b7da0475b0ef8387afe3fc3892b42d3694c947", "format": 1 }, { @@ -5296,7 +7067,7 @@ "name": "tests/integration/targets/aci_aaa_domain/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "f70ba67fedbe15cdcd8d967d90ff9a188436898f610fb427a9ef312c5460c0f5", + "chksum_sha256": "6957a06dbf27ff890df7e769895f53ab731eabe43b4d70f59d299db3be09391b", "format": 1 }, { @@ -5307,6 +7078,34 @@ "format": 1 }, { + "name": "tests/integration/targets/aci_l3out_eigrp_interface_profile", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, + "format": 1 + }, + { + "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_l3out_eigrp_interface_profile/tasks/main.yml", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "cfa446df78e06fa818f43f0e123b395d90c91dfca4b5d2953a98273ce21a9954", + "format": 1 + }, + { + "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_file_remote_path", "ftype": "dir", "chksum_type": null, @@ -5324,7 +7123,7 @@ "name": "tests/integration/targets/aci_file_remote_path/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "be86a485a2200db58a988ec0095acb483fbc9d7710ff026c96d9ef780cb2fc5b", + "chksum_sha256": "fd5329b2fe47a12cd6b500a0275628e0fa48efacddf8a7fe0b61b4ef9bf58efc", "format": 1 }, { @@ -5366,7 +7165,7 @@ "name": "tests/integration/targets/aci_aaa_user/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "0a27716e570cda199712f2864aa28f6845cda283992a047be6e435d739c30ce0", + "chksum_sha256": "e5e0db5d28a70fb4d52e137fe34fa991f737c2c12c575591544c4ecdbfb4dc04", "format": 1 }, { @@ -5394,7 +7193,7 @@ "name": "tests/integration/targets/aci_epg_to_contract_master/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "6072b9a2c06b9f3dada60cf3b523afec718985b00c2df0279f4e05d4ecc5432e", + "chksum_sha256": "08fb777a7d079af0d1c0eb643663d7665c95306d1446e6d78363707ac3a91113", "format": 1 }, { @@ -5422,7 +7221,7 @@ "name": "tests/integration/targets/aci_cloud_external_epg/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "bc04416ef5a6af8c60f0aac74936413174b083df60b44b9a0fd9791d687c24e5", + "chksum_sha256": "da9bd98cd5fea7a9d6a76f97d9ae25672e99b41ce724772f1416c76e9d4dab82", "format": 1 }, { @@ -5433,6 +7232,34 @@ "format": 1 }, { + "name": "tests/integration/targets/aci_keychain_policy", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, + "format": 1 + }, + { + "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": "1b29eb0c2070e1985696d8d10e54ca601f191c9bd13e4a11f78763adf88307fb", + "format": 1 + }, + { + "name": "tests/integration/targets/aci_keychain_policy/aliases", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "616f27a9a7bb49e561ef3782330e18d1a8cea3840e3166e798796684dd546a69", + "format": 1 + }, + { "name": "tests/integration/targets/aci_firmware_policy", "ftype": "dir", "chksum_type": null, @@ -5450,7 +7277,7 @@ "name": "tests/integration/targets/aci_firmware_policy/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "cffeb0a042ff0bba5cceabcf4ddbf8a233ebba5620ae52ed5ea38bb392532cda", + "chksum_sha256": "97ffa299416e48106e1431b8a80ebbea3eeed0686cd575325904e166968ca291", "format": 1 }, { @@ -5478,7 +7305,7 @@ "name": "tests/integration/targets/aci_cloud_subnet/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "a8f69aafc42231d6fcbb8e12c3e233c4d5f197b36133a53e8044cb4e80544111", + "chksum_sha256": "f6533302e08342b9dad6391562828ecc98b02e63ee29d65b1f0e3481a74db713", "format": 1 }, { @@ -5506,7 +7333,7 @@ "name": "tests/integration/targets/aci_vrf/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "f8e835d03f2b31ef9aab370d7fca0b89b821069d50d7917aac1ab757d19acb09", + "chksum_sha256": "440e5baec2b38bc0940223c14b5e9fe8d42d391263f235b2e7df366c7ad0cac2", "format": 1 }, { @@ -5534,7 +7361,7 @@ "name": "tests/integration/targets/aci_filter/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "3b390892db7b692a7a98a480bc46de220a682a0f929ec268d1861a63cc11e870", + "chksum_sha256": "b1325b621500ac3780cc4932d57525ad50ebdabd8021eb82b2bc794a009f5fe8", "format": 1 }, { @@ -5562,7 +7389,7 @@ "name": "tests/integration/targets/aci_l3out_interface/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "d4d9c101d09159d2b36a82c35f8fbccbdc87a4f40651964eaa2b38e37696ee05", + "chksum_sha256": "a1f06a4e765dd38a0c5200098f40dc8822e1017ec9522674be2cae300a4ce746", "format": 1 }, { @@ -5590,7 +7417,7 @@ "name": "tests/integration/targets/aci_tenant_span_dst_group/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "ff4eb055593d4fff6ee7b8a530e750ec83e6bef96f7e30b01debdfc10a45a11b", + "chksum_sha256": "813febdbdf77a5cf80cae3cd76dc7ffd52b549a94870d439398c002a61d5c98e", "format": 1 }, { @@ -5618,7 +7445,7 @@ "name": "tests/integration/targets/aci_l3out_logical_interface_profile_ospf_policy/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "32b2fb5e9f361fc21865ef39c0ce3e989de8cad67c902bbe9f776e041f743f17", + "chksum_sha256": "9ed24f55a9eab4d00c8ac950a45c0fe36425fcaa041f346087f91565c787b7d4", "format": 1 }, { @@ -5646,7 +7473,7 @@ "name": "tests/integration/targets/aci_epg/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "67a517482b4a33dcab9d8bd8e4554e267418005c62a16f769382b58322395f25", + "chksum_sha256": "7090d0c8c60de535e912349131843b0b242409ea8ddf02306e9ada7517bbd190", "format": 1 }, { @@ -5674,7 +7501,7 @@ "name": "tests/integration/targets/aci_cloud_bgp_asn/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "8cca30820ec8be49ca48b9dc4ce95ed9de8e963abe364b9e5c7a6efa3e1ecc23", + "chksum_sha256": "ef83e2ea2fc6e2f8b16098634b11aaa0f6584ffe2e580e51063eafabf767b792", "format": 1 }, { @@ -5685,6 +7512,34 @@ "format": 1 }, { + "name": "tests/integration/targets/aci_fabric_external_routing_profile", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, + "format": 1 + }, + { + "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_fabric_external_routing_profile/tasks/main.yml", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "773ccf7db7e09cbaf3c76e92ae057c969ecb48e332510c4f7e6d169c970b27d7", + "format": 1 + }, + { + "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_fabric_span_src_group_src_path", "ftype": "dir", "chksum_type": null, @@ -5702,7 +7557,7 @@ "name": "tests/integration/targets/aci_fabric_span_src_group_src_path/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "36d0fe1f44db748661297e8588d6311dded74f304e8c43e1575ae67e31309031", + "chksum_sha256": "c45de6f0f5ba988c452296375b81d51d2b2afc549b3af9fd8fe201e984d204bd", "format": 1 }, { @@ -5730,7 +7585,7 @@ "name": "tests/integration/targets/aci_fabric_span_src_group_src/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "7376aad0adce8582bb048f45bb6999bef5e4c0bd92b879ca9818b3a34af60596", + "chksum_sha256": "11d0d775fa82a716293db5881ef1a37c57f6e2a964dfeb687af2679560e4bade", "format": 1 }, { @@ -5758,7 +7613,7 @@ "name": "tests/integration/targets/aci_tenant_span_src_group/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "50933aa768540483691d9a20c4c1a15aa1d8af1f46513544d747f73abb84bcca", + "chksum_sha256": "7867b37ef567e6e844044a69229948b32007f26f9764787e8e8c5d36db630ce7", "format": 1 }, { @@ -5786,7 +7641,7 @@ "name": "tests/integration/targets/aci_config_export_policy/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "aa4ba50ca5446ff9d640b396c474dde2f5e0feb65eecb9e91db4aeb4d1eadd38", + "chksum_sha256": "c6d87fc399a3e571a7bf452696d3070b88b7020f08b3bd95e923bfae4009f38b", "format": 1 }, { @@ -5814,7 +7669,7 @@ "name": "tests/integration/targets/aci_cloud_epg_selector/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "f8b04b64f325492a0dd9e7c31568ffe2214b81f289ce9a96557d7ec4272fb592", + "chksum_sha256": "8d57d82be914fa88e07bc41d7bb244e02734ed6aac76a92bfc10977d5e69c33c", "format": 1 }, { @@ -5842,7 +7697,7 @@ "name": "tests/integration/targets/aci_epg_to_contract_interface/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "05e64f0bd49cf86a4f884c5816b2061d3bc79734d4c5549c084200777ce08579", + "chksum_sha256": "1c312538c0a8394a8aeb46f742e8d42a78f7e21eb7eb45baac278ea65357dea1", "format": 1 }, { @@ -5870,7 +7725,7 @@ "name": "tests/integration/targets/aci_system_endpoint_controls/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "d38cac5f1adb2065455a24ba14eeb63e9798c2d7beb71ec609b7aa2c24a57ed6", + "chksum_sha256": "5607830b2d7127241067d32fde8ad7074d75750f37b8fdd49ace1d8647d791e5", "format": 1 }, { @@ -5898,7 +7753,7 @@ "name": "tests/integration/targets/aci_l3out_interface_secondary_ip/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "f0f185cc60c0b1d032084324e53847b3c3dddd21b4a3cb03db5883490a764e0c", + "chksum_sha256": "2afa0e99471843228a5cf1a7459c2fc764b647318621416d6af001e72f31eb20", "format": 1 }, { @@ -5926,7 +7781,7 @@ "name": "tests/integration/targets/aci_static_binding_to_epg/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "3c12648b939c15bfbd8a35c6483db89011dbccd407961c4d41215ca270a71971", + "chksum_sha256": "48503f32dc4d09af6a416cb2697c5d1e50e86df3ef869cdabd889efb91d80444", "format": 1 }, { @@ -5937,6 +7792,34 @@ "format": 1 }, { + "name": "tests/integration/targets/aci_l3out_floating_svi_path", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, + "format": 1 + }, + { + "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_l3out_floating_svi_path/tasks/main.yml", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "e939e6263c6afc549ceaba38d1c3885bebd2e13f3fc6e82cc524dcab8848fc72", + "format": 1 + }, + { + "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_vmm_uplink", "ftype": "dir", "chksum_type": null, @@ -5954,7 +7837,7 @@ "name": "tests/integration/targets/aci_vmm_uplink/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "35981a27594dc20c90e735f385654aff3bd3be4a968645356b9edc96a24bfa19", + "chksum_sha256": "e68d4a1637bd4faec127d03539b84dcf8df2cd4f04f4d2ee54a8e6ee3f79e486", "format": 1 }, { @@ -5982,7 +7865,7 @@ "name": "tests/integration/targets/aci_firmware_group_node/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "c3e4f4978c8f104052bd17ebd014e836998899f4f807661656accefbf40e19fc", + "chksum_sha256": "91e40267ec7fcf8abd83cccda6005ac1cd79563ad8294a7a3424ada8cd4d1de7", "format": 1 }, { @@ -6010,7 +7893,7 @@ "name": "tests/integration/targets/aci_bgp_timers_policy/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "e1e28cfb914f228702667f03f8a265f9b869f13e6766c767a90e8edb0166762b", + "chksum_sha256": "6f414d5bdd980d5bc0683477eccf0068024b2840faa09cd22756ae6ffef09866", "format": 1 }, { @@ -6038,7 +7921,7 @@ "name": "tests/integration/targets/aci_access_span_filter_group/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "f670f47ac966f70d906c6b18d446b8e45984dd6e504d3b64bd480b5b28fccda9", + "chksum_sha256": "6dd4fd944b408971bfdb832ca9ddca613c84215afd429a31fc0f6a3942b67e8c", "format": 1 }, { @@ -6066,7 +7949,7 @@ "name": "tests/integration/targets/aci_l2out_extepg_to_contract/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "298360f809920f82f95eee117e53bfb6046d844d36f443e1d4e666cde742fbde", + "chksum_sha256": "8412f7fab3416a00fde4db461cfef7664d415505f3f5226ba65b6b6b2a0e2830", "format": 1 }, { @@ -6094,7 +7977,7 @@ "name": "tests/integration/targets/aci_system_global_aes_passphrase_encryption/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "ae783a7828434afa0de8e616e3e9ecfe84317763a28203beeba2aff1b63bcd55", + "chksum_sha256": "899d51d6e65dade49ddda996d828b8c246c4aa847400460253c7ee240a912f94", "format": 1 }, { @@ -6122,7 +8005,7 @@ "name": "tests/integration/targets/aci_aaa_user_certificate/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "de23c78bd0da077a2e5259699d1c861ca6c9ed0b161398c068c74fc95e31d59c", + "chksum_sha256": "199c9a55602b3f78f352c659379e413b9c4578ee27e82fc8b61bc1f870c2b6d5", "format": 1 }, { @@ -6206,7 +8089,7 @@ "name": "tests/integration/targets/aci_cloud_ctx_profile/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "c3244f45def81cbee17c3643e20b46e448c6740ff821bf0d37d2e8877d464c8a", + "chksum_sha256": "30aa6efad91c5732bce45da24f742a50dfc29ed56c7354dcd1dd3eac347c3784", "format": 1 }, { @@ -6234,7 +8117,7 @@ "name": "tests/integration/targets/aci_tenant_action_rule_profile/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "8a81f5e051113d70e75f90145d1d81cd6444922e3d38b0131d1e6601f7816dbd", + "chksum_sha256": "d404d98736d155e056fe35c47c91e155e160324994e69a6f555ec8705f34e2d1", "format": 1 }, { @@ -6262,7 +8145,7 @@ "name": "tests/integration/targets/aci_aaa_user_role/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "56d48ff0dec763a6c52d2d1f7e8c1fbf495e366ca4979d29b9c1178d3d135735", + "chksum_sha256": "3a5db07a207f6b1d4dea828953eccffde4a61d9c02064af4db569867b918f553", "format": 1 }, { @@ -6273,6 +8156,34 @@ "format": 1 }, { + "name": "tests/integration/targets/aci_bfd_multihop_node_policy", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, + "format": 1 + }, + { + "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_bfd_multihop_node_policy/tasks/main.yml", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "d008e5ceb983a17bb32d6788349c2e915a973edd2d4eb87e4cbb9f7da2b13aed", + "format": 1 + }, + { + "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_bgp_rr_asn", "ftype": "dir", "chksum_type": null, @@ -6290,7 +8201,7 @@ "name": "tests/integration/targets/aci_bgp_rr_asn/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "d91c2f2511cc599bfec0aad23925038f00045fe03ce492af6ab1b2bec2bed73f", + "chksum_sha256": "664c54c3392957c332451d9a1183860fa2e606c9892beb918d65f9e195dbb612", "format": 1 }, { @@ -6318,7 +8229,7 @@ "name": "tests/integration/targets/aci_contract_subject/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "f545c12b34c65b8f84356ddf1ac88a8038a6b9010d32567eef65976c86001096", + "chksum_sha256": "b2e2ef790915f6b82210707684804b4b87ea0a7231906446fed594e5539763d3", "format": 1 }, { @@ -6346,7 +8257,7 @@ "name": "tests/integration/targets/aci_l2out_extepg/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "5132135607c61b28d1b345e749441939fc7673970a1fe788692840bedd383a66", + "chksum_sha256": "9a64487a93a84b5d75b09d109eb24358a1b36ac88ead16a2dd9d083c7ea932a6", "format": 1 }, { @@ -6357,6 +8268,34 @@ "format": 1 }, { + "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_bgp_address_family_context_policy/tasks", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, + "format": 1 + }, + { + "name": "tests/integration/targets/aci_bgp_address_family_context_policy/tasks/main.yml", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "ec5d52ebe05821de9002324ce8868d780c2d8e67f1a364439113771225d44120", + "format": 1 + }, + { + "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_l3out_static_routes", "ftype": "dir", "chksum_type": null, @@ -6374,7 +8313,7 @@ "name": "tests/integration/targets/aci_l3out_static_routes/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "4b42b52c3a3a19c551fc82081e676952c8a08e778a9c3fdd3e4dc4a508e458c1", + "chksum_sha256": "cb6d8cf3197e1a320d278c77ee62e6e273a89d3cec7f1c4492dc46bc13952ff0", "format": 1 }, { @@ -6402,7 +8341,7 @@ "name": "tests/integration/targets/aci_cloud_zone/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "b06e53f5f18332fe1f6c2e00cb62c1d78ae10851aea950be32a945e28cad72a4", + "chksum_sha256": "6c157a960cbb53511ca4b65c8c15c8ba14a9ac55dfe374195e4216ff24a91d44", "format": 1 }, { @@ -6430,7 +8369,7 @@ "name": "tests/integration/targets/aci_switch_leaf_selector/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "522658a23ac16892e9e82fc69f7b4afd930e26dfc02ad82b3e93c95d0181461a", + "chksum_sha256": "2d806125c2e70e3fdd5cb182de4560a4dfb097aacd506d2de6c7337069672ab0", "format": 1 }, { @@ -6458,7 +8397,7 @@ "name": "tests/integration/targets/aci_aaa_user_domain/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "a2ab7a16b4d545e99c973b926d28fb765c480cd3e21587a129d29ba18a9c1255", + "chksum_sha256": "ae53b1118c33169250cd58a3414485bf90bcbce33fd322a93e91a63dd8a36205", "format": 1 }, { @@ -6469,6 +8408,34 @@ "format": 1 }, { + "name": "tests/integration/targets/aci_l3out_bfd_interface_profile", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, + "format": 1 + }, + { + "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_l3out_bfd_interface_profile/tasks/main.yml", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "fcaba6dbbd06bc810cf1a384017a895c0b4182cf60d20dfde9dc9fcab27859ac", + "format": 1 + }, + { + "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_fabric_spine_profile", "ftype": "dir", "chksum_type": null, @@ -6486,7 +8453,7 @@ "name": "tests/integration/targets/aci_fabric_spine_profile/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "8c7831e91043717924a30d223bdf42efd52198261270595dc1cd0e3b3a4d4d5f", + "chksum_sha256": "c6f9c12ac6b7d9eb27202617560fa2c7f6de2b246e3e5bf0d2afa3d20af23ff4", "format": 1 }, { @@ -6497,6 +8464,34 @@ "format": 1 }, { + "name": "tests/integration/targets/aci_fabric_pod_connectivity_profile", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, + "format": 1 + }, + { + "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_fabric_pod_connectivity_profile/tasks/main.yml", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "91495c491ee2f353f10948002561caa645366aa118d0a3c4bd8fed1855287b91", + "format": 1 + }, + { + "name": "tests/integration/targets/aci_fabric_pod_connectivity_profile/aliases", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "616f27a9a7bb49e561ef3782330e18d1a8cea3840e3166e798796684dd546a69", + "format": 1 + }, + { "name": "tests/integration/targets/aci_l3out_logical_node", "ftype": "dir", "chksum_type": null, @@ -6514,7 +8509,7 @@ "name": "tests/integration/targets/aci_l3out_logical_node/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "4607bdbef2f2b481fe393e457c18ba02c78af0b6d16f1d53c84e69c0057d30d0", + "chksum_sha256": "914550f2ff9cdabdce76de3706f87f5a13f48b223742d5fbba78728f21d3b1ee", "format": 1 }, { @@ -6525,6 +8520,62 @@ "format": 1 }, { + "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_action_rule_set_as_path_asn/tasks", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, + "format": 1 + }, + { + "name": "tests/integration/targets/aci_action_rule_set_as_path_asn/tasks/main.yml", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "7ae345cd77046a57a7f8e630459ab04b6252c60104548db9854fd3963fdcbd1d", + "format": 1 + }, + { + "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_filter_listify", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, + "format": 1 + }, + { + "name": "tests/integration/targets/aci_filter_listify/tasks", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, + "format": 1 + }, + { + "name": "tests/integration/targets/aci_filter_listify/tasks/main.yml", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "4ebd342b364c0bcd4d7458cabd4cbcf98eda3188fedc289375cbee648d18c45e", + "format": 1 + }, + { + "name": "tests/integration/targets/aci_filter_listify/aliases", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "616f27a9a7bb49e561ef3782330e18d1a8cea3840e3166e798796684dd546a69", + "format": 1 + }, + { "name": "tests/integration/targets/aci_cloud_region", "ftype": "dir", "chksum_type": null, @@ -6542,7 +8593,7 @@ "name": "tests/integration/targets/aci_cloud_region/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "07c218a26eba7b984743300e0c8292dc9dbda9000d4cb22a3216a3abb1dc18ed", + "chksum_sha256": "d03c2da42e15fc3b0c84a0b1b69bdac0c21fd13d7f640f9b28bd1a10449e5d5b", "format": 1 }, { @@ -6553,6 +8604,34 @@ "format": 1 }, { + "name": "tests/integration/targets/aci_access_spine_switch_selector", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, + "format": 1 + }, + { + "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_access_spine_switch_selector/tasks/main.yml", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "03c68b11627cec5057b89e00004d3f15f458e014ef267c78626d27f8ca7e6488", + "format": 1 + }, + { + "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_route_control_context", "ftype": "dir", "chksum_type": null, @@ -6570,7 +8649,7 @@ "name": "tests/integration/targets/aci_route_control_context/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "54fcba37e0a385af9767ffaa2740fd81458fc3cee008e017ec702f8162f18e70", + "chksum_sha256": "c06ebb912f21867917c48d6200c05a5a9c193aacd430899bd63c35e5f6685bca", "format": 1 }, { @@ -6598,7 +8677,7 @@ "name": "tests/integration/targets/aci_switch_policy_leaf_profile/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "71c9bc35fe283b8c8ca37f65c12ac529328987b60b799c48c2ded27832452f35", + "chksum_sha256": "6e48f8298d81dadd34c82e6f4909b4e8502eeeabd9e37debe57bb7538d2a8180", "format": 1 }, { @@ -6626,7 +8705,7 @@ "name": "tests/integration/targets/aci_vmm_vswitch_policy/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "097f845417dd0d363abacdf65fc8915762f05b878e6b628d3be3504f4edef7c6", + "chksum_sha256": "913426c8878960f24280848e6ceda7c2193f6576dbe043b956be207cb23b24aa", "format": 1 }, { @@ -6654,7 +8733,7 @@ "name": "tests/integration/targets/aci_syslog_source/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "201852b3cc6e35b2452031b52492754e0824fc6b6beefbf1afa676b7a4c4edb9", + "chksum_sha256": "1aa926ceea4e53ecff3632cc8251c721993d96bd323dc4160543b24bb7f7671b", "format": 1 }, { @@ -6682,14 +8761,14 @@ "name": "tests/integration/targets/aci_vmm_credential/tasks/vmware.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "68f594ddc8d654e2e02c8283a476b9bd5d66299f56bf71081b741b6f4c38efe4", + "chksum_sha256": "e4b4bf1a18cb208a79c4e698474729cad83c54ab24130553de53ddd95262080b", "format": 1 }, { "name": "tests/integration/targets/aci_vmm_credential/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "3160edcdbd1b730523e2239ca29b9ce2050d22d65028504573171f59b2a62e82", + "chksum_sha256": "e56710bf76207c9a80e3fcb62d230acd20b749db044ed8c6080744cd7fdea667", "format": 1 }, { @@ -6745,7 +8824,7 @@ "name": "tests/integration/targets/aci_switch_policy_vpc_protection_group/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "094faa7b08d4d132f470f233ab465a9ee16a6d37d7a5ac76d352cdef966533ea", + "chksum_sha256": "d36cb34648ae0539a22d1e5195610d2f2b51a905607af531fbea0309f1513216", "format": 1 }, { @@ -6756,6 +8835,34 @@ "format": 1 }, { + "name": "tests/integration/targets/aci_netflow_record_policy", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, + "format": 1 + }, + { + "name": "tests/integration/targets/aci_netflow_record_policy/tasks", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, + "format": 1 + }, + { + "name": "tests/integration/targets/aci_netflow_record_policy/tasks/main.yml", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "329bae5d9ca559cd2a7a964cb692775a6f9fda68d3ecb1fa9c759ad9c42cc800", + "format": 1 + }, + { + "name": "tests/integration/targets/aci_netflow_record_policy/aliases", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "616f27a9a7bb49e561ef3782330e18d1a8cea3840e3166e798796684dd546a69", + "format": 1 + }, + { "name": "tests/integration/targets/aci_igmp_interface_policy", "ftype": "dir", "chksum_type": null, @@ -6773,7 +8880,7 @@ "name": "tests/integration/targets/aci_igmp_interface_policy/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "4494f102e844ea6ff5c82c65daecef0b968b1e7f1b6109e55b015240e579fd16", + "chksum_sha256": "427b44e1d879dc625fff8fe46745130443253f461e918f614ebe9c943fdca45d", "format": 1 }, { @@ -6801,7 +8908,7 @@ "name": "tests/integration/targets/aci_aaa_role/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "421a7230dbd68e1e8a0ae78052502bcacc51e4873bfe24bd138004b4f340e60b", + "chksum_sha256": "f31f4e475199f346f8e3b5ef4da7fc19661e7af0a57701849ed9af132a5cb614", "format": 1 }, { @@ -6829,7 +8936,7 @@ "name": "tests/integration/targets/aci_static_node_mgmt_address/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "76354f4a25f3daeb76b8f8929c15c97d6822ed0c5cda61a2a5b6a4ca9932da52", + "chksum_sha256": "e8a5c433aef22455527758f03430c2e87aad859904f2c804b9f0ae735fc6f4f4", "format": 1 }, { @@ -6857,7 +8964,7 @@ "name": "tests/integration/targets/aci_config_rollback/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "6d4937bb22c5f4a4a7fe5771ba24fabaa8f0961137cf6811726fb2e07f02f9f5", + "chksum_sha256": "472c0fb98c3cf9edb626192d2481c896d11d1184503d873353ff8d7e4813223d", "format": 1 }, { @@ -6885,7 +8992,7 @@ "name": "tests/integration/targets/aci_interface_policy_port_security/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "5b4022adb62fa72c4942d6104977f94bc734486be02f53ddb5cae1ceffc61371", + "chksum_sha256": "f8c9744d1187e4d9f67cf1215af9f540d6cd1e7be7839a1c437d2a8392cc07e8", "format": 1 }, { @@ -6896,6 +9003,34 @@ "format": 1 }, { + "name": "tests/integration/targets/aci_l3out_floating_svi", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, + "format": 1 + }, + { + "name": "tests/integration/targets/aci_l3out_floating_svi/tasks", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, + "format": 1 + }, + { + "name": "tests/integration/targets/aci_l3out_floating_svi/tasks/main.yml", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "f03579a734119e7e928a7155c37e13075d716b45b5a4457074bfe1b8012f1e4a", + "format": 1 + }, + { + "name": "tests/integration/targets/aci_l3out_floating_svi/aliases", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "616f27a9a7bb49e561ef3782330e18d1a8cea3840e3166e798796684dd546a69", + "format": 1 + }, + { "name": "tests/integration/targets/aci_access_span_filter_group_entry", "ftype": "dir", "chksum_type": null, @@ -6913,7 +9048,7 @@ "name": "tests/integration/targets/aci_access_span_filter_group_entry/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "2bb778f87e5538a417e3629d1545ea4995df371213a705e81956e0497b86f9a7", + "chksum_sha256": "b2f5e1a7ae93be81c9a06807167c50ed2c19388765d2345be14b97ea28ba4c7d", "format": 1 }, { @@ -6941,7 +9076,7 @@ "name": "tests/integration/targets/aci_system/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "38c9cb66642f19daee872411bd6dc8df26d1ab38edad0c521397557003124ac4", + "chksum_sha256": "76e7fd03254cda8d4cadea91be613f9b77ec590c14a09d13e322b4264ff0651e", "format": 1 }, { @@ -6952,6 +9087,34 @@ "format": 1 }, { + "name": "tests/integration/targets/aci_pim_route_map_policy", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, + "format": 1 + }, + { + "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_pim_route_map_policy/tasks/main.yml", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "acae8cf67565eb38722387ce99c02bb793670d98086b73830596f6031661379c", + "format": 1 + }, + { + "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_epg_subnet", "ftype": "dir", "chksum_type": null, @@ -6969,7 +9132,7 @@ "name": "tests/integration/targets/aci_epg_subnet/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "88b56f6acb0c44928cab5e4b92aaf89a13a592bc7d1e0b88f70515743e29e624", + "chksum_sha256": "cebd3d119809c5f2ec21749d192c2ada5934a0f1e26d3d5f5ca08e6cae6fe946", "format": 1 }, { @@ -6997,7 +9160,7 @@ "name": "tests/integration/targets/aci_interface_policy_spanning_tree/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "04a8da39c4907965a8fcde343dd74c02f1dc4963d9ba8ed98d08ec90a95340e8", + "chksum_sha256": "bf5f4904bc4ce5d96a7af20f61d8b3f107cd89aa83ca310c94c4aa2978cf358e", "format": 1 }, { @@ -7008,6 +9171,34 @@ "format": 1 }, { + "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_bd_to_netflow_monitor_policy/tasks", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, + "format": 1 + }, + { + "name": "tests/integration/targets/aci_bd_to_netflow_monitor_policy/tasks/main.yml", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "082dfca281ac7354249b0bc7e8695278ca69428044f37989c5a3ea482460372c", + "format": 1 + }, + { + "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_fabric_interface_policy_group", "ftype": "dir", "chksum_type": null, @@ -7025,7 +9216,7 @@ "name": "tests/integration/targets/aci_fabric_interface_policy_group/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "827c31fe1653a6a1609f63e81ff2387defe400094845091b89f9b22ae5f536b8", + "chksum_sha256": "e49d3ab8dc00b23ced354238f15530310af0f86643a79d3d7264aba9fb3f8600", "format": 1 }, { @@ -7036,6 +9227,48 @@ "format": 1 }, { + "name": "tests/integration/targets/aci_aaa_certificate_authority", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, + "format": 1 + }, + { + "name": "tests/integration/targets/aci_aaa_certificate_authority/tasks", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, + "format": 1 + }, + { + "name": "tests/integration/targets/aci_aaa_certificate_authority/tasks/main.yml", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "a28a838e0ac37e529e9b2d07a23aa641181eec92493e7ae1f20ff6e8f007829d", + "format": 1 + }, + { + "name": "tests/integration/targets/aci_aaa_certificate_authority/aliases", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "616f27a9a7bb49e561ef3782330e18d1a8cea3840e3166e798796684dd546a69", + "format": 1 + }, + { + "name": "tests/integration/targets/aci_aaa_certificate_authority/pki", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, + "format": 1 + }, + { + "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, @@ -7053,7 +9286,7 @@ "name": "tests/integration/targets/aci_match_as_path_regex_term/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "c80e4ffc685fcdc906015246d0d97a767f81e3e76531b08571ed9033f0791dbb", + "chksum_sha256": "3e2a11094eae846a760da9b46d13d900c6cb4c74d5d120ae6ad81ad1cf3fccc2", "format": 1 }, { @@ -7064,6 +9297,34 @@ "format": 1 }, { + "name": "tests/integration/targets/aci_fabric_pod_external_tep", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, + "format": 1 + }, + { + "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_fabric_pod_external_tep/tasks/main.yml", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "d7eaf53338446482dd5fa4fe5140cc31e54b3601bc8453db94dccbde15690cbc", + "format": 1 + }, + { + "name": "tests/integration/targets/aci_fabric_pod_external_tep/aliases", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "616f27a9a7bb49e561ef3782330e18d1a8cea3840e3166e798796684dd546a69", + "format": 1 + }, + { "name": "tests/integration/targets/aci_bd_dhcp_label", "ftype": "dir", "chksum_type": null, @@ -7081,7 +9342,7 @@ "name": "tests/integration/targets/aci_bd_dhcp_label/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "e3479a63f7af0ecb0d46bbf2052d4dc3591acaac7ed031c599b4041766f3e34d", + "chksum_sha256": "30093f02b96084749a02daa955a8b2a71a3086d069340a0d885a8c48e16b54bb", "format": 1 }, { @@ -7092,6 +9353,62 @@ "format": 1 }, { + "name": "tests/integration/targets/aci_qos_custom_policy", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, + "format": 1 + }, + { + "name": "tests/integration/targets/aci_qos_custom_policy/tasks", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, + "format": 1 + }, + { + "name": "tests/integration/targets/aci_qos_custom_policy/tasks/main.yml", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "13b956ae3c20c1479e51191caf501a84bb8749ce2fe6116ba1f1d693b6252ce7", + "format": 1 + }, + { + "name": "tests/integration/targets/aci_qos_custom_policy/aliases", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "616f27a9a7bb49e561ef3782330e18d1a8cea3840e3166e798796684dd546a69", + "format": 1 + }, + { + "name": "tests/integration/targets/aci_bgp_peer_prefix_policy", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, + "format": 1 + }, + { + "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_bgp_peer_prefix_policy/tasks/main.yml", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "beda6e7ae2ba6b0f606bbf28ac41e5f08cdcc0d758ce0232579799a79910682f", + "format": 1 + }, + { + "name": "tests/integration/targets/aci_bgp_peer_prefix_policy/aliases", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "616f27a9a7bb49e561ef3782330e18d1a8cea3840e3166e798796684dd546a69", + "format": 1 + }, + { "name": "tests/integration/targets/aci_dns_profile", "ftype": "dir", "chksum_type": null, @@ -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 }, { @@ -7330,6 +9647,27 @@ "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", "chksum_type": "sha256", @@ -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 }, { @@ -7428,6 +9766,34 @@ "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", "chksum_type": null, @@ -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) <dag@wieers.com>", "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) <dag@wieers.com> # Copyright: (c) 2017, Swetha Chunduri (@schunduri) +# Copyright: (c) 2024, Samita Bhattacharjee (@samiib) <samitab@cisco.com> # GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) from __future__ import absolute_import, division, print_function @@ -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 <rsmeyers@cisco.com> +# Copyright: (c) 2023, Shreyas Srish <ssrish@cisco.com> +# Copyright: (c) 2024, Akini Ross <akinross@cisco.com> +# 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: '<?xml version="1.0" encoding="UTF-8"?><imdata totalCount="1"><error code="122" text="unknown managed object class foo"/></imdata>' +sent: + description: The actual/minimal configuration pushed to the APIC + returned: info + type: list + sample: + { + "fvTenant": { + "attributes": { + "descr": "Production environment" + } + } + } +previous: + description: The original configuration from the APIC before the module has started + returned: info + type: list + sample: + [ + { + "fvTenant": { + "attributes": { + "descr": "Production", + "dn": "uni/tn-production", + "name": "production", + "nameAlias": "", + "ownerKey": "", + "ownerTag": "" + } + } + } + ] +proposed: + description: The assembled configuration from the user-provided parameters + returned: info + type: dict + sample: + { + "fvTenant": { + "attributes": { + "descr": "Production environment", + "name": "production" + } + } + } +filter_string: + description: The filter string used for the request + returned: failure or debug + type: str + sample: ?rsp-prop-include=config-only +method: + description: The HTTP method used for the request to the APIC + returned: failure or debug + type: str + sample: POST +response: + description: The HTTP response from the APIC + returned: failure or debug + type: str + sample: OK (30 bytes) +status: + description: The HTTP status from the APIC + returned: failure or debug + type: int + sample: 200 +url: + description: The HTTP url used for the request to the APIC + returned: failure or debug + type: str + sample: https://10.11.12.13/api/mo/uni/tn-production.json +""" + + +# 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) <anvjain@cisco.com> # Copyright: (c) 2023, Gaspard Micol (@gmicol) <gmicol@cisco.com> # Copyright: (c) 2023, Shreyas Srish (@shrsr) <ssrish@cisco.com> +# Copyright: (c) 2023, Tim Cragg (@timcragg) <tcragg@cisco.com> +# Copyright: (c) 2024, Samita Bhattacharjee (@samiib) <samitab@cisco.com> # 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) <akinross@cisco.com> +# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) + +from __future__ import absolute_import, division, print_function + +__metaclass__ = type + +ANSIBLE_METADATA = {"metadata_version": "1.1", "status": ["preview"], "supported_by": "certified"} + +DOCUMENTATION = r""" +--- +module: aci_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: '<?xml version="1.0" encoding="UTF-8"?><imdata totalCount="1"><error code="122" text="unknown managed object class foo"/></imdata>' +sent: + description: The actual/minimal configuration pushed to the APIC + returned: info + type: list + sample: + { + "fvTenant": { + "attributes": { + "descr": "Production environment" + } + } + } +previous: + description: The original configuration from the APIC before the module has started + returned: info + type: list + sample: + [ + { + "fvTenant": { + "attributes": { + "descr": "Production", + "dn": "uni/tn-production", + "name": "production", + "nameAlias": "", + "ownerKey": "", + "ownerTag": "" + } + } + } + ] +proposed: + description: The assembled configuration from the user-provided parameters + returned: info + type: dict + sample: + { + "fvTenant": { + "attributes": { + "descr": "Production environment", + "name": "production" + } + } + } +filter_string: + description: The filter string used for the request + returned: failure or debug + type: str + sample: ?rsp-prop-include=config-only +method: + description: The HTTP method used for the request to the APIC + returned: failure or debug + type: str + sample: POST +response: + description: The HTTP response from the APIC + returned: failure or debug + type: str + sample: OK (30 bytes) +status: + description: The HTTP status from the APIC + returned: failure or debug + type: int + sample: 200 +url: + description: The HTTP url used for the request to the APIC + returned: failure or debug + type: str + sample: https://10.11.12.13/api/mo/uni/tn-production.json +""" + +from ansible.module_utils.basic import AnsibleModule +from ansible_collections.cisco.aci.plugins.module_utils.aci import ACIModule, aci_argument_spec, aci_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) <akinross@cisco.com> +# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) + +from __future__ import absolute_import, division, print_function + +__metaclass__ = type + +ANSIBLE_METADATA = {"metadata_version": "1.1", "status": ["preview"], "supported_by": "certified"} + +DOCUMENTATION = r""" +--- +module: aci_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: '<?xml version="1.0" encoding="UTF-8"?><imdata totalCount="1"><error code="122" text="unknown managed object class foo"/></imdata>' +sent: + description: The actual/minimal configuration pushed to the APIC + returned: info + type: list + sample: + { + "fvTenant": { + "attributes": { + "descr": "Production environment" + } + } + } +previous: + description: The original configuration from the APIC before the module has started + returned: info + type: list + sample: + [ + { + "fvTenant": { + "attributes": { + "descr": "Production", + "dn": "uni/tn-production", + "name": "production", + "nameAlias": "", + "ownerKey": "", + "ownerTag": "" + } + } + } + ] +proposed: + description: The assembled configuration from the user-provided parameters + returned: info + type: dict + sample: + { + "fvTenant": { + "attributes": { + "descr": "Production environment", + "name": "production" + } + } + } +filter_string: + description: The filter string used for the request + returned: failure or debug + type: str + sample: ?rsp-prop-include=config-only +method: + description: The HTTP method used for the request to the APIC + returned: failure or debug + type: str + sample: POST +response: + description: The HTTP response from the APIC + returned: failure or debug + type: str + sample: OK (30 bytes) +status: + description: The HTTP status from the APIC + returned: failure or debug + type: int + sample: 200 +url: + description: The HTTP url used for the request to the APIC + returned: failure or debug + type: str + sample: https://10.11.12.13/api/mo/uni/tn-production.json +""" + +from ansible.module_utils.basic import AnsibleModule +from ansible_collections.cisco.aci.plugins.module_utils.aci import ACIModule, aci_argument_spec, aci_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) <akinross@cisco.com> +# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) + +from __future__ import absolute_import, division, print_function + +__metaclass__ = type + +ANSIBLE_METADATA = {"metadata_version": "1.1", "status": ["preview"], "supported_by": "certified"} + +DOCUMENTATION = r""" +--- +module: aci_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: '<?xml version="1.0" encoding="UTF-8"?><imdata totalCount="1"><error code="122" text="unknown managed object class foo"/></imdata>' +sent: + description: The actual/minimal configuration pushed to the APIC + returned: info + type: list + sample: + { + "fvTenant": { + "attributes": { + "descr": "Production environment" + } + } + } +previous: + description: The original configuration from the APIC before the module has started + returned: info + type: list + sample: + [ + { + "fvTenant": { + "attributes": { + "descr": "Production", + "dn": "uni/tn-production", + "name": "production", + "nameAlias": "", + "ownerKey": "", + "ownerTag": "" + } + } + } + ] +proposed: + description: The assembled configuration from the user-provided parameters + returned: info + type: dict + sample: + { + "fvTenant": { + "attributes": { + "descr": "Production environment", + "name": "production" + } + } + } +filter_string: + description: The filter string used for the request + returned: failure or debug + type: str + sample: ?rsp-prop-include=config-only +method: + description: The HTTP method used for the request to the APIC + returned: failure or debug + type: str + sample: POST +response: + description: The HTTP response from the APIC + returned: failure or debug + type: str + sample: OK (30 bytes) +status: + description: The HTTP status from the APIC + returned: failure or debug + type: int + sample: 200 +url: + description: The HTTP url used for the request to the APIC + returned: failure or debug + type: str + sample: https://10.11.12.13/api/mo/uni/tn-production.json +""" + +from ansible.module_utils.basic import AnsibleModule +from ansible_collections.cisco.aci.plugins.module_utils.aci import ACIModule, aci_argument_spec, aci_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 <smnmtzgr@gmail.com> # Copyright: (c) 2020, Shreyas Srish <ssrish@cisco.com> # Copyright: (c) 2020, Zak Lantz (@manofcolombia) <zakodewald@gmail.com> +# Copyright: (c) 2024, Gaspard Micol (@gmicol) <gmicol@cisco.com> # GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) from __future__ import absolute_import, division, print_function @@ -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) <gmicol@cisco.com> +# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) + +from __future__ import absolute_import, division, print_function + +__metaclass__ = type + +ANSIBLE_METADATA = { + "metadata_version": "1.1", + "status": ["preview"], + "supported_by": "certified", +} + +DOCUMENTATION = r""" +--- +module: aci_access_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: '<?xml version="1.0" encoding="UTF-8"?><imdata totalCount="1"><error code="122" text="unknown managed object class foo"/></imdata>' +sent: + description: The actual/minimal configuration pushed to the APIC + returned: info + type: list + sample: + { + "fvTenant": { + "attributes": { + "descr": "Production environment" + } + } + } +previous: + description: The original configuration from the APIC before the module has started + returned: info + type: list + sample: + [ + { + "fvTenant": { + "attributes": { + "descr": "Production", + "dn": "uni/tn-production", + "name": "production", + "nameAlias": "", + "ownerKey": "", + "ownerTag": "" + } + } + } + ] +proposed: + description: The assembled configuration from the user-provided parameters + returned: info + type: dict + sample: + { + "fvTenant": { + "attributes": { + "descr": "Production environment", + "name": "production" + } + } + } +filter_string: + description: The filter string used for the request + returned: failure or debug + type: str + sample: ?rsp-prop-include=config-only +method: + description: The HTTP method used for the request to the APIC + returned: failure or debug + type: str + sample: POST +response: + description: The HTTP response from the APIC + returned: failure or debug + type: str + sample: OK (30 bytes) +status: + description: The HTTP status from the APIC + returned: failure or debug + type: int + sample: 200 +url: + description: The HTTP url used for the request to the APIC + returned: failure or debug + type: str + sample: https://10.11.12.13/api/mo/uni/tn-production.json +""" + +from ansible.module_utils.basic import AnsibleModule +from ansible_collections.cisco.aci.plugins.module_utils.aci import ACIModule, aci_argument_spec, aci_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) <gmicol@cisco.com> +# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) + +from __future__ import absolute_import, division, print_function + +__metaclass__ = type + +ANSIBLE_METADATA = { + "metadata_version": "1.1", + "status": ["preview"], + "supported_by": "certified", +} + +DOCUMENTATION = r""" +--- +module: aci_access_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: '<?xml version="1.0" encoding="UTF-8"?><imdata totalCount="1"><error code="122" text="unknown managed object class foo"/></imdata>' +sent: + description: The actual/minimal configuration pushed to the APIC + returned: info + type: list + sample: + { + "fvTenant": { + "attributes": { + "descr": "Production environment" + } + } + } +previous: + description: The original configuration from the APIC before the module has started + returned: info + type: list + sample: + [ + { + "fvTenant": { + "attributes": { + "descr": "Production", + "dn": "uni/tn-production", + "name": "production", + "nameAlias": "", + "ownerKey": "", + "ownerTag": "" + } + } + } + ] +proposed: + description: The assembled configuration from the user-provided parameters + returned: info + type: dict + sample: + { + "fvTenant": { + "attributes": { + "descr": "Production environment", + "name": "production" + } + } + } +filter_string: + description: The filter string used for the request + returned: failure or debug + type: str + sample: ?rsp-prop-include=config-only +method: + description: The HTTP method used for the request to the APIC + returned: failure or debug + type: str + sample: POST +response: + description: The HTTP response from the APIC + returned: failure or debug + type: str + sample: OK (30 bytes) +status: + description: The HTTP status from the APIC + returned: failure or debug + type: int + sample: 200 +url: + description: The HTTP url used for the request to the APIC + returned: failure or debug + type: str + sample: https://10.11.12.13/api/mo/uni/tn-production.json +""" + +from ansible.module_utils.basic import AnsibleModule +from ansible_collections.cisco.aci.plugins.module_utils.aci import ACIModule, aci_argument_spec, aci_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) <gmicol@cisco.com> +# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) + +from __future__ import absolute_import, division, print_function + +__metaclass__ = type + +ANSIBLE_METADATA = {"metadata_version": "1.1", "status": ["preview"], "supported_by": "certified"} + +DOCUMENTATION = r""" +--- +module: aci_access_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: '<?xml version="1.0" encoding="UTF-8"?><imdata totalCount="1"><error code="122" text="unknown managed object class foo"/></imdata>' +sent: + description: The actual/minimal configuration pushed to the APIC + returned: info + type: list + sample: + { + "fvTenant": { + "attributes": { + "descr": "Production environment" + } + } + } +previous: + description: The original configuration from the APIC before the module has started + returned: info + type: list + sample: + [ + { + "fvTenant": { + "attributes": { + "descr": "Production", + "dn": "uni/tn-production", + "name": "production", + "nameAlias": "", + "ownerKey": "", + "ownerTag": "" + } + } + } + ] +proposed: + description: The assembled configuration from the user-provided parameters + returned: info + type: dict + sample: + { + "fvTenant": { + "attributes": { + "descr": "Production environment", + "name": "production" + } + } + } +filter_string: + description: The filter string used for the request + returned: failure or debug + type: str + sample: ?rsp-prop-include=config-only +method: + description: The HTTP method used for the request to the APIC + returned: failure or debug + type: str + sample: POST +response: + description: The HTTP response from the APIC + returned: failure or debug + type: str + sample: OK (30 bytes) +status: + description: The HTTP status from the APIC + returned: failure or debug + type: int + sample: 200 +url: + description: The HTTP url used for the request to the APIC + returned: failure or debug + type: str + sample: https://10.11.12.13/api/mo/uni/tn-production.json +""" + +from ansible.module_utils.basic import AnsibleModule +from ansible_collections.cisco.aci.plugins.module_utils.aci import ACIModule, aci_argument_spec, aci_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) <gmicol@cisco.com> +# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) + +from __future__ import absolute_import, division, print_function + +__metaclass__ = type + +ANSIBLE_METADATA = { + "metadata_version": "1.1", + "status": ["preview"], + "supported_by": "certified", +} + +DOCUMENTATION = r""" +--- +module: aci_access_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: '<?xml version="1.0" encoding="UTF-8"?><imdata totalCount="1"><error code="122" text="unknown managed object class foo"/></imdata>' +sent: + description: The actual/minimal configuration pushed to the APIC + returned: info + type: list + sample: + { + "fvTenant": { + "attributes": { + "descr": "Production environment" + } + } + } +previous: + description: The original configuration from the APIC before the module has started + returned: info + type: list + sample: + [ + { + "fvTenant": { + "attributes": { + "descr": "Production", + "dn": "uni/tn-production", + "name": "production", + "nameAlias": "", + "ownerKey": "", + "ownerTag": "" + } + } + } + ] +proposed: + description: The assembled configuration from the user-provided parameters + returned: info + type: dict + sample: + { + "fvTenant": { + "attributes": { + "descr": "Production environment", + "name": "production" + } + } + } +filter_string: + description: The filter string used for the request + returned: failure or debug + type: str + sample: ?rsp-prop-include=config-only +method: + description: The HTTP method used for the request to the APIC + returned: failure or debug + type: str + sample: POST +response: + description: The HTTP response from the APIC + returned: failure or debug + type: str + sample: OK (30 bytes) +status: + description: The HTTP status from the APIC + returned: failure or debug + type: int + sample: 200 +url: + description: The HTTP url used for the request to the APIC + returned: failure or debug + type: str + sample: https://10.11.12.13/api/mo/uni/tn-production.json +""" + +from ansible.module_utils.basic import AnsibleModule +from ansible_collections.cisco.aci.plugins.module_utils.aci import ACIModule, aci_argument_spec, aci_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) <gmicol@cisco.com> +# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) + +from __future__ import absolute_import, division, print_function + +__metaclass__ = type + +ANSIBLE_METADATA = { + "metadata_version": "1.1", + "status": ["preview"], + "supported_by": "certified", +} + +DOCUMENTATION = r""" +--- +module: aci_access_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: '<?xml version="1.0" encoding="UTF-8"?><imdata totalCount="1"><error code="122" text="unknown managed object class foo"/></imdata>' +sent: + description: The actual/minimal configuration pushed to the APIC + returned: info + type: list + sample: + { + "fvTenant": { + "attributes": { + "descr": "Production environment" + } + } + } +previous: + description: The original configuration from the APIC before the module has started + returned: info + type: list + sample: + [ + { + "fvTenant": { + "attributes": { + "descr": "Production", + "dn": "uni/tn-production", + "name": "production", + "nameAlias": "", + "ownerKey": "", + "ownerTag": "" + } + } + } + ] +proposed: + description: The assembled configuration from the user-provided parameters + returned: info + type: dict + sample: + { + "fvTenant": { + "attributes": { + "descr": "Production environment", + "name": "production" + } + } + } +filter_string: + description: The filter string used for the request + returned: failure or debug + type: str + sample: ?rsp-prop-include=config-only +method: + description: The HTTP method used for the request to the APIC + returned: failure or debug + type: str + sample: POST +response: + description: The HTTP response from the APIC + returned: failure or debug + type: str + sample: OK (30 bytes) +status: + description: The HTTP status from the APIC + returned: failure or debug + type: int + sample: 200 +url: + description: The HTTP url used for the request to the APIC + returned: failure or debug + type: str + sample: https://10.11.12.13/api/mo/uni/tn-production.json +""" + +from ansible.module_utils.basic import AnsibleModule +from ansible_collections.cisco.aci.plugins.module_utils.aci import ACIModule, aci_argument_spec, aci_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: '<?xml version="1.0" encoding="UTF-8"?><imdata totalCount="1"><error code="122" text="unknown managed object class "/></imdata>' + sent: + description: The actual/minimal configuration pushed to the APIC + returned: info + type: list + sample: + { + "fvTenant": { + "attributes": { + "descr": "Production environment" + } + } + } + previous: + description: The original configuration from the APIC before the module has started + returned: info + type: list + sample: + [ + { + "fvTenant": { + "attributes": { + "descr": "Production", + "dn": "uni/tn-production", + "name": "production", + "nameAlias": "", + "ownerKey": "", + "ownerTag": "" + } + } + } + ] + proposed: + description: The assembled configuration from the user-provided parameters + returned: info + type: dict + sample: + { + "fvTenant": { + "attributes": { + "descr": "Production environment", + "name": "production" + } + } + } + filter_string: + description: The filter string used for the request + returned: failure or debug + type: str + sample: ?rsp-prop-include=config-only + method: + description: The HTTP method used for the request to the APIC + returned: failure or debug + type: str + sample: POST + response: + description: The HTTP response from the APIC + returned: failure or debug + type: str + sample: OK (30 bytes) + status: + description: The HTTP status from the APIC + returned: failure or debug + type: int + sample: 200 + url: + description: The HTTP url used for the request to the APIC + returned: failure or debug + type: str + sample: https://10.11.12.13/api/mo/uni/tn-production.json + """ + +from ansible.module_utils.basic import AnsibleModule +from ansible_collections.cisco.aci.plugins.module_utils.aci import ACIModule, aci_argument_spec, aci_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) <gmicol@cisco.com> +# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) + +from __future__ import absolute_import, division, print_function + +__metaclass__ = type + +ANSIBLE_METADATA = {"metadata_version": "1.1", "status": ["preview"], "supported_by": "certified"} + +DOCUMENTATION = r""" +--- +module: aci_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: '<?xml version="1.0" encoding="UTF-8"?><imdata totalCount="1"><error code="122" text="unknown managed object class foo"/></imdata>' +sent: + description: The actual/minimal configuration pushed to the APIC + returned: info + type: list + sample: + { + "fvTenant": { + "attributes": { + "descr": "Production environment" + } + } + } +previous: + description: The original configuration from the APIC before the module has started + returned: info + type: list + sample: + [ + { + "fvTenant": { + "attributes": { + "descr": "Production", + "dn": "uni/tn-production", + "name": "production", + "nameAlias": "", + "ownerKey": "", + "ownerTag": "" + } + } + } + ] +proposed: + description: The assembled configuration from the user-provided parameters + returned: info + type: dict + sample: + { + "fvTenant": { + "attributes": { + "descr": "Production environment", + "name": "production" + } + } + } +filter_string: + description: The filter string used for the request + returned: failure or debug + type: str + sample: ?rsp-prop-include=config-only +method: + description: The HTTP method used for the request to the APIC + returned: failure or debug + type: str + sample: POST +response: + description: The HTTP response from the APIC + returned: failure or debug + type: str + sample: OK (30 bytes) +status: + description: The HTTP status from the APIC + returned: failure or debug + type: int + sample: 200 +url: + description: The HTTP url used for the request to the APIC + returned: failure or debug + type: str + sample: https://10.11.12.13/api/mo/uni/tn-production.json +""" + +from ansible.module_utils.basic import AnsibleModule +from ansible_collections.cisco.aci.plugins.module_utils.aci import ACIModule, aci_argument_spec, aci_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) <gmicol@cisco.com> +# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) + +from __future__ import absolute_import, division, print_function + +__metaclass__ = type + +ANSIBLE_METADATA = {"metadata_version": "1.1", "status": ["preview"], "supported_by": "certified"} + +DOCUMENTATION = r""" +--- +module: aci_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: '<?xml version="1.0" encoding="UTF-8"?><imdata totalCount="1"><error code="122" text="unknown managed object class foo"/></imdata>' +sent: + description: The actual/minimal configuration pushed to the APIC + returned: info + type: list + sample: + { + "fvTenant": { + "attributes": { + "descr": "Production environment" + } + } + } +previous: + description: The original configuration from the APIC before the module has started + returned: info + type: list + sample: + [ + { + "fvTenant": { + "attributes": { + "descr": "Production", + "dn": "uni/tn-production", + "name": "production", + "nameAlias": "", + "ownerKey": "", + "ownerTag": "" + } + } + } + ] +proposed: + description: The assembled configuration from the user-provided parameters + returned: info + type: dict + sample: + { + "fvTenant": { + "attributes": { + "descr": "Production environment", + "name": "production" + } + } + } +filter_string: + description: The filter string used for the request + returned: failure or debug + type: str + sample: ?rsp-prop-include=config-only +method: + description: The HTTP method used for the request to the APIC + returned: failure or debug + type: str + sample: POST +response: + description: The HTTP response from the APIC + returned: failure or debug + type: str + sample: OK (30 bytes) +status: + description: The HTTP status from the APIC + returned: failure or debug + type: int + sample: 200 +url: + description: The HTTP url used for the request to the APIC + returned: failure or debug + type: str + sample: https://10.11.12.13/api/mo/uni/tn-production.json +""" + +from ansible.module_utils.basic import AnsibleModule +from ansible_collections.cisco.aci.plugins.module_utils.aci import ACIModule, aci_argument_spec, aci_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) <gmicol@cisco.com> +# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) + +from __future__ import absolute_import, division, print_function + +__metaclass__ = type + +ANSIBLE_METADATA = {"metadata_version": "1.1", "status": ["preview"], "supported_by": "certified"} + +DOCUMENTATION = r""" +--- +module: aci_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: '<?xml version="1.0" encoding="UTF-8"?><imdata totalCount="1"><error code="122" text="unknown managed object class foo"/></imdata>' +sent: + description: The actual/minimal configuration pushed to the APIC + returned: info + type: list + sample: + { + "fvTenant": { + "attributes": { + "descr": "Production environment" + } + } + } +previous: + description: The original configuration from the APIC before the module has started + returned: info + type: list + sample: + [ + { + "fvTenant": { + "attributes": { + "descr": "Production", + "dn": "uni/tn-production", + "name": "production", + "nameAlias": "", + "ownerKey": "", + "ownerTag": "" + } + } + } + ] +proposed: + description: The assembled configuration from the user-provided parameters + returned: info + type: dict + sample: + { + "fvTenant": { + "attributes": { + "descr": "Production environment", + "name": "production" + } + } + } +filter_string: + description: The filter string used for the request + returned: failure or debug + type: str + sample: ?rsp-prop-include=config-only +method: + description: The HTTP method used for the request to the APIC + returned: failure or debug + type: str + sample: POST +response: + description: The HTTP response from the APIC + returned: failure or debug + type: str + sample: OK (30 bytes) +status: + description: The HTTP status from the APIC + returned: failure or debug + type: int + sample: 200 +url: + description: The HTTP url used for the request to the APIC + returned: failure or debug + type: str + sample: https://10.11.12.13/api/mo/uni/tn-production.json +""" + +from ansible.module_utils.basic import AnsibleModule +from ansible_collections.cisco.aci.plugins.module_utils.aci import ACIModule, aci_argument_spec, aci_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) <samitab@cisco.com> # GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) from __future__ import absolute_import, division, print_function @@ -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) <samitab@cisco.com> +# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) + +from __future__ import absolute_import, division, print_function + +__metaclass__ = type + +ANSIBLE_METADATA = {"metadata_version": "1.1", "status": ["preview"], "supported_by": "certified"} + +DOCUMENTATION = r""" +--- +module: aci_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: '<?xml version="1.0" encoding="UTF-8"?><imdata totalCount="1"><error code="122" text="unknown managed object class foo"/></imdata>' +sent: + description: The actual/minimal configuration pushed to the APIC + returned: info + type: list + sample: + { + "fvTenant": { + "attributes": { + "descr": "Production environment" + } + } + } +previous: + description: The original configuration from the APIC before the module has started + returned: info + type: list + sample: + [ + { + "fvTenant": { + "attributes": { + "descr": "Production", + "dn": "uni/tn-production", + "name": "production", + "nameAlias": "", + "ownerKey": "", + "ownerTag": "" + } + } + } + ] +proposed: + description: The assembled configuration from the user-provided parameters + returned: info + type: dict + sample: + { + "fvTenant": { + "attributes": { + "descr": "Production environment", + "name": "production" + } + } + } +filter_string: + description: The filter string used for the request + returned: failure or debug + type: str + sample: ?rsp-prop-include=config-only +method: + description: The HTTP method used for the request to the APIC + returned: failure or debug + type: str + sample: POST +response: + description: The HTTP response from the APIC + returned: failure or debug + type: str + sample: OK (30 bytes) +status: + description: The HTTP status from the APIC + returned: failure or debug + type: int + sample: 200 +url: + description: The HTTP url used for the request to the APIC + returned: failure or debug + type: str + sample: https://10.11.12.13/api/mo/uni/tn-production.json +""" + +from ansible.module_utils.basic import AnsibleModule +from ansible_collections.cisco.aci.plugins.module_utils.aci import ACIModule, aci_argument_spec, aci_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) <samitab@cisco.com> +# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) + +from __future__ import absolute_import, division, print_function + +__metaclass__ = type + +ANSIBLE_METADATA = {"metadata_version": "1.1", "status": ["preview"], "supported_by": "certified"} + +DOCUMENTATION = r""" +--- +module: aci_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: '<?xml version="1.0" encoding="UTF-8"?><imdata totalCount="1"><error code="122" text="unknown managed object class foo"/></imdata>' +sent: + description: The actual/minimal configuration pushed to the APIC + returned: info + type: list + sample: + { + "fvTenant": { + "attributes": { + "descr": "Production environment" + } + } + } +previous: + description: The original configuration from the APIC before the module has started + returned: info + type: list + sample: + [ + { + "fvTenant": { + "attributes": { + "descr": "Production", + "dn": "uni/tn-production", + "name": "production", + "nameAlias": "", + "ownerKey": "", + "ownerTag": "" + } + } + } + ] +proposed: + description: The assembled configuration from the user-provided parameters + returned: info + type: dict + sample: + { + "fvTenant": { + "attributes": { + "descr": "Production environment", + "name": "production" + } + } + } +filter_string: + description: The filter string used for the request + returned: failure or debug + type: str + sample: ?rsp-prop-include=config-only +method: + description: The HTTP method used for the request to the APIC + returned: failure or debug + type: str + sample: POST +response: + description: The HTTP response from the APIC + returned: failure or debug + type: str + sample: OK (30 bytes) +status: + description: The HTTP status from the APIC + returned: failure or debug + type: int + sample: 200 +url: + description: The HTTP url used for the request to the APIC + returned: failure or debug + type: str + sample: https://10.11.12.13/api/mo/uni/tn-production.json +""" + +from ansible.module_utils.basic import AnsibleModule +from ansible_collections.cisco.aci.plugins.module_utils.aci import ACIModule, aci_argument_spec, aci_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) <anvjain@cisco.com> +# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) + +from __future__ import absolute_import, division, print_function + +__metaclass__ = type + +ANSIBLE_METADATA = {"metadata_version": "1.1", "status": ["preview"], "supported_by": "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: '<?xml version="1.0" encoding="UTF-8"?><imdata totalCount="1"><error code="122" text="unknown managed object class "/></imdata>' + sent: + description: The actual/minimal configuration pushed to the APIC + returned: info + type: list + sample: + { + "fvTenant": { + "attributes": { + "descr": "Production environment" + } + } + } + previous: + description: The original configuration from the APIC before the module has started + returned: info + type: list + sample: + [ + { + "fvTenant": { + "attributes": { + "descr": "Production", + "dn": "uni/tn-production", + "name": "production", + "nameAlias": "", + "ownerKey": "", + "ownerTag": "" + } + } + } + ] + proposed: + description: The assembled configuration from the user-provided parameters + returned: info + type: dict + sample: + { + "fvTenant": { + "attributes": { + "descr": "Production environment", + "name": "production" + } + } + } + filter_string: + description: The filter string used for the request + returned: failure or debug + type: str + sample: ?rsp-prop-include=config-only + method: + description: The HTTP method used for the request to the APIC + returned: failure or debug + type: str + sample: POST + response: + description: The HTTP response from the APIC + returned: failure or debug + type: str + sample: OK (30 bytes) + status: + description: The HTTP status from the APIC + returned: failure or debug + type: int + sample: 200 + url: + description: The HTTP url used for the request to the APIC + returned: failure or debug + type: str + sample: https://10.11.12.13/api/mo/uni/tn-production.json + """ + +from ansible.module_utils.basic import AnsibleModule +from ansible_collections.cisco.aci.plugins.module_utils.aci import ACIModule, aci_argument_spec, aci_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) <gmicol@cisco.com> +# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) + +from __future__ import absolute_import, division, print_function + +__metaclass__ = type + +ANSIBLE_METADATA = {"metadata_version": "1.1", "status": ["preview"], "supported_by": "certified"} + +DOCUMENTATION = r""" +--- +module: aci_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: '<?xml version="1.0" encoding="UTF-8"?><imdata totalCount="1"><error code="122" text="unknown managed object class foo"/></imdata>' +sent: + description: The actual/minimal configuration pushed to the APIC + returned: info + type: list + sample: + { + "fvTenant": { + "attributes": { + "descr": "Production environment" + } + } + } +previous: + description: The original configuration from the APIC before the module has started + returned: info + type: list + sample: + [ + { + "fvTenant": { + "attributes": { + "descr": "Production", + "dn": "uni/tn-production", + "name": "production", + "nameAlias": "", + "ownerKey": "", + "ownerTag": "" + } + } + } + ] +proposed: + description: The assembled configuration from the user-provided parameters + returned: info + type: dict + sample: + { + "fvTenant": { + "attributes": { + "descr": "Production environment", + "name": "production" + } + } + } +filter_string: + description: The filter string used for the request + returned: failure or debug + type: str + sample: ?rsp-prop-include=config-only +method: + description: The HTTP method used for the request to the APIC + returned: failure or debug + type: str + sample: POST +response: + description: The HTTP response from the APIC + returned: failure or debug + type: str + sample: OK (30 bytes) +status: + description: The HTTP status from the APIC + returned: failure or debug + type: int + sample: 200 +url: + description: The HTTP url used for the request to the APIC + returned: failure or debug + type: str + sample: https://10.11.12.13/api/mo/uni/tn-production.json +""" + +from ansible.module_utils.basic import AnsibleModule +from ansible_collections.cisco.aci.plugins.module_utils.aci import ACIModule, aci_argument_spec, aci_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) <gmicol@cisco.com> +# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) + +from __future__ import absolute_import, division, print_function + +__metaclass__ = type + +ANSIBLE_METADATA = {"metadata_version": "1.1", "status": ["preview"], "supported_by": "certified"} + +DOCUMENTATION = r""" +--- +module: aci_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: '<?xml version="1.0" encoding="UTF-8"?><imdata totalCount="1"><error code="122" text="unknown managed object class foo"/></imdata>' +sent: + description: The actual/minimal configuration pushed to the APIC + returned: info + type: list + sample: + { + "fvTenant": { + "attributes": { + "descr": "Production environment" + } + } + } +previous: + description: The original configuration from the APIC before the module has started + returned: info + type: list + sample: + [ + { + "fvTenant": { + "attributes": { + "descr": "Production", + "dn": "uni/tn-production", + "name": "production", + "nameAlias": "", + "ownerKey": "", + "ownerTag": "" + } + } + } + ] +proposed: + description: The assembled configuration from the user-provided parameters + returned: info + type: dict + sample: + { + "fvTenant": { + "attributes": { + "descr": "Production environment", + "name": "production" + } + } + } +filter_string: + description: The filter string used for the request + returned: failure or debug + type: str + sample: ?rsp-prop-include=config-only +method: + description: The HTTP method used for the request to the APIC + returned: failure or debug + type: str + sample: POST +response: + description: The HTTP response from the APIC + returned: failure or debug + type: str + sample: OK (30 bytes) +status: + description: The HTTP status from the APIC + returned: failure or debug + type: int + sample: 200 +url: + description: The HTTP url used for the request to the APIC + returned: failure or debug + type: str + sample: https://10.11.12.13/api/mo/uni/tn-production.json +""" + +from ansible.module_utils.basic import AnsibleModule +from ansible_collections.cisco.aci.plugins.module_utils.aci import ACIModule, aci_argument_spec, aci_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) <gmicol@cisco.com> +# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) + +from __future__ import absolute_import, division, print_function + +__metaclass__ = type + +ANSIBLE_METADATA = {"metadata_version": "1.1", "status": ["preview"], "supported_by": "certified"} + +DOCUMENTATION = r""" +--- +module: aci_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: '<?xml version="1.0" encoding="UTF-8"?><imdata totalCount="1"><error code="122" text="unknown managed object class foo"/></imdata>' +sent: + description: The actual/minimal configuration pushed to the APIC + returned: info + type: list + sample: + { + "fvTenant": { + "attributes": { + "descr": "Production environment" + } + } + } +previous: + description: The original configuration from the APIC before the module has started + returned: info + type: list + sample: + [ + { + "fvTenant": { + "attributes": { + "descr": "Production", + "dn": "uni/tn-production", + "name": "production", + "nameAlias": "", + "ownerKey": "", + "ownerTag": "" + } + } + } + ] +proposed: + description: The assembled configuration from the user-provided parameters + returned: info + type: dict + sample: + { + "fvTenant": { + "attributes": { + "descr": "Production environment", + "name": "production" + } + } + } +filter_string: + description: The filter string used for the request + returned: failure or debug + type: str + sample: ?rsp-prop-include=config-only +method: + description: The HTTP method used for the request to the APIC + returned: failure or debug + type: str + sample: POST +response: + description: The HTTP response from the APIC + returned: failure or debug + type: str + sample: OK (30 bytes) +status: + description: The HTTP status from the APIC + returned: failure or debug + type: int + sample: 200 +url: + description: The HTTP url used for the request to the APIC + returned: failure or debug + type: str + sample: https://10.11.12.13/api/mo/uni/tn-production.json +""" + +from ansible.module_utils.basic import AnsibleModule +from ansible_collections.cisco.aci.plugins.module_utils.aci import ACIModule, aci_argument_spec, aci_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 <nirav.katarmal@crestdatasys.com> # Copyright: (c) 2020, Cindy Zhao <cizhao@cisco.com> +# Copyright: (c) 2024, Samita Bhattacharjee <samitab@cisco.com> # GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) from __future__ import absolute_import, division, print_function @@ -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) <gmicol@cisco.com> +# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) + +from __future__ import absolute_import, division, print_function + +__metaclass__ = type + +ANSIBLE_METADATA = {"metadata_version": "1.1", "status": ["preview"], "supported_by": "community"} + +DOCUMENTATION = r""" +--- +module: aci_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: '<?xml version="1.0" encoding="UTF-8"?><imdata totalCount="1"><error code="122" text="unknown managed object class foo"/></imdata>' +sent: + description: The actual/minimal configuration pushed to the APIC + returned: info + type: list + sample: + { + "fvTenant": { + "attributes": { + "descr": "Production environment" + } + } + } +previous: + description: The original configuration from the APIC before the module has started + returned: info + type: list + sample: + [ + { + "fvTenant": { + "attributes": { + "descr": "Production", + "dn": "uni/tn-production", + "name": "production", + "nameAlias": "", + "ownerKey": "", + "ownerTag": "" + } + } + } + ] +proposed: + description: The assembled configuration from the user-provided parameters + returned: info + type: dict + sample: + { + "fvTenant": { + "attributes": { + "descr": "Production environment", + "name": "production" + } + } + } +filter_string: + description: The filter string used for the request + returned: failure or debug + type: str + sample: ?rsp-prop-include=config-only +method: + description: The HTTP method used for the request to the APIC + returned: failure or debug + type: str + sample: POST +response: + description: The HTTP response from the APIC + returned: failure or debug + type: str + sample: OK (30 bytes) +status: + description: The HTTP status from the APIC + returned: failure or debug + type: int + sample: 200 +url: + description: The HTTP url used for the request to the APIC + returned: failure or debug + type: str + sample: https://10.11.12.13/api/mo/uni/tn-production.json +""" + + +from ansible.module_utils.basic import AnsibleModule +from ansible_collections.cisco.aci.plugins.module_utils.aci import ACIModule, aci_argument_spec, aci_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) <gmicol@cisco.com> +# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) + +from __future__ import absolute_import, division, print_function + +__metaclass__ = type + +ANSIBLE_METADATA = {"metadata_version": "1.1", "status": ["preview"], "supported_by": "community"} + +DOCUMENTATION = r""" +--- +module: aci_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: '<?xml version="1.0" encoding="UTF-8"?><imdata totalCount="1"><error code="122" text="unknown managed object class foo"/></imdata>' +sent: + description: The actual/minimal configuration pushed to the APIC + returned: info + type: list + sample: + { + "fvTenant": { + "attributes": { + "descr": "Production environment" + } + } + } +previous: + description: The original configuration from the APIC before the module has started + returned: info + type: list + sample: + [ + { + "fvTenant": { + "attributes": { + "descr": "Production", + "dn": "uni/tn-production", + "name": "production", + "nameAlias": "", + "ownerKey": "", + "ownerTag": "" + } + } + } + ] +proposed: + description: The assembled configuration from the user-provided parameters + returned: info + type: dict + sample: + { + "fvTenant": { + "attributes": { + "descr": "Production environment", + "name": "production" + } + } + } +filter_string: + description: The filter string used for the request + returned: failure or debug + type: str + sample: ?rsp-prop-include=config-only +method: + description: The HTTP method used for the request to the APIC + returned: failure or debug + type: str + sample: POST +response: + description: The HTTP response from the APIC + returned: failure or debug + type: str + sample: OK (30 bytes) +status: + description: The HTTP status from the APIC + returned: failure or debug + type: int + sample: 200 +url: + description: The HTTP url used for the request to the APIC + returned: failure or debug + type: str + sample: https://10.11.12.13/api/mo/uni/tn-production.json +""" + + +from ansible.module_utils.basic import AnsibleModule +from ansible_collections.cisco.aci.plugins.module_utils.aci import ACIModule, aci_argument_spec, aci_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 <christian.kolrep@dataport.de> +# 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) 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) <akinross@cisco.com> # GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) from __future__ import absolute_import, division, print_function @@ -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 <akinross@cisco.com> +# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) + +from __future__ import absolute_import, division, print_function + +__metaclass__ = type + +ANSIBLE_METADATA = {"metadata_version": "1.1", "status": ["preview"], "supported_by": "certified"} + +DOCUMENTATION = r""" +--- +module: aci_epg_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: '<?xml version="1.0" encoding="UTF-8"?><imdata totalCount="1"><error code="122" text="unknown managed object class foo"/></imdata>' +sent: + description: The actual/minimal configuration pushed to the APIC + returned: info + type: list + sample: + { + "fvTenant": { + "attributes": { + "descr": "Production environment" + } + } + } +previous: + description: The original configuration from the APIC before the module has started + returned: info + type: list + sample: + [ + { + "fvTenant": { + "attributes": { + "descr": "Production", + "dn": "uni/tn-production", + "name": "production", + "nameAlias": "", + "ownerKey": "", + "ownerTag": "" + } + } + } + ] +proposed: + description: The assembled configuration from the user-provided parameters + returned: info + type: dict + sample: + { + "fvTenant": { + "attributes": { + "descr": "Production environment", + "name": "production" + } + } + } +filter_string: + description: The filter string used for the request + returned: failure or debug + type: str + sample: ?rsp-prop-include=config-only +method: + description: The HTTP method used for the request to the APIC + returned: failure or debug + type: str + sample: POST +response: + description: The HTTP response from the APIC + returned: failure or debug + type: str + sample: OK (30 bytes) +status: + description: The HTTP status from the APIC + returned: failure or debug + type: int + sample: 200 +url: + description: The HTTP url used for the request to the APIC + returned: failure or debug + type: str + sample: https://10.11.12.13/api/mo/uni/tn-production.json +""" + +from ansible.module_utils.basic import AnsibleModule +from ansible_collections.cisco.aci.plugins.module_utils.aci import ACIModule, aci_argument_spec, aci_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 <christian.kolrep@dataport.de> +# 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) + +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: '<?xml version="1.0" encoding="UTF-8"?><imdata totalCount="1"><error code="122" text="unknown managed object class foo"/></imdata>' +sent: + description: The actual/minimal configuration pushed to the APIC + returned: info + type: list + sample: + { + "fvTenant": { + "attributes": { + "descr": "Production environment" + } + } + } +previous: + description: The original configuration from the APIC before the module has started + returned: info + type: list + sample: + [ + { + "fvTenant": { + "attributes": { + "descr": "Production", + "dn": "uni/tn-production", + "name": "production", + "nameAlias": "", + "ownerKey": "", + "ownerTag": "" + } + } + } + ] +proposed: + description: The assembled configuration from the user-provided parameters + returned: info + type: dict + sample: + { + "fvTenant": { + "attributes": { + "descr": "Production environment", + "name": "production" + } + } + } +filter_string: + description: The filter string used for the request + returned: failure or debug + type: str + sample: ?rsp-prop-include=config-only +method: + description: The HTTP method used for the request to the APIC + returned: failure or debug + type: str + sample: POST +response: + description: The HTTP response from the APIC + returned: failure or debug + type: str + sample: OK (30 bytes) +status: + description: The HTTP status from the APIC + returned: failure or debug + type: int + sample: 200 +url: + description: The HTTP url used for the request to the APIC + returned: failure or debug + type: str + sample: https://10.11.12.13/api/mo/uni/tn-production.json +""" + +from ansible.module_utils.basic import AnsibleModule +from ansible_collections.cisco.aci.plugins.module_utils.aci import ACIModule, aci_argument_spec, aci_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) <samitab.cisco.com> + +# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) + +from __future__ import absolute_import, division, print_function + +__metaclass__ = type + +ANSIBLE_METADATA = {"metadata_version": "1.1", "status": ["preview"], "supported_by": "certified"} + +DOCUMENTATION = r""" +--- +module: aci_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: '<?xml version="1.0" encoding="UTF-8"?><imdata totalCount="1"><error code="122" text="unknown managed object class foo"/></imdata>' +sent: + description: The actual/minimal configuration pushed to the APIC + returned: info + type: list + sample: + { + "fvTenant": { + "attributes": { + "descr": "Production environment" + } + } + } +previous: + description: The original configuration from the APIC before the module has started + returned: info + type: list + sample: + [ + { + "fvTenant": { + "attributes": { + "descr": "Production", + "dn": "uni/tn-production", + "name": "production", + "nameAlias": "", + "ownerKey": "", + "ownerTag": "" + } + } + } + ] +proposed: + description: The assembled configuration from the user-provided parameters + returned: info + type: dict + sample: + { + "fvTenant": { + "attributes": { + "descr": "Production environment", + "name": "production" + } + } + } +filter_string: + description: The filter string used for the request + returned: failure or debug + type: str + sample: ?rsp-prop-include=config-only +method: + description: The HTTP method used for the request to the APIC + returned: failure or debug + type: str + sample: POST +response: + description: The HTTP response from the APIC + returned: failure or debug + type: str + sample: OK (30 bytes) +status: + description: The HTTP status from the APIC + returned: failure or debug + type: int + sample: 200 +url: + description: The HTTP url used for the request to the APIC + returned: failure or debug + type: str + sample: https://10.11.12.13/api/mo/uni/tn-production.json +""" + +from ansible.module_utils.basic import AnsibleModule +from ansible_collections.cisco.aci.plugins.module_utils.aci import ACIModule, aci_argument_spec, aci_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) <samitab.cisco.com> + +# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) + +from __future__ import absolute_import, division, print_function + +__metaclass__ = type + +ANSIBLE_METADATA = {"metadata_version": "1.1", "status": ["preview"], "supported_by": "certified"} + +DOCUMENTATION = r""" +--- +module: aci_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: '<?xml version="1.0" encoding="UTF-8"?><imdata totalCount="1"><error code="122" text="unknown managed object class foo"/></imdata>' +sent: + description: The actual/minimal configuration pushed to the APIC + returned: info + type: list + sample: + { + "fvTenant": { + "attributes": { + "descr": "Production environment" + } + } + } +previous: + description: The original configuration from the APIC before the module has started + returned: info + type: list + sample: + [ + { + "fvTenant": { + "attributes": { + "descr": "Production", + "dn": "uni/tn-production", + "name": "production", + "nameAlias": "", + "ownerKey": "", + "ownerTag": "" + } + } + } + ] +proposed: + description: The assembled configuration from the user-provided parameters + returned: info + type: dict + sample: + { + "fvTenant": { + "attributes": { + "descr": "Production environment", + "name": "production" + } + } + } +filter_string: + description: The filter string used for the request + returned: failure or debug + type: str + sample: ?rsp-prop-include=config-only +method: + description: The HTTP method used for the request to the APIC + returned: failure or debug + type: str + sample: POST +response: + description: The HTTP response from the APIC + returned: failure or debug + type: str + sample: OK (30 bytes) +status: + description: The HTTP status from the APIC + returned: failure or debug + type: int + sample: 200 +url: + description: The HTTP url used for the request to the APIC + returned: failure or debug + type: str + sample: https://10.11.12.13/api/mo/uni/tn-production.json +""" + +from ansible.module_utils.basic import AnsibleModule +from ansible_collections.cisco.aci.plugins.module_utils.aci import ACIModule, aci_argument_spec, aci_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) <akinross@cisco.com> +# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) + +from __future__ import absolute_import, division, print_function + +__metaclass__ = type + +ANSIBLE_METADATA = {"metadata_version": "1.1", "status": ["preview"], "supported_by": "certified"} + +DOCUMENTATION = r""" +--- +module: aci_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: '<?xml version="1.0" encoding="UTF-8"?><imdata totalCount="1"><error code="122" text="unknown managed object class foo"/></imdata>' +sent: + description: The actual/minimal configuration pushed to the APIC + returned: info + type: list + sample: + { + "fvTenant": { + "attributes": { + "descr": "Production environment" + } + } + } +previous: + description: The original configuration from the APIC before the module has started + returned: info + type: list + sample: + [ + { + "fvTenant": { + "attributes": { + "descr": "Production", + "dn": "uni/tn-production", + "name": "production", + "nameAlias": "", + "ownerKey": "", + "ownerTag": "" + } + } + } + ] +proposed: + description: The assembled configuration from the user-provided parameters + returned: info + type: dict + sample: + { + "fvTenant": { + "attributes": { + "descr": "Production environment", + "name": "production" + } + } + } +filter_string: + description: The filter string used for the request + returned: failure or debug + type: str + sample: ?rsp-prop-include=config-only +method: + description: The HTTP method used for the request to the APIC + returned: failure or debug + type: str + sample: POST +response: + description: The HTTP response from the APIC + returned: failure or debug + type: str + sample: OK (30 bytes) +status: + description: The HTTP status from the APIC + returned: failure or debug + type: int + sample: 200 +url: + description: The HTTP url used for the request to the APIC + returned: failure or debug + type: str + sample: https://10.11.12.13/api/mo/uni/tn-production.json +""" + +from ansible.module_utils.basic import AnsibleModule +from ansible_collections.cisco.aci.plugins.module_utils.aci import ACIModule, aci_argument_spec, aci_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) <akinross@cisco.com> +# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) + +from __future__ import absolute_import, division, print_function + +__metaclass__ = type + +ANSIBLE_METADATA = {"metadata_version": "1.1", "status": ["preview"], "supported_by": "certified"} + +DOCUMENTATION = r""" +--- +module: aci_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: '<?xml version="1.0" encoding="UTF-8"?><imdata totalCount="1"><error code="122" text="unknown managed object class foo"/></imdata>' +sent: + description: The actual/minimal configuration pushed to the APIC + returned: info + type: list + sample: + { + "fvTenant": { + "attributes": { + "descr": "Production environment" + } + } + } +previous: + description: The original configuration from the APIC before the module has started + returned: info + type: list + sample: + [ + { + "fvTenant": { + "attributes": { + "descr": "Production", + "dn": "uni/tn-production", + "name": "production", + "nameAlias": "", + "ownerKey": "", + "ownerTag": "" + } + } + } + ] +proposed: + description: The assembled configuration from the user-provided parameters + returned: info + type: dict + sample: + { + "fvTenant": { + "attributes": { + "descr": "Production environment", + "name": "production" + } + } + } +filter_string: + description: The filter string used for the request + returned: failure or debug + type: str + sample: ?rsp-prop-include=config-only +method: + description: The HTTP method used for the request to the APIC + returned: failure or debug + type: str + sample: POST +response: + description: The HTTP response from the APIC + returned: failure or debug + type: str + sample: OK (30 bytes) +status: + description: The HTTP status from the APIC + returned: failure or debug + type: int + sample: 200 +url: + description: The HTTP url used for the request to the APIC + returned: failure or debug + type: str + sample: https://10.11.12.13/api/mo/uni/tn-production.json +""" + +from ansible.module_utils.basic import AnsibleModule +from ansible_collections.cisco.aci.plugins.module_utils.aci import ACIModule, aci_argument_spec, aci_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) <samitab@cisco.com> +# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) + +from __future__ import absolute_import, division, print_function + +__metaclass__ = type + +ANSIBLE_METADATA = {"metadata_version": "1.1", "status": ["preview"], "supported_by": "certified"} + +DOCUMENTATION = r""" +--- +module: aci_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: '<?xml version="1.0" encoding="UTF-8"?><imdata totalCount="1"><error code="122" text="unknown managed object class foo"/></imdata>' +sent: + description: The actual/minimal configuration pushed to the APIC + returned: info + type: list + sample: + { + "fvTenant": { + "attributes": { + "descr": "Production environment" + } + } + } +previous: + description: The original configuration from the APIC before the module has started + returned: info + type: list + sample: + [ + { + "fvTenant": { + "attributes": { + "descr": "Production", + "dn": "uni/tn-production", + "name": "production", + "nameAlias": "", + "ownerKey": "", + "ownerTag": "" + } + } + } + ] +proposed: + description: The assembled configuration from the user-provided parameters + returned: info + type: dict + sample: + { + "fvTenant": { + "attributes": { + "descr": "Production environment", + "name": "production" + } + } + } +filter_string: + description: The filter string used for the request + returned: failure or debug + type: str + sample: ?rsp-prop-include=config-only +method: + description: The HTTP method used for the request to the APIC + returned: failure or debug + type: str + sample: POST +response: + description: The HTTP response from the APIC + returned: failure or debug + type: str + sample: OK (30 bytes) +status: + description: The HTTP status from the APIC + returned: failure or debug + type: int + sample: 200 +url: + description: The HTTP url used for the request to the APIC + returned: failure or debug + type: str + sample: https://10.11.12.13/api/mo/uni/tn-production.json +""" + +from ansible.module_utils.basic import AnsibleModule +from ansible_collections.cisco.aci.plugins.module_utils.aci import ( + ACIModule, + aci_argument_spec, + aci_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) <samitab.cisco.com> + +# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) + +from __future__ import absolute_import, division, print_function + +__metaclass__ = type + +ANSIBLE_METADATA = {"metadata_version": "1.1", "status": ["preview"], "supported_by": "certified"} + +DOCUMENTATION = r""" +--- +module: aci_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: '<?xml version="1.0" encoding="UTF-8"?><imdata totalCount="1"><error code="122" text="unknown managed object class foo"/></imdata>' +sent: + description: The actual/minimal configuration pushed to the APIC + returned: info + type: list + sample: + { + "fvTenant": { + "attributes": { + "descr": "Production environment" + } + } + } +previous: + description: The original configuration from the APIC before the module has started + returned: info + type: list + sample: + [ + { + "fvTenant": { + "attributes": { + "descr": "Production", + "dn": "uni/tn-production", + "name": "production", + "nameAlias": "", + "ownerKey": "", + "ownerTag": "" + } + } + } + ] +proposed: + description: The assembled configuration from the user-provided parameters + returned: info + type: dict + sample: + { + "fvTenant": { + "attributes": { + "descr": "Production environment", + "name": "production" + } + } + } +filter_string: + description: The filter string used for the request + returned: failure or debug + type: str + sample: ?rsp-prop-include=config-only +method: + description: The HTTP method used for the request to the APIC + returned: failure or debug + type: str + sample: POST +response: + description: The HTTP response from the APIC + returned: failure or debug + type: str + sample: OK (30 bytes) +status: + description: The HTTP status from the APIC + returned: failure or debug + type: int + sample: 200 +url: + description: The HTTP url used for the request to the APIC + returned: failure or debug + type: str + sample: https://10.11.12.13/api/mo/uni/tn-production.json +""" + +from ansible.module_utils.basic import AnsibleModule +from ansible_collections.cisco.aci.plugins.module_utils.aci import ACIModule, aci_argument_spec, aci_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) <samitab@cisco.com> +# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) + +from __future__ import absolute_import, division, print_function + +__metaclass__ = type + +ANSIBLE_METADATA = {"metadata_version": "1.1", "status": ["preview"], "supported_by": "certified"} + +DOCUMENTATION = r""" +--- +module: aci_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: '<?xml version="1.0" encoding="UTF-8"?><imdata totalCount="1"><error code="122" text="unknown managed object class foo"/></imdata>' +sent: + description: The actual/minimal configuration pushed to the APIC + returned: info + type: list + sample: + { + "fvTenant": { + "attributes": { + "descr": "Production environment" + } + } + } +previous: + description: The original configuration from the APIC before the module has started + returned: info + type: list + sample: + [ + { + "fvTenant": { + "attributes": { + "descr": "Production", + "dn": "uni/tn-production", + "name": "production", + "nameAlias": "", + "ownerKey": "", + "ownerTag": "" + } + } + } + ] +proposed: + description: The assembled configuration from the user-provided parameters + returned: info + type: dict + sample: + { + "fvTenant": { + "attributes": { + "descr": "Production environment", + "name": "production" + } + } + } +filter_string: + description: The filter string used for the request + returned: failure or debug + type: str + sample: ?rsp-prop-include=config-only +method: + description: The HTTP method used for the request to the APIC + returned: failure or debug + type: str + sample: POST +response: + description: The HTTP response from the APIC + returned: failure or debug + type: str + sample: OK (30 bytes) +status: + description: The HTTP status from the APIC + returned: failure or debug + type: int + sample: 200 +url: + description: The HTTP url used for the request to the APIC + returned: failure or debug + type: str + sample: https://10.11.12.13/api/mo/uni/tn-production.json +""" + +from ansible.module_utils.basic import AnsibleModule +from ansible_collections.cisco.aci.plugins.module_utils.aci import ( + ACIModule, + aci_argument_spec, + aci_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) <samitab@cisco.com> +# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) + +from __future__ import absolute_import, division, print_function + +__metaclass__ = type + +ANSIBLE_METADATA = {"metadata_version": "1.1", "status": ["preview"], "supported_by": "certified"} + +DOCUMENTATION = r""" +--- +module: aci_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: '<?xml version="1.0" encoding="UTF-8"?><imdata totalCount="1"><error code="122" text="unknown managed object class foo"/></imdata>' +sent: + description: The actual/minimal configuration pushed to the APIC + returned: info + type: list + sample: + { + "fvTenant": { + "attributes": { + "descr": "Production environment" + } + } + } +previous: + description: The original configuration from the APIC before the module has started + returned: info + type: list + sample: + [ + { + "fvTenant": { + "attributes": { + "descr": "Production", + "dn": "uni/tn-production", + "name": "production", + "nameAlias": "", + "ownerKey": "", + "ownerTag": "" + } + } + } + ] +proposed: + description: The assembled configuration from the user-provided parameters + returned: info + type: dict + sample: + { + "fvTenant": { + "attributes": { + "descr": "Production environment", + "name": "production" + } + } + } +filter_string: + description: The filter string used for the request + returned: failure or debug + type: str + sample: ?rsp-prop-include=config-only +method: + description: The HTTP method used for the request to the APIC + returned: failure or debug + type: str + sample: POST +response: + description: The HTTP response from the APIC + returned: failure or debug + type: str + sample: OK (30 bytes) +status: + description: The HTTP status from the APIC + returned: failure or debug + type: int + sample: 200 +url: + description: The HTTP url used for the request to the APIC + returned: failure or debug + type: str + sample: https://10.11.12.13/api/mo/uni/tn-production.json +""" + +from ansible.module_utils.basic import AnsibleModule +from ansible_collections.cisco.aci.plugins.module_utils.aci import ( + ACIModule, + aci_argument_spec, + aci_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) <samitab@cisco.com> +# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) + +from __future__ import absolute_import, division, print_function + +__metaclass__ = type + +ANSIBLE_METADATA = {"metadata_version": "1.1", "status": ["preview"], "supported_by": "certified"} + +DOCUMENTATION = r""" +--- +module: aci_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: '<?xml version="1.0" encoding="UTF-8"?><imdata totalCount="1"><error code="122" text="unknown managed object class foo"/></imdata>' +sent: + description: The actual/minimal configuration pushed to the APIC + returned: info + type: list + sample: + { + "fvTenant": { + "attributes": { + "descr": "Production environment" + } + } + } +previous: + description: The original configuration from the APIC before the module has started + returned: info + type: list + sample: + [ + { + "fvTenant": { + "attributes": { + "descr": "Production", + "dn": "uni/tn-production", + "name": "production", + "nameAlias": "", + "ownerKey": "", + "ownerTag": "" + } + } + } + ] +proposed: + description: The assembled configuration from the user-provided parameters + returned: info + type: dict + sample: + { + "fvTenant": { + "attributes": { + "descr": "Production environment", + "name": "production" + } + } + } +filter_string: + description: The filter string used for the request + returned: failure or debug + type: str + sample: ?rsp-prop-include=config-only +method: + description: The HTTP method used for the request to the APIC + returned: failure or debug + type: str + sample: POST +response: + description: The HTTP response from the APIC + returned: failure or debug + type: str + sample: OK (30 bytes) +status: + description: The HTTP status from the APIC + returned: failure or debug + type: int + sample: 200 +url: + description: The HTTP url used for the request to the APIC + returned: failure or debug + type: str + sample: https://10.11.12.13/api/mo/uni/tn-production.json +""" + +from ansible.module_utils.basic import AnsibleModule +from ansible_collections.cisco.aci.plugins.module_utils.aci import ACIModule, aci_argument_spec, aci_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) <anvjain@cisco.com> +# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) + +from __future__ import absolute_import, division, print_function + +__metaclass__ = type + +ANSIBLE_METADATA = {"metadata_version": "1.1", "status": ["preview"], "supported_by": "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: '<?xml version="1.0" encoding="UTF-8"?><imdata totalCount="1"><error code="122" text="unknown managed object class "/></imdata>' + sent: + description: The actual/minimal configuration pushed to the APIC + returned: info + type: list + sample: + { + "fvTenant": { + "attributes": { + "descr": "Production environment" + } + } + } + previous: + description: The original configuration from the APIC before the module has started + returned: info + type: list + sample: + [ + { + "fvTenant": { + "attributes": { + "descr": "Production", + "dn": "uni/tn-production", + "name": "production", + "nameAlias": "", + "ownerKey": "", + "ownerTag": "" + } + } + } + ] + proposed: + description: The assembled configuration from the user-provided parameters + returned: info + type: dict + sample: + { + "fvTenant": { + "attributes": { + "descr": "Production environment", + "name": "production" + } + } + } + filter_string: + description: The filter string used for the request + returned: failure or debug + type: str + sample: ?rsp-prop-include=config-only + method: + description: The HTTP method used for the request to the APIC + returned: failure or debug + type: str + sample: POST + response: + description: The HTTP response from the APIC + returned: failure or debug + type: str + sample: OK (30 bytes) + status: + description: The HTTP status from the APIC + returned: failure or debug + type: int + sample: 200 + url: + description: The HTTP url used for the request to the APIC + returned: failure or debug + type: str + sample: https://10.11.12.13/api/mo/uni/tn-production.json + """ + +from ansible.module_utils.basic import AnsibleModule +from ansible_collections.cisco.aci.plugins.module_utils.aci import ACIModule, aci_argument_spec, aci_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) <anvjain@cisco.com> +# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) + +from __future__ import absolute_import, division, print_function + +__metaclass__ = type + +ANSIBLE_METADATA = {"metadata_version": "1.1", "status": ["preview"], "supported_by": "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: '<?xml version="1.0" encoding="UTF-8"?><imdata totalCount="1"><error code="122" text="unknown managed object class "/></imdata>' + sent: + description: The actual/minimal configuration pushed to the APIC + returned: info + type: list + sample: + { + "fvTenant": { + "attributes": { + "descr": "Production environment" + } + } + } + previous: + description: The original configuration from the APIC before the module has started + returned: info + type: list + sample: + [ + { + "fvTenant": { + "attributes": { + "descr": "Production", + "dn": "uni/tn-production", + "name": "production", + "nameAlias": "", + "ownerKey": "", + "ownerTag": "" + } + } + } + ] + proposed: + description: The assembled configuration from the user-provided parameters + returned: info + type: dict + sample: + { + "fvTenant": { + "attributes": { + "descr": "Production environment", + "name": "production" + } + } + } + filter_string: + description: The filter string used for the request + returned: failure or debug + type: str + sample: ?rsp-prop-include=config-only + method: + description: The HTTP method used for the request to the APIC + returned: failure or debug + type: str + sample: POST + response: + description: The HTTP response from the APIC + returned: failure or debug + type: str + sample: OK (30 bytes) + status: + description: The HTTP status from the APIC + returned: failure or debug + type: int + sample: 200 + url: + description: The HTTP url used for the request to the APIC + returned: failure or debug + type: str + sample: https://10.11.12.13/api/mo/uni/tn-production.json + """ + +from ansible.module_utils.basic import AnsibleModule +from ansible_collections.cisco.aci.plugins.module_utils.aci import ACIModule, aci_argument_spec, aci_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) <gmicol@cisco.com> +# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) + +from __future__ import absolute_import, division, print_function + +__metaclass__ = type + +ANSIBLE_METADATA = {"metadata_version": "1.1", "status": ["preview"], "supported_by": "certified"} + +DOCUMENTATION = r""" +--- +module: aci_interface_policy_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: '<?xml version="1.0" encoding="UTF-8"?><imdata totalCount="1"><error code="122" text="unknown managed object class foo"/></imdata>' +sent: + description: The actual/minimal configuration pushed to the APIC + returned: info + type: list + sample: + { + "fvTenant": { + "attributes": { + "descr": "Production environment" + } + } + } +previous: + description: The original configuration from the APIC before the module has started + returned: info + type: list + sample: + [ + { + "fvTenant": { + "attributes": { + "descr": "Production", + "dn": "uni/tn-production", + "name": "production", + "nameAlias": "", + "ownerKey": "", + "ownerTag": "" + } + } + } + ] +proposed: + description: The assembled configuration from the user-provided parameters + returned: info + type: dict + sample: + { + "fvTenant": { + "attributes": { + "descr": "Production environment", + "name": "production" + } + } + } +filter_string: + description: The filter string used for the request + returned: failure or debug + type: str + sample: ?rsp-prop-include=config-only +method: + description: The HTTP method used for the request to the APIC + returned: failure or debug + type: str + sample: POST +response: + description: The HTTP response from the APIC + returned: failure or debug + type: str + sample: OK (30 bytes) +status: + description: The HTTP status from the APIC + returned: failure or debug + type: int + sample: 200 +url: + description: The HTTP url used for the request to the APIC + returned: failure or debug + type: str + sample: https://10.11.12.13/api/mo/uni/tn-production.json +""" + +from ansible.module_utils.basic import AnsibleModule +from ansible_collections.cisco.aci.plugins.module_utils.aci import ACIModule, aci_argument_spec, aci_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) <ssrish@cisco.com> +# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) + +from __future__ import absolute_import, division, print_function + +__metaclass__ = type + +ANSIBLE_METADATA = {"metadata_version": "1.1", "status": ["preview"], "supported_by": "certified"} + +DOCUMENTATION = r""" +--- +module: aci_interface_policy_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: '<?xml version="1.0" encoding="UTF-8"?><imdata totalCount="1"><error code="122" text="unknown managed object class foo"/></imdata>' +sent: + description: The actual/minimal configuration pushed to the APIC + returned: info + type: list + sample: + { + "fvTenant": { + "attributes": { + "descr": "Production environment" + } + } + } +previous: + description: The original configuration from the APIC before the module has started + returned: info + type: list + sample: + [ + { + "fvTenant": { + "attributes": { + "descr": "Production", + "dn": "uni/tn-production", + "name": "production", + "nameAlias": "", + "ownerKey": "", + "ownerTag": "" + } + } + } + ] +proposed: + description: The assembled configuration from the user-provided parameters + returned: info + type: dict + sample: + { + "fvTenant": { + "attributes": { + "descr": "Production environment", + "name": "production" + } + } + } +filter_string: + description: The filter string used for the request + returned: failure or debug + type: str + sample: ?rsp-prop-include=config-only +method: + description: The HTTP method used for the request to the APIC + returned: failure or debug + type: str + sample: POST +response: + description: The HTTP response from the APIC + returned: failure or debug + type: str + sample: OK (30 bytes) +status: + description: The HTTP status from the APIC + returned: failure or debug + type: int + sample: 200 +url: + description: The HTTP url used for the request to the APIC + returned: failure or debug + type: str + sample: https://10.11.12.13/api/mo/uni/tn-production.json +""" + +from ansible.module_utils.basic import AnsibleModule +from ansible_collections.cisco.aci.plugins.module_utils.aci import ACIModule, aci_argument_spec, aci_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) <gmicol@cisco.com> +# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) + +from __future__ import absolute_import, division, print_function + +__metaclass__ = type + +ANSIBLE_METADATA = {"metadata_version": "1.1", "status": ["preview"], "supported_by": "certified"} + +DOCUMENTATION = r""" +--- +module: aci_interface_policy_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: '<?xml version="1.0" encoding="UTF-8"?><imdata totalCount="1"><error code="122" text="unknown managed object class foo"/></imdata>' +sent: + description: The actual/minimal configuration pushed to the APIC + returned: info + type: list + sample: + { + "fvTenant": { + "attributes": { + "descr": "Production environment" + } + } + } +previous: + description: The original configuration from the APIC before the module has started + returned: info + type: list + sample: + [ + { + "fvTenant": { + "attributes": { + "descr": "Production", + "dn": "uni/tn-production", + "name": "production", + "nameAlias": "", + "ownerKey": "", + "ownerTag": "" + } + } + } + ] +proposed: + description: The assembled configuration from the user-provided parameters + returned: info + type: dict + sample: + { + "fvTenant": { + "attributes": { + "descr": "Production environment", + "name": "production" + } + } + } +filter_string: + description: The filter string used for the request + returned: failure or debug + type: str + sample: ?rsp-prop-include=config-only +method: + description: The HTTP method used for the request to the APIC + returned: failure or debug + type: str + sample: POST +response: + description: The HTTP response from the APIC + returned: failure or debug + type: str + sample: OK (30 bytes) +status: + description: The HTTP status from the APIC + returned: failure or debug + type: int + sample: 200 +url: + description: The HTTP url used for the request to the APIC + returned: failure or debug + type: str + sample: https://10.11.12.13/api/mo/uni/tn-production.json +""" + +from ansible.module_utils.basic import AnsibleModule +from ansible_collections.cisco.aci.plugins.module_utils.aci import ACIModule, aci_argument_spec, aci_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) <gmicol@cisco.com> +# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) + +from __future__ import absolute_import, division, print_function + +__metaclass__ = type + +ANSIBLE_METADATA = {"metadata_version": "1.1", "status": ["preview"], "supported_by": "certified"} + +DOCUMENTATION = r""" +--- +module: aci_interface_policy_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: '<?xml version="1.0" encoding="UTF-8"?><imdata totalCount="1"><error code="122" text="unknown managed object class foo"/></imdata>' +sent: + description: The actual/minimal configuration pushed to the APIC + returned: info + type: list + sample: + { + "fvTenant": { + "attributes": { + "descr": "Production environment" + } + } + } +previous: + description: The original configuration from the APIC before the module has started + returned: info + type: list + sample: + [ + { + "fvTenant": { + "attributes": { + "descr": "Production", + "dn": "uni/tn-production", + "name": "production", + "nameAlias": "", + "ownerKey": "", + "ownerTag": "" + } + } + } + ] +proposed: + description: The assembled configuration from the user-provided parameters + returned: info + type: dict + sample: + { + "fvTenant": { + "attributes": { + "descr": "Production environment", + "name": "production" + } + } + } +filter_string: + description: The filter string used for the request + returned: failure or debug + type: str + sample: ?rsp-prop-include=config-only +method: + description: The HTTP method used for the request to the APIC + returned: failure or debug + type: str + sample: POST +response: + description: The HTTP response from the APIC + returned: failure or debug + type: str + sample: OK (30 bytes) +status: + description: The HTTP status from the APIC + returned: failure or debug + type: int + sample: 200 +url: + description: The HTTP url used for the request to the APIC + returned: failure or debug + type: str + sample: https://10.11.12.13/api/mo/uni/tn-production.json +""" + +from ansible.module_utils.basic import AnsibleModule +from ansible_collections.cisco.aci.plugins.module_utils.aci import ( + ACIModule, + aci_argument_spec, + aci_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) <gmicol@cisco.com> +# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) + +from __future__ import absolute_import, division, print_function + +__metaclass__ = type + +ANSIBLE_METADATA = {"metadata_version": "1.1", "status": ["preview"], "supported_by": "community"} + +DOCUMENTATION = r""" +--- +module: aci_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: '<?xml version="1.0" encoding="UTF-8"?><imdata totalCount="1"><error code="122" text="unknown managed object class foo"/></imdata>' +sent: + description: The actual/minimal configuration pushed to the APIC + returned: info + type: list + sample: + { + "fvTenant": { + "attributes": { + "descr": "Production environment" + } + } + } +previous: + description: The original configuration from the APIC before the module has started + returned: info + type: list + sample: + [ + { + "fvTenant": { + "attributes": { + "descr": "Production", + "dn": "uni/tn-production", + "name": "production", + "nameAlias": "", + "ownerKey": "", + "ownerTag": "" + } + } + } + ] +proposed: + description: The assembled configuration from the user-provided parameters + returned: info + type: dict + sample: + { + "fvTenant": { + "attributes": { + "descr": "Production environment", + "name": "production" + } + } + } +filter_string: + description: The filter string used for the request + returned: failure or debug + type: str + sample: ?rsp-prop-include=config-only +method: + description: The HTTP method used for the request to the APIC + returned: failure or debug + type: str + sample: POST +response: + description: The HTTP response from the APIC + returned: failure or debug + type: str + sample: OK (30 bytes) +status: + description: The HTTP status from the APIC + returned: failure or debug + type: int + sample: 200 +url: + description: The HTTP url used for the request to the APIC + returned: failure or debug + type: str + sample: https://10.11.12.13/api/mo/uni/tn-production.json +""" + + +from ansible.module_utils.basic import AnsibleModule +from ansible_collections.cisco.aci.plugins.module_utils.aci import ACIModule, aci_argument_spec, aci_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) <gmicol@cisco.com> +# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) + +from __future__ import absolute_import, division, print_function + +__metaclass__ = type + +ANSIBLE_METADATA = {"metadata_version": "1.1", "status": ["preview"], "supported_by": "community"} + +DOCUMENTATION = r""" +--- +module: aci_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: '<?xml version="1.0" encoding="UTF-8"?><imdata totalCount="1"><error code="122" text="unknown managed object class foo"/></imdata>' +sent: + description: The actual/minimal configuration pushed to the APIC + returned: info + type: list + sample: + { + "fvTenant": { + "attributes": { + "descr": "Production environment" + } + } + } +previous: + description: The original configuration from the APIC before the module has started + returned: info + type: list + sample: + [ + { + "fvTenant": { + "attributes": { + "descr": "Production", + "dn": "uni/tn-production", + "name": "production", + "nameAlias": "", + "ownerKey": "", + "ownerTag": "" + } + } + } + ] +proposed: + description: The assembled configuration from the user-provided parameters + returned: info + type: dict + sample: + { + "fvTenant": { + "attributes": { + "descr": "Production environment", + "name": "production" + } + } + } +filter_string: + description: The filter string used for the request + returned: failure or debug + type: str + sample: ?rsp-prop-include=config-only +method: + description: The HTTP method used for the request to the APIC + returned: failure or debug + type: str + sample: POST +response: + description: The HTTP response from the APIC + returned: failure or debug + type: str + sample: OK (30 bytes) +status: + description: The HTTP status from the APIC + returned: failure or debug + type: int + sample: 200 +url: + description: The HTTP url used for the request to the APIC + returned: failure or debug + type: str + sample: https://10.11.12.13/api/mo/uni/tn-production.json +""" + + +from ansible.module_utils.basic import AnsibleModule +from ansible_collections.cisco.aci.plugins.module_utils.aci import ACIModule, aci_argument_spec, aci_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) <gmicol@cisco.com> +# Copyright: (c) 2023, Akini Ross (@akinross) <akinross@cisco.com> # GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) 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) <anvjain@cisco.com> +# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) + +from __future__ import absolute_import, division, print_function + +__metaclass__ = type + +ANSIBLE_METADATA = {"metadata_version": "1.1", "status": ["preview"], "supported_by": "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: '<?xml version="1.0" encoding="UTF-8"?><imdata totalCount="1"><error code="122" text="unknown managed object class "/></imdata>' + sent: + description: The actual/minimal configuration pushed to the APIC + returned: info + type: list + sample: + { + "fvTenant": { + "attributes": { + "descr": "Production environment" + } + } + } + previous: + description: The original configuration from the APIC before the module has started + returned: info + type: list + sample: + [ + { + "fvTenant": { + "attributes": { + "descr": "Production", + "dn": "uni/tn-production", + "name": "production", + "nameAlias": "", + "ownerKey": "", + "ownerTag": "" + } + } + } + ] + proposed: + description: The assembled configuration from the user-provided parameters + returned: info + type: dict + sample: + { + "fvTenant": { + "attributes": { + "descr": "Production environment", + "name": "production" + } + } + } + filter_string: + description: The filter string used for the request + returned: failure or debug + type: str + sample: ?rsp-prop-include=config-only + method: + description: The HTTP method used for the request to the APIC + returned: failure or debug + type: str + sample: POST + response: + description: The HTTP response from the APIC + returned: failure or debug + type: str + sample: OK (30 bytes) + status: + description: The HTTP status from the APIC + returned: failure or debug + type: int + sample: 200 + url: + description: The HTTP url used for the request to the APIC + returned: failure or debug + type: str + sample: https://10.11.12.13/api/mo/uni/tn-production.json + """ + +from ansible.module_utils.basic import AnsibleModule +from ansible_collections.cisco.aci.plugins.module_utils.aci import ACIModule, aci_argument_spec, aci_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) <anvjain@cisco.com> +# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) + +from __future__ import absolute_import, division, print_function + +__metaclass__ = type + +ANSIBLE_METADATA = {"metadata_version": "1.1", "status": ["preview"], "supported_by": "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: '<?xml version="1.0" encoding="UTF-8"?><imdata totalCount="1"><error code="122" text="unknown managed object class "/></imdata>' + sent: + description: The actual/minimal configuration pushed to the APIC + returned: info + type: list + sample: + { + "fvTenant": { + "attributes": { + "descr": "Production environment" + } + } + } + previous: + description: The original configuration from the APIC before the module has started + returned: info + type: list + sample: + [ + { + "fvTenant": { + "attributes": { + "descr": "Production", + "dn": "uni/tn-production", + "name": "production", + "nameAlias": "", + "ownerKey": "", + "ownerTag": "" + } + } + } + ] + proposed: + description: The assembled configuration from the user-provided parameters + returned: info + type: dict + sample: + { + "fvTenant": { + "attributes": { + "descr": "Production environment", + "name": "production" + } + } + } + filter_string: + description: The filter string used for the request + returned: failure or debug + type: str + sample: ?rsp-prop-include=config-only + method: + description: The HTTP method used for the request to the APIC + returned: failure or debug + type: str + sample: POST + response: + description: The HTTP response from the APIC + returned: failure or debug + type: str + sample: OK (30 bytes) + status: + description: The HTTP status from the APIC + returned: failure or debug + type: int + sample: 200 + url: + description: The HTTP url used for the request to the APIC + returned: failure or debug + type: str + sample: https://10.11.12.13/api/mo/uni/tn-production.json + """ + +from ansible.module_utils.basic import AnsibleModule +from ansible_collections.cisco.aci.plugins.module_utils.aci import ACIModule, aci_argument_spec, aci_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) <gmicol@cisco.com> +# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) + +from __future__ import absolute_import, division, print_function + +__metaclass__ = type + +ANSIBLE_METADATA = {"metadata_version": "1.1", "status": ["preview"], "supported_by": "community"} + +DOCUMENTATION = r""" +--- +module: aci_l3out_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: '<?xml version="1.0" encoding="UTF-8"?><imdata totalCount="1"><error code="122" text="unknown managed object class foo"/></imdata>' +sent: + description: The actual/minimal configuration pushed to the APIC + returned: info + type: list + sample: + { + "fvTenant": { + "attributes": { + "descr": "Production environment" + } + } + } +previous: + description: The original configuration from the APIC before the module has started + returned: info + type: list + sample: + [ + { + "fvTenant": { + "attributes": { + "descr": "Production", + "dn": "uni/tn-production", + "name": "production", + "nameAlias": "", + "ownerKey": "", + "ownerTag": "" + } + } + } + ] +proposed: + description: The assembled configuration from the user-provided parameters + returned: info + type: dict + sample: + { + "fvTenant": { + "attributes": { + "descr": "Production environment", + "name": "production" + } + } + } +filter_string: + description: The filter string used for the request + returned: failure or debug + type: str + sample: ?rsp-prop-include=config-only +method: + description: The HTTP method used for the request to the APIC + returned: failure or debug + type: str + sample: POST +response: + description: The HTTP response from the APIC + returned: failure or debug + type: str + sample: OK (30 bytes) +status: + description: The HTTP status from the APIC + returned: failure or debug + type: int + sample: 200 +url: + description: The HTTP url used for the request to the APIC + returned: failure or debug + type: str + sample: https://10.11.12.13/api/mo/uni/tn-production.json +""" + + +from ansible.module_utils.basic import AnsibleModule +from ansible_collections.cisco.aci.plugins.module_utils.aci import ACIModule, aci_argument_spec, aci_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) <gmicol@cisco.com> +# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) + +from __future__ import absolute_import, division, print_function + +__metaclass__ = type + +ANSIBLE_METADATA = {"metadata_version": "1.1", "status": ["preview"], "supported_by": "community"} + +DOCUMENTATION = r""" +--- +module: aci_l3out_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: '<?xml version="1.0" encoding="UTF-8"?><imdata totalCount="1"><error code="122" text="unknown managed object class foo"/></imdata>' +sent: + description: The actual/minimal configuration pushed to the APIC + returned: info + type: list + sample: + { + "fvTenant": { + "attributes": { + "descr": "Production environment" + } + } + } +previous: + description: The original configuration from the APIC before the module has started + returned: info + type: list + sample: + [ + { + "fvTenant": { + "attributes": { + "descr": "Production", + "dn": "uni/tn-production", + "name": "production", + "nameAlias": "", + "ownerKey": "", + "ownerTag": "" + } + } + } + ] +proposed: + description: The assembled configuration from the user-provided parameters + returned: info + type: dict + sample: + { + "fvTenant": { + "attributes": { + "descr": "Production environment", + "name": "production" + } + } + } +filter_string: + description: The filter string used for the request + returned: failure or debug + type: str + sample: ?rsp-prop-include=config-only +method: + description: The HTTP method used for the request to the APIC + returned: failure or debug + type: str + sample: POST +response: + description: The HTTP response from the APIC + returned: failure or debug + type: str + sample: OK (30 bytes) +status: + description: The HTTP status from the APIC + returned: failure or debug + type: int + sample: 200 +url: + description: The HTTP url used for the request to the APIC + returned: failure or debug + type: str + sample: https://10.11.12.13/api/mo/uni/tn-production.json +""" + + +from ansible.module_utils.basic import AnsibleModule +from ansible_collections.cisco.aci.plugins.module_utils.aci import ACIModule, aci_argument_spec, aci_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 <ssrish@cisco.com> +# Copyright: (c) 2023, Akini Ross (@akinross) <akinross@cisco.com> # GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) 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 <ssrish@cisco.com> +# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) + +from __future__ import absolute_import, division, print_function + +__metaclass__ = type + +ANSIBLE_METADATA = {"metadata_version": "1.1", "status": ["preview"], "supported_by": "community"} + +DOCUMENTATION = r""" +--- +module: aci_l3out_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: '<?xml version="1.0" encoding="UTF-8"?><imdata totalCount="1"><error code="122" text="unknown managed object class foo"/></imdata>' +sent: + description: The actual/minimal configuration pushed to the APIC + returned: info + type: list + sample: + { + "fvTenant": { + "attributes": { + "descr": "Production environment" + } + } + } +previous: + description: The original configuration from the APIC before the module has started + returned: info + type: list + sample: + [ + { + "fvTenant": { + "attributes": { + "descr": "Production", + "dn": "uni/tn-production", + "name": "production", + "nameAlias": "", + "ownerKey": "", + "ownerTag": "" + } + } + } + ] +proposed: + description: The assembled configuration from the user-provided parameters + returned: info + type: dict + sample: + { + "fvTenant": { + "attributes": { + "descr": "Production environment", + "name": "production" + } + } + } +filter_string: + description: The filter string used for the request + returned: failure or debug + type: str + sample: ?rsp-prop-include=config-only +method: + description: The HTTP method used for the request to the APIC + returned: failure or debug + type: str + sample: POST +response: + description: The HTTP response from the APIC + returned: failure or debug + type: str + sample: OK (30 bytes) +status: + description: The HTTP status from the APIC + returned: failure or debug + type: int + sample: 200 +url: + description: The HTTP url used for the request to the APIC + returned: failure or debug + type: str + sample: https://10.11.12.13/api/mo/uni/tn-production.json +""" + + +from ansible.module_utils.basic import AnsibleModule +from ansible_collections.cisco.aci.plugins.module_utils.aci import ACIModule, aci_argument_spec, aci_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 <ssrish@cisco.com> +# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) + +from __future__ import absolute_import, division, print_function + +__metaclass__ = type + +ANSIBLE_METADATA = {"metadata_version": "1.1", "status": ["preview"], "supported_by": "community"} + +DOCUMENTATION = r""" +--- +module: aci_l3out_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: '<?xml version="1.0" encoding="UTF-8"?><imdata totalCount="1"><error code="122" text="unknown managed object class foo"/></imdata>' +sent: + description: The actual/minimal configuration pushed to the APIC + returned: info + type: list + sample: + { + "fvTenant": { + "attributes": { + "descr": "Production environment" + } + } + } +previous: + description: The original configuration from the APIC before the module has started + returned: info + type: list + sample: + [ + { + "fvTenant": { + "attributes": { + "descr": "Production", + "dn": "uni/tn-production", + "name": "production", + "nameAlias": "", + "ownerKey": "", + "ownerTag": "" + } + } + } + ] +proposed: + description: The assembled configuration from the user-provided parameters + returned: info + type: dict + sample: + { + "fvTenant": { + "attributes": { + "descr": "Production environment", + "name": "production" + } + } + } +filter_string: + description: The filter string used for the request + returned: failure or debug + type: str + sample: ?rsp-prop-include=config-only +method: + description: The HTTP method used for the request to the APIC + returned: failure or debug + type: str + sample: POST +response: + description: The HTTP response from the APIC + returned: failure or debug + type: str + sample: OK (30 bytes) +status: + description: The HTTP status from the APIC + returned: failure or debug + type: int + sample: 200 +url: + description: The HTTP url used for the request to the APIC + returned: failure or debug + type: str + sample: https://10.11.12.13/api/mo/uni/tn-production.json +""" + + +from ansible.module_utils.basic import AnsibleModule +from ansible_collections.cisco.aci.plugins.module_utils.aci import ACIModule, aci_argument_spec, aci_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 <ssrish@cisco.com> +# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) + +from __future__ import absolute_import, division, print_function + +__metaclass__ = type + +ANSIBLE_METADATA = { + "metadata_version": "1.1", + "status": ["preview"], + "supported_by": "community", +} + +DOCUMENTATION = r""" +--- +module: aci_l3out_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: '<?xml version="1.0" encoding="UTF-8"?><imdata totalCount="1"><error code="122" text="unknown managed object class foo"/></imdata>' +sent: + description: The actual/minimal configuration pushed to the APIC + returned: info + type: list + sample: + { + "fvTenant": { + "attributes": { + "descr": "Production environment" + } + } + } +previous: + description: The original configuration from the APIC before the module has started + returned: info + type: list + sample: + [ + { + "fvTenant": { + "attributes": { + "descr": "Production", + "dn": "uni/tn-production", + "name": "production", + "nameAlias": "", + "ownerKey": "", + "ownerTag": "" + } + } + } + ] +proposed: + description: The assembled configuration from the user-provided parameters + returned: info + type: dict + sample: + { + "fvTenant": { + "attributes": { + "descr": "Production environment", + "name": "production" + } + } + } +filter_string: + description: The filter string used for the request + returned: failure or debug + type: str + sample: ?rsp-prop-include=config-only +method: + description: The HTTP method used for the request to the APIC + returned: failure or debug + type: str + sample: POST +response: + description: The HTTP response from the APIC + returned: failure or debug + type: str + sample: OK (30 bytes) +status: + description: The HTTP status from the APIC + returned: failure or debug + type: int + sample: 200 +url: + description: The HTTP url used for the request to the APIC + returned: failure or debug + type: str + sample: https://10.11.12.13/api/mo/uni/tn-production.json +""" + +from ansible_collections.cisco.aci.plugins.module_utils.aci import ACIModule, aci_argument_spec, 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 <ssrish@cisco.com> +# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) + +from __future__ import absolute_import, division, print_function + +__metaclass__ = type + +ANSIBLE_METADATA = { + "metadata_version": "1.1", + "status": ["preview"], + "supported_by": "community", +} + +DOCUMENTATION = r""" +--- +module: aci_l3out_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: '<?xml version="1.0" encoding="UTF-8"?><imdata totalCount="1"><error code="122" text="unknown managed object class foo"/></imdata>' +sent: + description: The actual/minimal configuration pushed to the APIC + returned: info + type: list + sample: + { + "fvTenant": { + "attributes": { + "descr": "Production environment" + } + } + } +previous: + description: The original configuration from the APIC before the module has started + returned: info + type: list + sample: + [ + { + "fvTenant": { + "attributes": { + "descr": "Production", + "dn": "uni/tn-production", + "name": "production", + "nameAlias": "", + "ownerKey": "", + "ownerTag": "" + } + } + } + ] +proposed: + description: The assembled configuration from the user-provided parameters + returned: info + type: dict + sample: + { + "fvTenant": { + "attributes": { + "descr": "Production environment", + "name": "production" + } + } + } +filter_string: + description: The filter string used for the request + returned: failure or debug + type: str + sample: ?rsp-prop-include=config-only +method: + description: The HTTP method used for the request to the APIC + returned: failure or debug + type: str + sample: POST +response: + description: The HTTP response from the APIC + returned: failure or debug + type: str + sample: OK (30 bytes) +status: + description: The HTTP status from the APIC + returned: failure or debug + type: int + sample: 200 +url: + description: The HTTP url used for the request to the APIC + returned: failure or debug + type: str + sample: https://10.11.12.13/api/mo/uni/tn-production.json +""" + +from ansible_collections.cisco.aci.plugins.module_utils.aci import ACIModule, aci_argument_spec, 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) <ssrish@cisco.com> +# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) + +from __future__ import absolute_import, division, print_function + +__metaclass__ = type + +ANSIBLE_METADATA = {"metadata_version": "1.1", "status": ["preview"], "supported_by": "community"} + +DOCUMENTATION = r""" +--- +module: aci_l3out_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: '<?xml version="1.0" encoding="UTF-8"?><imdata totalCount="1"><error code="122" text="unknown managed object class foo"/></imdata>' +sent: + description: The actual/minimal configuration pushed to the APIC + returned: info + type: list + sample: + { + "fvTenant": { + "attributes": { + "descr": "Production environment" + } + } + } +previous: + description: The original configuration from the APIC before the module has started + returned: info + type: list + sample: + [ + { + "fvTenant": { + "attributes": { + "descr": "Production", + "dn": "uni/tn-production", + "name": "production", + "nameAlias": "", + "ownerKey": "", + "ownerTag": "" + } + } + } + ] +proposed: + description: The assembled configuration from the user-provided parameters + returned: info + type: dict + sample: + { + "fvTenant": { + "attributes": { + "descr": "Production environment", + "name": "production" + } + } + } +filter_string: + description: The filter string used for the request + returned: failure or debug + type: str + sample: ?rsp-prop-include=config-only +method: + description: The HTTP method used for the request to the APIC + returned: failure or debug + type: str + sample: POST +response: + description: The HTTP response from the APIC + returned: failure or debug + type: str + sample: OK (30 bytes) +status: + description: The HTTP status from the APIC + returned: failure or debug + type: int + sample: 200 +url: + description: The HTTP url used for the request to the APIC + returned: failure or debug + type: str + sample: https://10.11.12.13/api/mo/uni/tn-production.json +""" + + +from ansible.module_utils.basic import AnsibleModule +from ansible_collections.cisco.aci.plugins.module_utils.aci import ACIModule, aci_argument_spec, aci_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) <ssrish@cisco.com> +# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) + +from __future__ import absolute_import, division, print_function + +__metaclass__ = type + +ANSIBLE_METADATA = {"metadata_version": "1.1", "status": ["preview"], "supported_by": "community"} + +DOCUMENTATION = r""" +--- +module: aci_l3out_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: '<?xml version="1.0" encoding="UTF-8"?><imdata totalCount="1"><error code="122" text="unknown managed object class foo"/></imdata>' +sent: + description: The actual/minimal configuration pushed to the APIC + returned: info + type: list + sample: + { + "fvTenant": { + "attributes": { + "descr": "Production environment" + } + } + } +previous: + description: The original configuration from the APIC before the module has started + returned: info + type: list + sample: + [ + { + "fvTenant": { + "attributes": { + "descr": "Production", + "dn": "uni/tn-production", + "name": "production", + "nameAlias": "", + "ownerKey": "", + "ownerTag": "" + } + } + } + ] +proposed: + description: The assembled configuration from the user-provided parameters + returned: info + type: dict + sample: + { + "fvTenant": { + "attributes": { + "descr": "Production environment", + "name": "production" + } + } + } +filter_string: + description: The filter string used for the request + returned: failure or debug + type: str + sample: ?rsp-prop-include=config-only +method: + description: The HTTP method used for the request to the APIC + returned: failure or debug + type: str + sample: POST +response: + description: The HTTP response from the APIC + returned: failure or debug + type: str + sample: OK (30 bytes) +status: + description: The HTTP status from the APIC + returned: failure or debug + type: int + sample: 200 +url: + description: The HTTP url used for the request to the APIC + returned: failure or debug + type: str + sample: https://10.11.12.13/api/mo/uni/tn-production.json +""" + + +from ansible.module_utils.basic import AnsibleModule +from ansible_collections.cisco.aci.plugins.module_utils.aci import ACIModule, aci_argument_spec, aci_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) <ssrish@cisco.com> +# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) + +from __future__ import absolute_import, division, print_function + +__metaclass__ = type + +ANSIBLE_METADATA = {"metadata_version": "1.1", "status": ["preview"], "supported_by": "community"} + +DOCUMENTATION = r""" +--- +module: aci_l3out_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: '<?xml version="1.0" encoding="UTF-8"?><imdata totalCount="1"><error code="122" text="unknown managed object class foo"/></imdata>' +sent: + description: The actual/minimal configuration pushed to the APIC + returned: info + type: list + sample: + { + "fvTenant": { + "attributes": { + "descr": "Production environment" + } + } + } +previous: + description: The original configuration from the APIC before the module has started + returned: info + type: list + sample: + [ + { + "fvTenant": { + "attributes": { + "descr": "Production", + "dn": "uni/tn-production", + "name": "production", + "nameAlias": "", + "ownerKey": "", + "ownerTag": "" + } + } + } + ] +proposed: + description: The assembled configuration from the user-provided parameters + returned: info + type: dict + sample: + { + "fvTenant": { + "attributes": { + "descr": "Production environment", + "name": "production" + } + } + } +filter_string: + description: The filter string used for the request + returned: failure or debug + type: str + sample: ?rsp-prop-include=config-only +method: + description: The HTTP method used for the request to the APIC + returned: failure or debug + type: str + sample: POST +response: + description: The HTTP response from the APIC + returned: failure or debug + type: str + sample: OK (30 bytes) +status: + description: The HTTP status from the APIC + returned: failure or debug + type: int + sample: 200 +url: + description: The HTTP url used for the request to the APIC + returned: failure or debug + type: str + sample: https://10.11.12.13/api/mo/uni/tn-production.json +""" + + +from ansible.module_utils.basic import AnsibleModule +from ansible_collections.cisco.aci.plugins.module_utils.aci import ACIModule, aci_argument_spec, aci_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) <akinross@cisco.com> # GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) from __future__ import absolute_import, division, print_function @@ -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) <gmicol@cisco.com> # GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) from __future__ import absolute_import, division, print_function @@ -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) <jasonjuenger@gmail.com> +# Copyright: (c) 2023, Gaspard Micol (@gmicol) <gmicol@cisco.com> # GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) 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) <akinross@cisco.com> # GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) from __future__ import absolute_import, division, print_function @@ -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) <akinross@cisco.com> # GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) from __future__ import absolute_import, division, print_function @@ -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) <akinross@cisco.com> +# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) + +from __future__ import absolute_import, division, print_function + +__metaclass__ = type + +ANSIBLE_METADATA = { + "metadata_version": "1.1", + "status": ["preview"], + "supported_by": "certified", +} + +DOCUMENTATION = r""" +--- +module: aci_l3out_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: '<?xml version="1.0" encoding="UTF-8"?><imdata totalCount="1"><error code="122" text="unknown managed object class foo"/></imdata>' +sent: + description: The actual/minimal configuration pushed to the APIC + returned: info + type: list + sample: + { + "fvTenant": { + "attributes": { + "descr": "Production environment" + } + } + } +previous: + description: The original configuration from the APIC before the module has started + returned: info + type: list + sample: + [ + { + "fvTenant": { + "attributes": { + "descr": "Production", + "dn": "uni/tn-production", + "name": "production", + "nameAlias": "", + "ownerKey": "", + "ownerTag": "" + } + } + } + ] +proposed: + description: The assembled configuration from the user-provided parameters + returned: info + type: dict + sample: + { + "fvTenant": { + "attributes": { + "descr": "Production environment", + "name": "production" + } + } + } +filter_string: + description: The filter string used for the request + returned: failure or debug + type: str + sample: ?rsp-prop-include=config-only +method: + description: The HTTP method used for the request to the APIC + returned: failure or debug + type: str + sample: POST +response: + description: The HTTP response from the APIC + returned: failure or debug + type: str + sample: OK (30 bytes) +status: + description: The HTTP status from the APIC + returned: failure or debug + type: int + sample: 200 +url: + description: The HTTP url used for the request to the APIC + returned: failure or debug + type: str + sample: https://10.11.12.13/api/mo/uni/tn-production.json +""" + +from ansible.module_utils.basic import AnsibleModule +from ansible_collections.cisco.aci.plugins.module_utils.aci import ACIModule, aci_argument_spec, aci_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) <gmicol@cisco.com> +# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) + +from __future__ import absolute_import, division, print_function + +__metaclass__ = type + +ANSIBLE_METADATA = {"metadata_version": "1.1", "status": ["preview"], "supported_by": "community"} + +DOCUMENTATION = r""" +--- +module: aci_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: '<?xml version="1.0" encoding="UTF-8"?><imdata totalCount="1"><error code="122" text="unknown managed object class foo"/></imdata>' +sent: + description: The actual/minimal configuration pushed to the APIC + returned: info + type: list + sample: + { + "fvTenant": { + "attributes": { + "descr": "Production environment" + } + } + } +previous: + description: The original configuration from the APIC before the module has started + returned: info + type: list + sample: + [ + { + "fvTenant": { + "attributes": { + "descr": "Production", + "dn": "uni/tn-production", + "name": "production", + "nameAlias": "", + "ownerKey": "", + "ownerTag": "" + } + } + } + ] +proposed: + description: The assembled configuration from the user-provided parameters + returned: info + type: dict + sample: + { + "fvTenant": { + "attributes": { + "descr": "Production environment", + "name": "production" + } + } + } +filter_string: + description: The filter string used for the request + returned: failure or debug + type: str + sample: ?rsp-prop-include=config-only +method: + description: The HTTP method used for the request to the APIC + returned: failure or debug + type: str + sample: POST +response: + description: The HTTP response from the APIC + returned: failure or debug + type: str + sample: OK (30 bytes) +status: + description: The HTTP status from the APIC + returned: failure or debug + type: int + sample: 200 +url: + description: The HTTP url used for the request to the APIC + returned: failure or debug + type: str + sample: https://10.11.12.13/api/mo/uni/tn-production.json +""" + + +from ansible.module_utils.basic import AnsibleModule +from ansible_collections.cisco.aci.plugins.module_utils.aci import ( + ACIModule, + aci_argument_spec, + aci_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) <gmicol@cisco.com> +# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) + +from __future__ import absolute_import, division, print_function + +__metaclass__ = type + +ANSIBLE_METADATA = {"metadata_version": "1.1", "status": ["preview"], "supported_by": "community"} + +DOCUMENTATION = r""" +--- +module: aci_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: '<?xml version="1.0" encoding="UTF-8"?><imdata totalCount="1"><error code="122" text="unknown managed object class foo"/></imdata>' +sent: + description: The actual/minimal configuration pushed to the APIC + returned: info + type: list + sample: + { + "fvTenant": { + "attributes": { + "descr": "Production environment" + } + } + } +previous: + description: The original configuration from the APIC before the module has started + returned: info + type: list + sample: + [ + { + "fvTenant": { + "attributes": { + "descr": "Production", + "dn": "uni/tn-production", + "name": "production", + "nameAlias": "", + "ownerKey": "", + "ownerTag": "" + } + } + } + ] +proposed: + description: The assembled configuration from the user-provided parameters + returned: info + type: dict + sample: + { + "fvTenant": { + "attributes": { + "descr": "Production environment", + "name": "production" + } + } + } +filter_string: + description: The filter string used for the request + returned: failure or debug + type: str + sample: ?rsp-prop-include=config-only +method: + description: The HTTP method used for the request to the APIC + returned: failure or debug + type: str + sample: POST +response: + description: The HTTP response from the APIC + returned: failure or debug + type: str + sample: OK (30 bytes) +status: + description: The HTTP status from the APIC + returned: failure or debug + type: int + sample: 200 +url: + description: The HTTP url used for the request to the APIC + returned: failure or debug + type: str + sample: https://10.11.12.13/api/mo/uni/tn-production.json +""" + + +from ansible.module_utils.basic import AnsibleModule +from ansible_collections.cisco.aci.plugins.module_utils.aci import ACIModule, aci_argument_spec, aci_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) <gmicol@cisco.com> +# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) + +from __future__ import absolute_import, division, print_function + +__metaclass__ = type + +ANSIBLE_METADATA = {"metadata_version": "1.1", "status": ["preview"], "supported_by": "community"} + +DOCUMENTATION = r""" +--- +module: aci_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: '<?xml version="1.0" encoding="UTF-8"?><imdata totalCount="1"><error code="122" text="unknown managed object class foo"/></imdata>' +sent: + description: The actual/minimal configuration pushed to the APIC + returned: info + type: list + sample: + { + "fvTenant": { + "attributes": { + "descr": "Production environment" + } + } + } +previous: + description: The original configuration from the APIC before the module has started + returned: info + type: list + sample: + [ + { + "fvTenant": { + "attributes": { + "descr": "Production", + "dn": "uni/tn-production", + "name": "production", + "nameAlias": "", + "ownerKey": "", + "ownerTag": "" + } + } + } + ] +proposed: + description: The assembled configuration from the user-provided parameters + returned: info + type: dict + sample: + { + "fvTenant": { + "attributes": { + "descr": "Production environment", + "name": "production" + } + } + } +filter_string: + description: The filter string used for the request + returned: failure or debug + type: str + sample: ?rsp-prop-include=config-only +method: + description: The HTTP method used for the request to the APIC + returned: failure or debug + type: str + sample: POST +response: + description: The HTTP response from the APIC + returned: failure or debug + type: str + sample: OK (30 bytes) +status: + description: The HTTP status from the APIC + returned: failure or debug + type: int + sample: 200 +url: + description: The HTTP url used for the request to the APIC + returned: failure or debug + type: str + sample: https://10.11.12.13/api/mo/uni/tn-production.json +""" + + +from ansible.module_utils.basic import AnsibleModule +from ansible_collections.cisco.aci.plugins.module_utils.aci import ACIModule, aci_argument_spec, aci_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) <gmicol@cisco.com> +# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) + +from __future__ import absolute_import, division, print_function + +__metaclass__ = type + +ANSIBLE_METADATA = {"metadata_version": "1.1", "status": ["preview"], "supported_by": "community"} + +DOCUMENTATION = r""" +--- +module: aci_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: '<?xml version="1.0" encoding="UTF-8"?><imdata totalCount="1"><error code="122" text="unknown managed object class foo"/></imdata>' +sent: + description: The actual/minimal configuration pushed to the APIC + returned: info + type: list + sample: + { + "fvTenant": { + "attributes": { + "descr": "Production environment" + } + } + } +previous: + description: The original configuration from the APIC before the module has started + returned: info + type: list + sample: + [ + { + "fvTenant": { + "attributes": { + "descr": "Production", + "dn": "uni/tn-production", + "name": "production", + "nameAlias": "", + "ownerKey": "", + "ownerTag": "" + } + } + } + ] +proposed: + description: The assembled configuration from the user-provided parameters + returned: info + type: dict + sample: + { + "fvTenant": { + "attributes": { + "descr": "Production environment", + "name": "production" + } + } + } +filter_string: + description: The filter string used for the request + returned: failure or debug + type: str + sample: ?rsp-prop-include=config-only +method: + description: The HTTP method used for the request to the APIC + returned: failure or debug + type: str + sample: POST +response: + description: The HTTP response from the APIC + returned: failure or debug + type: str + sample: OK (30 bytes) +status: + description: The HTTP status from the APIC + returned: failure or debug + type: int + sample: 200 +url: + description: The HTTP url used for the request to the APIC + returned: failure or debug + type: str + sample: https://10.11.12.13/api/mo/uni/tn-production.json +""" + + +from ansible.module_utils.basic import AnsibleModule +from ansible_collections.cisco.aci.plugins.module_utils.aci import ACIModule, aci_argument_spec, aci_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) <gmicol@cisco.com> +# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) + +from __future__ import absolute_import, division, print_function + +__metaclass__ = type + +ANSIBLE_METADATA = {"metadata_version": "1.1", "status": ["preview"], "supported_by": "certified"} + +DOCUMENTATION = r""" +--- +module: aci_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: '<?xml version="1.0" encoding="UTF-8"?><imdata totalCount="1"><error code="122" text="unknown managed object class foo"/></imdata>' +sent: + description: The actual/minimal configuration pushed to the APIC + returned: info + type: list + sample: + { + "fvTenant": { + "attributes": { + "descr": "Production environment" + } + } + } +previous: + description: The original configuration from the APIC before the module has started + returned: info + type: list + sample: + [ + { + "fvTenant": { + "attributes": { + "descr": "Production", + "dn": "uni/tn-production", + "name": "production", + "nameAlias": "", + "ownerKey": "", + "ownerTag": "" + } + } + } + ] +proposed: + description: The assembled configuration from the user-provided parameters + returned: info + type: dict + sample: + { + "fvTenant": { + "attributes": { + "descr": "Production environment", + "name": "production" + } + } + } +filter_string: + description: The filter string used for the request + returned: failure or debug + type: str + sample: ?rsp-prop-include=config-only +method: + description: The HTTP method used for the request to the APIC + returned: failure or debug + type: str + sample: POST +response: + description: The HTTP response from the APIC + returned: failure or debug + type: str + sample: OK (30 bytes) +status: + description: The HTTP status from the APIC + returned: failure or debug + type: int + sample: 200 +url: + description: The HTTP url used for the request to the APIC + returned: failure or debug + type: str + sample: https://10.11.12.13/api/mo/uni/tn-production.json +""" + +from ansible.module_utils.basic import AnsibleModule +from ansible_collections.cisco.aci.plugins.module_utils.aci import ACIModule, aci_argument_spec, aci_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) <gmicol@cisco.com> +# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) + +from __future__ import absolute_import, division, print_function + +__metaclass__ = type + +ANSIBLE_METADATA = {"metadata_version": "1.1", "status": ["preview"], "supported_by": "community"} + +DOCUMENTATION = r""" +--- +module: aci_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: '<?xml version="1.0" encoding="UTF-8"?><imdata totalCount="1"><error code="122" text="unknown managed object class foo"/></imdata>' +sent: + description: The actual/minimal configuration pushed to the APIC + returned: info + type: list + sample: + { + "fvTenant": { + "attributes": { + "descr": "Production environment" + } + } + } +previous: + description: The original configuration from the APIC before the module has started + returned: info + type: list + sample: + [ + { + "fvTenant": { + "attributes": { + "descr": "Production", + "dn": "uni/tn-production", + "name": "production", + "nameAlias": "", + "ownerKey": "", + "ownerTag": "" + } + } + } + ] +proposed: + description: The assembled configuration from the user-provided parameters + returned: info + type: dict + sample: + { + "fvTenant": { + "attributes": { + "descr": "Production environment", + "name": "production" + } + } + } +filter_string: + description: The filter string used for the request + returned: failure or debug + type: str + sample: ?rsp-prop-include=config-only +method: + description: The HTTP method used for the request to the APIC + returned: failure or debug + type: str + sample: POST +response: + description: The HTTP response from the APIC + returned: failure or debug + type: str + sample: OK (30 bytes) +status: + description: The HTTP status from the APIC + returned: failure or debug + type: int + sample: 200 +url: + description: The HTTP url used for the request to the APIC + returned: failure or debug + type: str + sample: https://10.11.12.13/api/mo/uni/tn-production.json +""" + + +from ansible.module_utils.basic import AnsibleModule +from ansible_collections.cisco.aci.plugins.module_utils.aci import ACIModule, aci_argument_spec, aci_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) <gmicol@cisco.com> +# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) + +from __future__ import absolute_import, division, print_function + +__metaclass__ = type + +ANSIBLE_METADATA = {"metadata_version": "1.1", "status": ["preview"], "supported_by": "community"} + +DOCUMENTATION = r""" +--- +module: aci_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: '<?xml version="1.0" encoding="UTF-8"?><imdata totalCount="1"><error code="122" text="unknown managed object class foo"/></imdata>' +sent: + description: The actual/minimal configuration pushed to the APIC + returned: info + type: list + sample: + { + "fvTenant": { + "attributes": { + "descr": "Production environment" + } + } + } +previous: + description: The original configuration from the APIC before the module has started + returned: info + type: list + sample: + [ + { + "fvTenant": { + "attributes": { + "descr": "Production", + "dn": "uni/tn-production", + "name": "production", + "nameAlias": "", + "ownerKey": "", + "ownerTag": "" + } + } + } + ] +proposed: + description: The assembled configuration from the user-provided parameters + returned: info + type: dict + sample: + { + "fvTenant": { + "attributes": { + "descr": "Production environment", + "name": "production" + } + } + } +filter_string: + description: The filter string used for the request + returned: failure or debug + type: str + sample: ?rsp-prop-include=config-only +method: + description: The HTTP method used for the request to the APIC + returned: failure or debug + type: str + sample: POST +response: + description: The HTTP response from the APIC + returned: failure or debug + type: str + sample: OK (30 bytes) +status: + description: The HTTP status from the APIC + returned: failure or debug + type: int + sample: 200 +url: + description: The HTTP url used for the request to the APIC + returned: failure or debug + type: str + sample: https://10.11.12.13/api/mo/uni/tn-production.json +""" + + +from ansible.module_utils.basic import AnsibleModule +from ansible_collections.cisco.aci.plugins.module_utils.aci import ACIModule, aci_argument_spec, aci_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) <gmicol@cisco.com> +# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) + +from __future__ import absolute_import, division, print_function + +__metaclass__ = type + +ANSIBLE_METADATA = {"metadata_version": "1.1", "status": ["preview"], "supported_by": "community"} + +DOCUMENTATION = r""" +--- +module: aci_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: '<?xml version="1.0" encoding="UTF-8"?><imdata totalCount="1"><error code="122" text="unknown managed object class foo"/></imdata>' +sent: + description: The actual/minimal configuration pushed to the APIC + returned: info + type: list + sample: + { + "fvTenant": { + "attributes": { + "descr": "Production environment" + } + } + } +previous: + description: The original configuration from the APIC before the module has started + returned: info + type: list + sample: + [ + { + "fvTenant": { + "attributes": { + "descr": "Production", + "dn": "uni/tn-production", + "name": "production", + "nameAlias": "", + "ownerKey": "", + "ownerTag": "" + } + } + } + ] +proposed: + description: The assembled configuration from the user-provided parameters + returned: info + type: dict + sample: + { + "fvTenant": { + "attributes": { + "descr": "Production environment", + "name": "production" + } + } + } +filter_string: + description: The filter string used for the request + returned: failure or debug + type: str + sample: ?rsp-prop-include=config-only +method: + description: The HTTP method used for the request to the APIC + returned: failure or debug + type: str + sample: POST +response: + description: The HTTP response from the APIC + returned: failure or debug + type: str + sample: OK (30 bytes) +status: + description: The HTTP status from the APIC + returned: failure or debug + type: int + sample: 200 +url: + description: The HTTP url used for the request to the APIC + returned: failure or debug + type: str + sample: https://10.11.12.13/api/mo/uni/tn-production.json +""" + + +from ansible.module_utils.basic import AnsibleModule +from ansible_collections.cisco.aci.plugins.module_utils.aci import ACIModule, aci_argument_spec, aci_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) <gmicol@cisco.com> +# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) + +from __future__ import absolute_import, division, print_function + +__metaclass__ = type + +ANSIBLE_METADATA = {"metadata_version": "1.1", "status": ["preview"], "supported_by": "community"} + +DOCUMENTATION = r""" +--- +module: aci_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: '<?xml version="1.0" encoding="UTF-8"?><imdata totalCount="1"><error code="122" text="unknown managed object class foo"/></imdata>' +sent: + description: The actual/minimal configuration pushed to the APIC + returned: info + type: list + sample: + { + "fvTenant": { + "attributes": { + "descr": "Production environment" + } + } + } +previous: + description: The original configuration from the APIC before the module has started + returned: info + type: list + sample: + [ + { + "fvTenant": { + "attributes": { + "descr": "Production", + "dn": "uni/tn-production", + "name": "production", + "nameAlias": "", + "ownerKey": "", + "ownerTag": "" + } + } + } + ] +proposed: + description: The assembled configuration from the user-provided parameters + returned: info + type: dict + sample: + { + "fvTenant": { + "attributes": { + "descr": "Production environment", + "name": "production" + } + } + } +filter_string: + description: The filter string used for the request + returned: failure or debug + type: str + sample: ?rsp-prop-include=config-only +method: + description: The HTTP method used for the request to the APIC + returned: failure or debug + type: str + sample: POST +response: + description: The HTTP response from the APIC + returned: failure or debug + type: str + sample: OK (30 bytes) +status: + description: The HTTP status from the APIC + returned: failure or debug + type: int + sample: 200 +url: + description: The HTTP url used for the request to the APIC + returned: failure or debug + type: str + sample: https://10.11.12.13/api/mo/uni/tn-production.json +""" + + +from ansible.module_utils.basic import AnsibleModule +from ansible_collections.cisco.aci.plugins.module_utils.aci import ( + ACIModule, + aci_argument_spec, + aci_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) <gmicol@cisco.com> +# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) + +from __future__ import absolute_import, division, print_function + +__metaclass__ = type + +ANSIBLE_METADATA = {"metadata_version": "1.1", "status": ["preview"], "supported_by": "community"} + +DOCUMENTATION = r""" +--- +module: aci_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: '<?xml version="1.0" encoding="UTF-8"?><imdata totalCount="1"><error code="122" text="unknown managed object class foo"/></imdata>' +sent: + description: The actual/minimal configuration pushed to the APIC + returned: info + type: list + sample: + { + "fvTenant": { + "attributes": { + "descr": "Production environment" + } + } + } +previous: + description: The original configuration from the APIC before the module has started + returned: info + type: list + sample: + [ + { + "fvTenant": { + "attributes": { + "descr": "Production", + "dn": "uni/tn-production", + "name": "production", + "nameAlias": "", + "ownerKey": "", + "ownerTag": "" + } + } + } + ] +proposed: + description: The assembled configuration from the user-provided parameters + returned: info + type: dict + sample: + { + "fvTenant": { + "attributes": { + "descr": "Production environment", + "name": "production" + } + } + } +filter_string: + description: The filter string used for the request + returned: failure or debug + type: str + sample: ?rsp-prop-include=config-only +method: + description: The HTTP method used for the request to the APIC + returned: failure or debug + type: str + sample: POST +response: + description: The HTTP response from the APIC + returned: failure or debug + type: str + sample: OK (30 bytes) +status: + description: The HTTP status from the APIC + returned: failure or debug + type: int + sample: 200 +url: + description: The HTTP url used for the request to the APIC + returned: failure or debug + type: str + sample: https://10.11.12.13/api/mo/uni/tn-production.json +""" + + +from ansible.module_utils.basic import AnsibleModule +from ansible_collections.cisco.aci.plugins.module_utils.aci import ( + ACIModule, + aci_argument_spec, + aci_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) <dag@wieers.com> # Copyright: (c) 2020, Cindy Zhao (@cizhao) <cizhao@cisco.com> +# Copyright: (c) 2023, Samita Bhattacharjee (@samitab) <samitab@cisco.com> # GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) from __future__ import absolute_import, division, print_function @@ -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 <akinross@cisco.com> +# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) + +from __future__ import absolute_import, division, print_function + +__metaclass__ = type + +ANSIBLE_METADATA = {"metadata_version": "1.1", "status": ["preview"], "supported_by": "certified"} + +DOCUMENTATION = r""" +--- +module: aci_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: '<?xml version="1.0" encoding="UTF-8"?><imdata totalCount="1"><error code="122" text="unknown managed object class foo"/></imdata>' +sent: + description: The actual/minimal configuration pushed to the APIC + returned: info + type: list + sample: + { + "fvTenant": { + "attributes": { + "descr": "Production environment" + } + } + } +previous: + description: The original configuration from the APIC before the module has started + returned: info + type: list + sample: + [ + { + "fvTenant": { + "attributes": { + "descr": "Production", + "dn": "uni/tn-production", + "name": "production", + "nameAlias": "", + "ownerKey": "", + "ownerTag": "" + } + } + } + ] +proposed: + description: The assembled configuration from the user-provided parameters + returned: info + type: dict + sample: + { + "fvTenant": { + "attributes": { + "descr": "Production environment", + "name": "production" + } + } + } +filter_string: + description: The filter string used for the request + returned: failure or debug + type: str + sample: ?rsp-prop-include=config-only +method: + description: The HTTP method used for the request to the APIC + returned: failure or debug + type: str + sample: POST +response: + description: The HTTP response from the APIC + returned: failure or debug + type: str + sample: OK (30 bytes) +status: + description: The HTTP status from the APIC + returned: failure or debug + type: int + sample: 200 +url: + description: The HTTP url used for the request to the APIC + returned: failure or debug + type: str + sample: https://10.11.12.13/api/mo/uni/tn-production.json +""" + +from ansible.module_utils.basic import AnsibleModule +from ansible_collections.cisco.aci.plugins.module_utils.aci import ACIModule, aci_argument_spec, aci_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 <brunocalogero@hotmail.com> +# Copyright: (c) 2024, Gaspard Micol (@gmicol) <gmicol@cisco.com> # GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) from __future__ import absolute_import, division, print_function @@ -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) <tcragg@cisco.com> +# Copyright: (c) 2023, Gaspard Micol (@gmicol) <gmicol@cisco.com> # GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) 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 <mawidmer@cisco.com> # Copyright: (c) 2021, Anvitha Jain (@anvitha-jain) <anvjain@cisco.com> +# Copyright: (c) 2023, Akini Ross (@akinross) <akinross@cisco.com> # GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) 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: '<?xml version="1.0" encoding="UTF-8"?><imdata totalCount="1"><error code="122" text="unknown managed object class "/></imdata>' + sent: + description: The actual/minimal configuration pushed to the APIC + returned: info + type: list + sample: + { + "fvTenant": { + "attributes": { + "descr": "Production environment" + } + } + } + previous: + description: The original configuration from the APIC before the module has started + returned: info + type: list + sample: + [ + { + "fvTenant": { + "attributes": { + "descr": "Production", + "dn": "uni/tn-production", + "name": "production", + "nameAlias": "", + "ownerKey": "", + "ownerTag": "" + } + } + } + ] + proposed: + description: The assembled configuration from the user-provided parameters + returned: info + type: dict + sample: + { + "fvTenant": { + "attributes": { + "descr": "Production environment", + "name": "production" + } + } + } + filter_string: + description: The filter string used for the request + returned: failure or debug + type: str + sample: ?rsp-prop-include=config-only + method: + description: The HTTP method used for the request to the APIC + returned: failure or debug + type: str + sample: POST + response: + description: The HTTP response from the APIC + returned: failure or debug + type: str + sample: OK (30 bytes) + status: + description: The HTTP status from the APIC + returned: failure or debug + type: int + sample: 200 + url: + description: The HTTP url used for the request to the APIC + returned: failure or debug + type: str + sample: https://10.11.12.13/api/mo/uni/tn-production.json + """ + +from ansible.module_utils.basic import AnsibleModule +from ansible_collections.cisco.aci.plugins.module_utils.aci import ACIModule, aci_argument_spec, aci_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) <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_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) <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: 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 <ssrish@cisco.com> # Copyright: (c) 2017, Bruno Calogero <brunocalogero@hotmail.com> +# Copyright: (c) 2024, Gaspard Micol (@gmicol) <gmicol@cisco.com> # GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) - name: Test that we have an ACI APIC host, ACI username and ACI password - fail: + 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) <gmicol@cisco.com> + +# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) + +- name: Test that we have an ACI APIC host, ACI username and ACI password + 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) <gmicol@cisco.com> + +# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) + +- name: Test that we have an ACI APIC host, ACI username and ACI password + 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) <gmicol@cisco.com> + +# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) + +- name: Test that we have an ACI APIC host, ACI username and ACI password + 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) <gmicol@cisco.com> + +# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) + +- name: Test that we have an ACI APIC host, ACI username and ACI password + 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) <gmicol@cisco.com> + +# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) + +- name: Test that we have an ACI APIC host, ACI username and ACI password + 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) <gmicol@cisco.com> + +# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) + +- name: Test that we have an ACI APIC host, ACI username and ACI password + 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) <gmicol@cisco.com> + +# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) + +- name: Test that we have an ACI APIC host, ACI username and ACI password + 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) <gmicol@cisco.com> + +# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) + +- name: Test that we have an ACI APIC host, ACI username and ACI password + 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) <dag@wieers.com> +# Copyright: (c) 2024, Samita Bhattacharjee (@samiib) <samitab@cisco.com> # GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) - name: Test that we have an ACI APIC host, ACI username and ACI password - fail: + 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) <samitab@cisco.com> # GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) - name: Test that we have an ACI APIC host, ACI username and ACI password - fail: + 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) <samitab@cisco.com> # GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) - name: Test that we have an ACI APIC host, ACI username and ACI password - fail: + 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: + ansible.builtin.assert: that: - bd_present_check_mode is changed - bd_present_check_mode.sent.fvBD.attributes.descr == 'Ansible Test' @@ -172,8 +313,8 @@ - 'bd_present_missing_param.msg == "state is present but all of the following are missing: tenant"' when: version.current.0.topSystem.attributes.version is version('4.2', '<') - - name: present asserts (>v4.2) - assert: + - name: present asserts (>=v4.2 & <v6.0) + ansible.builtin.assert: that: - bd_present_check_mode is changed - bd_present_check_mode.sent.fvBD.attributes.descr == 'Ansible Test' @@ -193,16 +334,243 @@ - bd_present_2b.sent.fvBD.attributes.ipLearning == 'no' - bd_present_2b.sent.fvBD.attributes.multiDstPktAct == 'drop' - bd_present_2b.sent.fvBD.attributes.name == 'anstest2' - - bd_present_2b.sent.fvBD.attributes.unicastRoute == 'no' + - bd_present_2b.sent.fvBD.attributes.unicastRoute == 'yes' - bd_present_2b.sent.fvBD.attributes.unkMacUcastAct == 'flood' - bd_present_2b.sent.fvBD.attributes.unkMcastAct == 'opt-flood' - bd_present_2b.sent.fvBD.attributes.v6unkMcastAct == 'opt-flood' - bd_present_2b.sent.fvBD.attributes.type == 'regular' - - bd_present_2b.sent.fvBD.children.0.fvRsBDToProfile.attributes.tnL3extOutName == 'ansible_l3out' - - bd_present_2b.sent.fvBD.children.0.fvRsBDToProfile.attributes.tnRtctrlProfileName == 'ansible_l3out_route' + - bd_present_2b.sent.fvBD.attributes.hostBasedRouting == 'yes' + - bd_present_2b.sent.fvBD.attributes.intersiteBumTrafficAllow == 'yes' + - bd_present_2b.sent.fvBD.attributes.intersiteL2Stretch == 'yes' + - bd_present_2b.sent.fvBD.attributes.ipv6McastAllow == 'yes' + - bd_present_2b.sent.fvBD.attributes.llAddr == 'fe80::1322:33ff:fe44:5566' + - bd_present_2b.sent.fvBD.attributes.vmac == '00:AA:BB:CC:DD:03' + - bd_present_2b.sent.fvBD.attributes.OptimizeWanBandwidth == 'yes' + - bd_present_2b.sent.fvBD.children.0.fvRsIgmpsn.attributes.tnIgmpSnoopPolName == 'ansible_igmp_snoop' + - bd_present_2b.sent.fvBD.children.1.fvRsMldsn.attributes.tnMldSnoopPolName == 'ansible_mld_snoop' + - bd_present_2b.sent.fvBD.children.2.fvRsBDToProfile.attributes.tnL3extOutName == 'ansible_l3out' + - bd_present_2b.sent.fvBD.children.2.fvRsBDToProfile.attributes.tnRtctrlProfileName == 'ansible_l3out_route' + - bd_present_2b.sent.fvBD.children.3.fvRsBDToFhs.attributes.tnFhsBDPolName == 'ansible_fhs' + - bd_present_2b.sent.fvBD.children.4.fvAccP.attributes.encap == 'vlan-101' + - bd_present_2b.sent.fvBD.children.5.fvRsABDPolMonPol.attributes.tnMonEPGPolName == 'ansible_monitoring_pol' + - bd_present_2b.sent.fvBD.children.6.igmpIfP.children.0.igmpRsIfPol.attributes.tDn == 'uni/tn-ansible_test/igmpIfPol-ansible_igmp_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('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: 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) <samitab@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 + +# 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) <samitab@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") }}' + +# 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) <gmicol@cisco.com> + +# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) + +- name: Test that we have an ACI APIC host, ACI username and ACI password + 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) <gmicol@cisco.com> + +# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) + +- name: Test that we have an ACI APIC host, ACI username and ACI password + 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) <gmicol@cisco.com> + +# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) + +- name: Test that we have an ACI APIC host, ACI username and ACI password + 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) <cizhao@cisco.com> +# Copyright: (c) 2024, Samita Bhattacharjee (@samitab) <samitab@cisco.com> # GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) - name: Test that we have an ACI APIC host, ACI username and ACI password - fail: + 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) <gmicol@cisco.com> + +# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) + +- name: Test that we have an ACI APIC host, ACI username and ACI password + 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) <gmicol@cisco.com> + +# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) + +- name: Test that we have an ACI APIC host, ACI username and ACI password + 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) <samitab@cisco.com> # GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) - name: Test that we have an ACI APIC host, ACI username and ACI password - fail: + 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) <akinross@cisco.com> # GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) - name: Test that we have an ACI APIC host, ACI username and ACI password - fail: + 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' @@ -245,7 +245,7 @@ when: version.current.0.topSystem.attributes.version is version('5.2', '<') - name: Assertions check for query all ESGs of an App Profile (>=v5.2) - assert: + 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 <akinross@cisco.com> +# +# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) + +- name: Test that we have an ACI APIC host, ACI username and ACI password + ansible.builtin.fail: + msg: 'Please define the following variables: aci_hostname, aci_username and aci_password.' + when: aci_hostname is not defined or aci_username is not defined or aci_password is not defined + +- name: Set vars + ansible.builtin.set_fact: + aci_info: &aci_info + host: "{{ aci_hostname }}" + username: "{{ aci_username }}" + password: "{{ aci_password }}" + validate_certs: '{{ aci_validate_certs | default(false) }}' + use_ssl: '{{ aci_use_ssl | default(true) }}' + use_proxy: '{{ aci_use_proxy | default(true) }}' + output_level: '{{ aci_output_level | default("info") }}' + aci_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) <gmicol@cisco.com> + +# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) + +- name: Test that we have an ACI APIC host, ACI username and ACI password + 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) <gmicol@cisco.com> + +# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) + +- name: Test that we have an ACI APIC host, ACI username and ACI password + 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) <gmicol@cisco.com> + +# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) + +- name: Test that we have an ACI APIC host, ACI username and ACI password + 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) <gmicol@cisco.com> + +# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) + +- name: Test that we have an ACI APIC host, ACI username and ACI password + 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) <gmicol@cisco.com> + +# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) + +- name: Test that we have an ACI APIC host, ACI username and ACI password + 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) <gmicol@cisco.com> +# Copyright: (c) 2023, Akini Ross (@akinross) <akinross@cisco.com> # GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) - name: Test that we have an ACI APIC host, ACI username and ACI password - fail: + 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) <gmicol@cisco.com> + +# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) + +- name: Test that we have an ACI APIC host, ACI username and ACI password + 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) <gmicol@cisco.com> + +# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) + +- name: Test that we have an ACI APIC host, ACI username and ACI password + 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) <akinross@cisco.com> # GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) - name: Test that we have an ACI APIC host, ACI username and ACI password - fail: + 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) <gmicol@cisco.com> + # GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) # SET VARS - name: Set vars - set_fact: + 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) <akinross@cisco.com> # GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) - name: Test that we have an ACI APIC host, ACI username and ACI password - fail: + 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) <akinross@cisco.com> # GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) - name: Test that we have an ACI APIC host, ACI username and ACI password - fail: + 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) <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: 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) <gmicol@cisco.com> + +# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) + +- name: Test that we have an ACI APIC host, ACI username and ACI password + 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) <gmicol@cisco.com> + +# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) + +- name: Test that we have an ACI APIC host, ACI username and ACI password + 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) <gmicol@cisco.com> + +# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) + +- name: Test that we have an ACI APIC host, ACI username and ACI password + 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) <gmicol@cisco.com> + +# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) + +- name: Test that we have an ACI APIC host, ACI username and ACI password + 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) <gmicol@cisco.com> + +# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) + +- name: Test that we have an ACI APIC host, ACI username and ACI password + 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) <gmicol@cisco.com> + +# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) + +- name: Test that we have an ACI APIC host, ACI username and ACI password + 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) <gmicol@cisco.com> + +# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) + +- name: Test that we have an ACI APIC host, ACI username and ACI password + 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) <gmicol@cisco.com> + +# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) + +- name: Test that we have an ACI APIC host, ACI username and ACI password + 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) <gmicol@cisco.com> + +# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) + +- name: Test that we have an ACI APIC host, ACI username and ACI password + 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) <gmicol@cisco.com> + +# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) + +- name: Test that we have an ACI APIC host, ACI username and ACI password + 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 @@ +<tagTag value="bar"/>
\ 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 @@ +<fvTenant descr="ans_test_create tenant created successfully" dn="uni/tn-ans_test_create" name="ans_test_create" status="" annotation="test:optionincontent"/>
\ 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 @@ +<fvTenant name="ans_test_create" descr="Ansible test tenant xml"> + <fvCtx name="VRF1"/> + <fvAp name="Application1"> + <fvAEPg name="WebTier" annotation="test:inchild"/> + </fvAp> +</fvTenant>
\ 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: + <fvTenant name="ansible_test_annotation"/> + 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: + <fvTenant name="ansible_test" descr="Ansible test tenant"/> + 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: + <fvTenant name="ansible_test" descr="Ansible test tenant" 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.xml + method: post + annotation: test:inoption + content: + <fvTenant name="ansible_test" descr="Ansible test tenant" 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.xml + method: post + annotation: test:inoption + content: + <tagTag 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.xml + method: post + annotation: test:inoption + content: + <fvTenant name="ansible_test" descr="Ansible test tenant"> + <fvCtx name="VRF1"/> + <fvAp name="Application1"> + <fvAEPg name="WebTier" annotation="test:inchild"/> + </fvAp> + </fvTenant> + 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) <dag@wieers.com> # Copyright: (c) 2020, Lionel Hercot (@lhercot) <lhercot@cisco.com> +# Copyright: (c) 2024, Samita Bhattacharjee (@samiib) <samitab@cisco.com> # GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) - name: Test that we have an ACI APIC host, ACI username and ACI password - fail: + 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) <tcragg@cisco.com> # Copyright: (c) 2023, Gaspard Micol (@gmicol) <gmicol@cisco.com> # GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) - name: Test that we have an ACI APIC host, ACI username and ACI password - fail: + 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) <anvjain@cisco.com> +# Copyright: (c) 2023, Akini Ross (@akinross) <akinross@cisco.com> # GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) # 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") |