From e5baef7f5dc735f6a05d8ca18dcb9b5335575e31 Mon Sep 17 00:00:00 2001 From: David Neilan <125286969+dneilan-intel@users.noreply.github.com> Date: Thu, 18 Apr 2024 18:17:40 +0100 Subject: [PATCH] [minor_change] Add aci_system_connectivity_preference module (#601) --- .../aci_system_connectivity_preference.py | 264 ++++++++++++++++++ .../aliases | 2 + .../tasks/main.yml | 91 ++++++ 3 files changed, 357 insertions(+) create mode 100644 plugins/modules/aci_system_connectivity_preference.py create mode 100644 tests/integration/targets/aci_system_connectivity_preference/aliases create mode 100644 tests/integration/targets/aci_system_connectivity_preference/tasks/main.yml diff --git a/plugins/modules/aci_system_connectivity_preference.py b/plugins/modules/aci_system_connectivity_preference.py new file mode 100644 index 000000000..2a38d3589 --- /dev/null +++ b/plugins/modules/aci_system_connectivity_preference.py @@ -0,0 +1,264 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- + +# Copyright: (c) 2024, David Neilan (@dneilan-intel) +# GNU General Public License 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_system_connectivity_preference +short_description: APIC Connectivity Preferences (mgmt:ConnectivityPrefs) +description: +- Manages APIC Connectivity Preferences on Cisco ACI fabrics. +options: + interface_preference: + description: + - Interface to use for external connection. + type: str + choices: [ inband, ooband ] + aliases: [ interface_pref, int_pref, external_connection ] + + state: + description: + - Use C(present) for updating. + - Use C(query) for listing an object. + type: str + choices: [ 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(mgmt:ConnectivityPrefs). + link: https://developer.cisco.com/docs/apic-mim-ref/ + +author: +- David Neilan (@dneilan-intel) +""" + +EXAMPLES = r""" +- name: Configure Out-of-band Connectivity Preference + cisco.aci.aci_system_connectivity_preference: + host: apic + username: admin + password: SomeSecretPassword + interface_preference: ooband + state: present + delegate_to: localhost + +- name: Configure In-band Connectivity Preference + cisco.aci.aci_system_connectivity_preference: + host: apic + username: admin + password: SomeSecretPassword + interface_preference: inband + state: present + delegate_to: localhost + +- name: Query Management Connectivity Preference + cisco.aci.aci_system_connectivity_preference: + host: apic + username: admin + password: SomeSecretPassword + state: query + delegate_to: localhost +""" + +RETURN = r""" +current: + description: The existing configuration from the APIC after the module has finished + returned: success + type: list + sample: + [ + { + "mgmtConnectivityPrefs": { + "attributes": { + "annotation": "", + "childAction": "", + "descr": "", + "dn": "uni/fabric/connectivityPrefs", + "extMngdBy": "", + "interfacePref": "inband", + "lcOwn": "local", + "modTs": "2023-11-14T16:25:32.629+00:00", + "name": "default", + "nameAlias": "", + "ownerKey": "", + "ownerTag": "", + "status": "", + "uid": "0" + } + } + } + ] +error: + description: The error information as returned from the APIC + returned: failure + type: dict + sample: + { + "code": "120", + "text": "unknown property value foo, name interfacePref, class mgmtConnectivityPrefs [(Dn0)] Dn0=, " + } +raw: + description: The raw output returned by the APIC REST API (xml or json) + returned: parse error + type: str + sample: + { + "totalCount": "1", + "imdata": [ + { + "error": { + "attributes": { + "code": "120", + "text": "unknown property value foo, name interfacePref, class mgmtConnectivityPrefs [(Dn0)] Dn0=, " + } + } + } + ] + } +sent: + description: The actual/minimal configuration pushed to the APIC + returned: info + type: list + sample: + { + "mgmtConnectivityPrefs": { + "attributes": { + "interfacePref": "inband" + } + } + } +previous: + description: The original configuration from the APIC before the module has started + returned: info + type: list + sample: + [ + { + "mgmtConnectivityPrefs": { + "attributes": { + "annotation": "", + "descr": "", + "dn": "uni/fabric/connectivityPrefs", + "interfacePref": "ooband", + "name": "default", + "nameAlias": "", + "ownerKey": "", + "ownerTag": "" + } + } + } + ] +proposed: + description: The assembled configuration from the user-provided parameters + returned: info + type: dict + sample: + { + "mgmtConnectivityPrefs": { + "attributes": { + "interfacePref": "inband" + } + } + } +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_preference=dict( + type="str", + choices=["ooband", "inband"], + aliases=["interface_pref", "int_pref", "external_connection"], + ), + state=dict(type="str", default="present", choices=["present", "query"]), + ) + + module = AnsibleModule( + argument_spec=argument_spec, + supports_check_mode=True, + required_if=[ + ["state", "present", ["interface_preference"]], + ], + ) + aci = ACIModule(module) + + interface_preference = module.params.get("interface_preference") + state = module.params.get("state") + + aci.construct_url( + root_class=dict( + aci_class="mgmtConnectivityPrefs", + aci_rn="fabric/connectivityPrefs", + ), + ) + aci.get_existing() + + if state == "present": + aci.payload( + aci_class="mgmtConnectivityPrefs", + class_config=dict(interfacePref=interface_preference), + ) + + aci.get_diff(aci_class="mgmtConnectivityPrefs") + + aci.post_config() + + aci.exit_json() + + +if __name__ == "__main__": + main() diff --git a/tests/integration/targets/aci_system_connectivity_preference/aliases b/tests/integration/targets/aci_system_connectivity_preference/aliases new file mode 100644 index 000000000..209b793f9 --- /dev/null +++ b/tests/integration/targets/aci_system_connectivity_preference/aliases @@ -0,0 +1,2 @@ +# No ACI simulator yet, so not enabled +# unsupported diff --git a/tests/integration/targets/aci_system_connectivity_preference/tasks/main.yml b/tests/integration/targets/aci_system_connectivity_preference/tasks/main.yml new file mode 100644 index 000000000..bf857f27d --- /dev/null +++ b/tests/integration/targets/aci_system_connectivity_preference/tasks/main.yml @@ -0,0 +1,91 @@ +# Test code for the ACI modules +# Copyright: (c) 2024, David Neilan (@dneilan-intel) + +# GNU General Public License v3.0+ (see LICENSE 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") }}' + +# CLEANUP ENVIRONMENT +- name: Initialize system connectivity preference + cisco.aci.aci_system_connectivity_preference: &aci_system_connectivity_preference_initial + <<: *aci_info + interface_preference: inband + +# UPDATE SYSTEM CONNECTIVITY PREFERENCE +- name: Update system connectivity preference (check mode) + cisco.aci.aci_system_connectivity_preference: &aci_connectivity_preference + <<: *aci_info + interface_preference: ooband + check_mode: true + register: cm_update_connectivity_preference + +- name: Update system connectivity preference + cisco.aci.aci_system_connectivity_preference: + <<: *aci_connectivity_preference + register: nm_update_connectivity_preference + +- name: Update system connectivity preference again + cisco.aci.aci_system_connectivity_preference: + <<: *aci_connectivity_preference + register: nm_update_connectivity_preference_again + +- name: Verify system connectivity preference + ansible.builtin.assert: + that: + - cm_update_connectivity_preference is changed + - cm_update_connectivity_preference.proposed.mgmtConnectivityPrefs.attributes.interfacePref == "ooband" + - cm_update_connectivity_preference.current.0.mgmtConnectivityPrefs.attributes.interfacePref == "inband" + - nm_update_connectivity_preference is changed + - nm_update_connectivity_preference.current.0.mgmtConnectivityPrefs.attributes.interfacePref == "ooband" + - nm_update_connectivity_preference.previous.0.mgmtConnectivityPrefs.attributes.interfacePref == "inband" + - nm_update_connectivity_preference_again is not changed + - nm_update_connectivity_preference_again.current.0.mgmtConnectivityPrefs.attributes.interfacePref == "ooband" + - nm_update_connectivity_preference_again.previous.0.mgmtConnectivityPrefs.attributes.interfacePref == "ooband" + +# QUERY SYSTEM CONNECTIVITY PREFERENCE +- name: Query system connectivity preference + cisco.aci.aci_system_connectivity_preference: + <<: *aci_connectivity_preference + state: query + register: query + +- name: Verify system connectivity preference query + ansible.builtin.assert: + that: + - query is not changed + - query.current.0.mgmtConnectivityPrefs.attributes.interfacePref == "ooband" + +# ERROR SYSTEM CONNECTIVITY PREFERENCE +- name: Update system connectivity preference (error) + cisco.aci.aci_system_connectivity_preference: + <<: *aci_info + interface_preference: foo + ignore_errors: true + register: err_update_system_connectivity_preference + +- name: Verify system connectivity preference error + ansible.builtin.assert: + that: + - err_update_system_connectivity_preference is failed + - err_update_system_connectivity_preference.msg == expected_failure_message + vars: + expected_failure_message: "value of interface_preference must be one of: ooband, inband, got: foo" + +# CLEANUP ENVIRONMENT +- name: Revert system connectivity preference + cisco.aci.aci_system_connectivity_preference: + <<: *aci_system_connectivity_preference_initial