From 46c7f382d331539a3e16a2ae6cddd96b02302a36 Mon Sep 17 00:00:00 2001 From: Faiz Mohammad Date: Thu, 24 Oct 2024 19:33:47 +0530 Subject: [PATCH 1/7] [minor change] New module for out-of-band contract creation --- plugins/modules/aci_oob_contract.py | 282 ++++++++++++++++++ .../targets/aci_oob_contract/aliases | 2 + .../targets/aci_oob_contract/tasks/main.yml | 142 +++++++++ 3 files changed, 426 insertions(+) create mode 100644 plugins/modules/aci_oob_contract.py create mode 100644 tests/integration/targets/aci_oob_contract/aliases create mode 100644 tests/integration/targets/aci_oob_contract/tasks/main.yml diff --git a/plugins/modules/aci_oob_contract.py b/plugins/modules/aci_oob_contract.py new file mode 100644 index 000000000..52df3a157 --- /dev/null +++ b/plugins/modules/aci_oob_contract.py @@ -0,0 +1,282 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- + +# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) + +from __future__ import absolute_import, division, print_function + +__metaclass__ = type + +ANSIBLE_METADATA = {"metadata_version": "1.1", "status": ["preview"], "supported_by": "certified"} + +DOCUMENTATION = r""" +--- +module: aci_oob_contract +short_description: Manage out-of-band contract resources (vz:OOBBrCP) +description: +- Manage out-of-band Contract resources on Cisco ACI fabrics. +options: + contract: + description: + - The name of the contract. + type: str + aliases: [ contract_name, name ] + description: + description: + - Description for the contract. + type: str + aliases: [ descr ] + scope: + description: + - The scope of a service contract. + - The APIC defaults to C(context) when unset during creation. + type: str + choices: [ application-profile, context, global, tenant ] + priority: + description: + - The desired QoS class to be used. + - The APIC defaults to C(unspecified) when unset during creation. + type: str + choices: [ level1, level2, level3, unspecified ] + 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(vz:BrCP). + link: https://developer.cisco.com/docs/apic-mim-ref/ +author: +- Faiz Mohammad (@faizmoh) +""" + +EXAMPLES = r""" +- name: Add a new contract + cisco.aci.aci_oob_contract: + host: apic + username: admin + password: SomeSecretPassword + contract: web_to_db + description: Communication between web-servers and database + scope: global + state: present + delegate_to: localhost + +- name: Remove an existing contract + cisco.aci.aci_contract: + host: apic + username: admin + password: SomeSecretPassword + contract: web_to_db + state: absent + delegate_to: localhost + +- name: Query a specific contract + cisco.aci.aci_contract: + host: apic + username: admin + password: SomeSecretPassword + contract: web_to_db + state: query + delegate_to: localhost + register: query_result + +- name: Query all contracts + cisco.aci.aci_contract: + host: apic + username: admin + password: SomeSecretPassword + state: query + delegate_to: localhost + register: query_result +""" + +RETURN = r""" +current: + description: The existing configuration from the APIC after the module has finished + returned: success + type: list + sample: + [ + { + "fvTenant": { + "attributes": { + "descr": "Production environment", + "dn": "uni/tn-production", + "name": "production", + "nameAlias": "", + "ownerKey": "", + "ownerTag": "" + } + } + } + ] +error: + description: The error information as returned from the APIC + returned: failure + type: dict + sample: + { + "code": "122", + "text": "unknown managed object class foo" + } +raw: + description: The raw output returned by the APIC REST API (xml or json) + returned: parse error + type: str + sample: '' +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( + contract=dict(type="str", aliases=["contract_name", "name"]), # Not required for querying all objects + description=dict(type="str", aliases=["descr"]), + scope=dict(type="str", choices=["application-profile", "context", "global", "tenant"]), + priority=dict(type="str", choices=["level1", "level2", "level3", "unspecified"]), # No default provided on purpose + state=dict(type="str", default="present", choices=["absent", "present", "query"]), + name_alias=dict(type="str"), + ) + + module = AnsibleModule( + argument_spec=argument_spec, + supports_check_mode=True, + required_if=[ + ["state", "absent", ["contract"]], + ["state", "present", ["contract"]], + ] + ) + + contract = module.params.get("contract") + description = module.params.get("description") + scope = module.params.get("scope") + priority = module.params.get("priority") + state = module.params.get("state") + tenant = "mgmt" # hard coding tenant to 'mgmt' + 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="vzOOBBrCP", + aci_rn="oobbrc-{0}".format(contract), + module_object=contract, + target_filter={"name": contract}, + ), + ) + + aci.get_existing() + + if state == "present": + aci.payload( + aci_class="vzOOBBrCP", + class_config=dict( + name=contract, + descr=description, + scope=scope, + prio=priority, + nameAlias=name_alias, + ), + ) + + aci.get_diff(aci_class="vzOOBBrCP") + + aci.post_config() + + elif state == "absent": + aci.delete_config() + + aci.exit_json() + + +if __name__ == "__main__": + main() diff --git a/tests/integration/targets/aci_oob_contract/aliases b/tests/integration/targets/aci_oob_contract/aliases new file mode 100644 index 000000000..209b793f9 --- /dev/null +++ b/tests/integration/targets/aci_oob_contract/aliases @@ -0,0 +1,2 @@ +# No ACI simulator yet, so not enabled +# unsupported diff --git a/tests/integration/targets/aci_oob_contract/tasks/main.yml b/tests/integration/targets/aci_oob_contract/tasks/main.yml new file mode 100644 index 000000000..0397b42cc --- /dev/null +++ b/tests/integration/targets/aci_oob_contract/tasks/main.yml @@ -0,0 +1,142 @@ +# Test code for the ACI modules +# Copyright: (c) 2017, Jacob McGill (@jmcgill298) + +# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) + +- name: Test that we have an ACI APIC host, ACI username and ACI password + ansible.builtin.fail: + msg: 'Please define the following variables: aci_hostname, aci_username and aci_password.' + when: aci_hostname is not defined or aci_username is not defined or aci_password is not defined + +- name: ensure tenant exists for tests to kick off + cisco.aci.aci_tenant: &aci_tenant_present + host: "{{ aci_hostname }}" + username: "{{ aci_username }}" + password: "{{ aci_password }}" + validate_certs: '{{ aci_validate_certs | default(false) }}' + use_ssl: '{{ aci_use_ssl | default(true) }}' + use_proxy: '{{ aci_use_proxy | default(true) }}' + output_level: debug + tenant: mgmt + state: present + register: tenant_present + +- name: create contract - check mode works + cisco.aci.aci_oob_contract: &aci_oob_contract_present + <<: *aci_tenant_present + tenant: "{{ fakevar | default(omit) }}" + contract: anstest + description: Ansible Test + check_mode: true + register: present_check_mode + +- name: create contract - creation works + cisco.aci.aci_oob_contract: + <<: *aci_oob_contract_present + register: contract_present + +- name: create contract - idempotency works + cisco.aci.aci_oob_contract: + <<: *aci_oob_contract_present + register: present_idempotent + +- name: update contract - update works + cisco.aci.aci_oob_contract: + <<: *aci_oob_contract_present + scope: application-profile + register: present_update + +- name: create contract - used for query + cisco.aci.aci_oob_contract: + <<: *aci_oob_contract_present + contract: anstest2 + +- name: missing param - failure message works + cisco.aci.aci_oob_contract: + <<: *aci_tenant_present + tenant: "{{ fakevar | default(omit) }}" + ignore_errors: true + register: present_missing_param + +- name: present assertions + ansible.builtin.assert: + that: + - present_check_mode is changed + - present_check_mode.previous == [] + - present_check_mode.sent.vzBrCP.attributes.name == 'anstest' + - present_check_mode.sent.vzBrCP.attributes.descr == 'Ansible Test' + - contract_present is changed + - contract_present.current.0.vzBrCP.attributes.annotation == 'orchestrator:ansible' + - contract_present.sent == present_check_mode.sent + - present_idempotent is not changed + - present_update is changed + - present_update.sent != present_update.proposed + - present_update.sent.vzBrCP.attributes.scope == "application-profile" + - present_missing_param is failed + - 'present_missing_param.msg == "state is present but all of the following are missing: contract"' + +- name: query contract + cisco.aci.aci_oob_contract: &aci_oob_contract_query + <<: *aci_oob_contract_present + state: query + register: query_contract + +- name: query all + cisco.aci.aci_oob_contract: + <<: *aci_oob_contract_query + contract: "{{ fakevar | default(omit) }}" + register: query_tenant + +- name: query assertions + ansible.builtin.assert: + that: + - query_contract is not changed + - query_contract.current | length == 1 + - '"tn-ansible_test/brc-anstest.json" in query_contract.url' + - query_tenant is not changed + - query_tenant.current | length == 1 + - query_tenant.current.0.fvTenant.children | length > 1 + - '"rsp-subtree-class=vzBrCP" in query_tenant.filter_string' + - '"tn-ansible_test.json" in query_tenant.url' + + +- name: delete contract - check mode works + cisco.aci.aci_oob_contract: &aci_oob_contract_absent + <<: *aci_oob_contract_present + state: absent + check_mode: true + register: absent_check_mode + +- name: delete contract - deletion works + cisco.aci.aci_oob_contract: + <<: *aci_oob_contract_absent + register: contract_absent + +- name: delete contract - idempotency works + cisco.aci.aci_oob_contract: + <<: *aci_oob_contract_absent + register: absent_idempotent + +- name: delete contract - cleanup second contract + cisco.aci.aci_oob_contract: + <<: *aci_oob_contract_absent + contract: anstest2 + +- name: missing param - fail message works + cisco.aci.aci_oob_contract: + <<: *aci_oob_contract_absent + contract: "{{ fakevar | default(omit) }}" + ignore_errors: true + register: absent_missing_param + +- name: absent assertions + ansible.builtin.assert: + that: + - absent_check_mode is changed + - absent_check_mode.previous != [] + - contract_absent is changed + - contract_absent.previous == absent_check_mode.previous + - absent_idempotent is not changed + - absent_idempotent.previous == [] + - absent_missing_param is failed + - 'absent_missing_param.msg == "state is absent but all of the following are missing: contract"' From 56b27fed5e8ec3b3b787cca24f2eb78f3baa3419 Mon Sep 17 00:00:00 2001 From: Faiz Mohammad Date: Thu, 31 Oct 2024 13:11:02 +0530 Subject: [PATCH 2/7] rectified tests in oob_contract tests file --- .../targets/aci_oob_contract/tasks/main.yml | 274 +++++++++--------- 1 file changed, 143 insertions(+), 131 deletions(-) diff --git a/tests/integration/targets/aci_oob_contract/tasks/main.yml b/tests/integration/targets/aci_oob_contract/tasks/main.yml index 0397b42cc..57c71db9d 100644 --- a/tests/integration/targets/aci_oob_contract/tasks/main.yml +++ b/tests/integration/targets/aci_oob_contract/tasks/main.yml @@ -8,135 +8,147 @@ msg: 'Please define the following variables: aci_hostname, aci_username and aci_password.' when: aci_hostname is not defined or aci_username is not defined or aci_password is not defined -- name: ensure tenant exists for tests to kick off - cisco.aci.aci_tenant: &aci_tenant_present - host: "{{ aci_hostname }}" - username: "{{ aci_username }}" - password: "{{ aci_password }}" - validate_certs: '{{ aci_validate_certs | default(false) }}' - use_ssl: '{{ aci_use_ssl | default(true) }}' - use_proxy: '{{ aci_use_proxy | default(true) }}' - output_level: debug - tenant: mgmt - state: present - register: tenant_present - -- name: create contract - check mode works - cisco.aci.aci_oob_contract: &aci_oob_contract_present - <<: *aci_tenant_present - tenant: "{{ fakevar | default(omit) }}" - contract: anstest - description: Ansible Test - check_mode: true - register: present_check_mode - -- name: create contract - creation works - cisco.aci.aci_oob_contract: - <<: *aci_oob_contract_present - register: contract_present - -- name: create contract - idempotency works - cisco.aci.aci_oob_contract: - <<: *aci_oob_contract_present - register: present_idempotent - -- name: update contract - update works - cisco.aci.aci_oob_contract: - <<: *aci_oob_contract_present - scope: application-profile - register: present_update - -- name: create contract - used for query - cisco.aci.aci_oob_contract: - <<: *aci_oob_contract_present - contract: anstest2 - -- name: missing param - failure message works - cisco.aci.aci_oob_contract: - <<: *aci_tenant_present - tenant: "{{ fakevar | default(omit) }}" - ignore_errors: true - register: present_missing_param - -- name: present assertions - ansible.builtin.assert: - that: - - present_check_mode is changed - - present_check_mode.previous == [] - - present_check_mode.sent.vzBrCP.attributes.name == 'anstest' - - present_check_mode.sent.vzBrCP.attributes.descr == 'Ansible Test' - - contract_present is changed - - contract_present.current.0.vzBrCP.attributes.annotation == 'orchestrator:ansible' - - contract_present.sent == present_check_mode.sent - - present_idempotent is not changed - - present_update is changed - - present_update.sent != present_update.proposed - - present_update.sent.vzBrCP.attributes.scope == "application-profile" - - present_missing_param is failed - - 'present_missing_param.msg == "state is present but all of the following are missing: contract"' - -- name: query contract - cisco.aci.aci_oob_contract: &aci_oob_contract_query - <<: *aci_oob_contract_present +# 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 + cisco.aci.aci_system: + <<: *aci_info + id: 1 state: query - register: query_contract - -- name: query all - cisco.aci.aci_oob_contract: - <<: *aci_oob_contract_query - contract: "{{ fakevar | default(omit) }}" - register: query_tenant - -- name: query assertions - ansible.builtin.assert: - that: - - query_contract is not changed - - query_contract.current | length == 1 - - '"tn-ansible_test/brc-anstest.json" in query_contract.url' - - query_tenant is not changed - - query_tenant.current | length == 1 - - query_tenant.current.0.fvTenant.children | length > 1 - - '"rsp-subtree-class=vzBrCP" in query_tenant.filter_string' - - '"tn-ansible_test.json" in query_tenant.url' - - -- name: delete contract - check mode works - cisco.aci.aci_oob_contract: &aci_oob_contract_absent - <<: *aci_oob_contract_present - state: absent - check_mode: true - register: absent_check_mode - -- name: delete contract - deletion works - cisco.aci.aci_oob_contract: - <<: *aci_oob_contract_absent - register: contract_absent - -- name: delete contract - idempotency works - cisco.aci.aci_oob_contract: - <<: *aci_oob_contract_absent - register: absent_idempotent - -- name: delete contract - cleanup second contract - cisco.aci.aci_oob_contract: - <<: *aci_oob_contract_absent - contract: anstest2 - -- name: missing param - fail message works - cisco.aci.aci_oob_contract: - <<: *aci_oob_contract_absent - contract: "{{ fakevar | default(omit) }}" - ignore_errors: true - register: absent_missing_param - -- name: absent assertions - ansible.builtin.assert: - that: - - absent_check_mode is changed - - absent_check_mode.previous != [] - - contract_absent is changed - - contract_absent.previous == absent_check_mode.previous - - absent_idempotent is not changed - - absent_idempotent.previous == [] - - absent_missing_param is failed - - 'absent_missing_param.msg == "state is absent but all of the following are missing: contract"' + 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 ACI v5+ and non-cloud sites + when: + - version.current.0.topSystem.attributes.version is version('5', '>=') + - query_cloud.current == [] # This condition will execute only non-cloud sites + block: # block specifies execution of tasks within, based on conditions + - name: create contract - check mode works + cisco.aci.aci_oob_contract: &aci_oob_contract_present + <<: *aci_info + contract: anstest + description: Ansible Test + check_mode: true + register: present_check_mode + + - name: create contract - creation works + cisco.aci.aci_oob_contract: + <<: *aci_oob_contract_present + register: contract_present + + - name: create contract - idempotency works + cisco.aci.aci_oob_contract: + <<: *aci_oob_contract_present + register: present_idempotent + + - name: update contract - update works + cisco.aci.aci_oob_contract: + <<: *aci_oob_contract_present + scope: application-profile + register: present_update + + - name: create contract - used for query + cisco.aci.aci_oob_contract: + <<: *aci_oob_contract_present + contract: anstest2 + + - name: missing param - failure message works + cisco.aci.aci_oob_contract: + <<: *aci_info + ignore_errors: true + register: present_missing_param + + - name: present assertions + ansible.builtin.assert: + that: + - present_check_mode is changed + - present_check_mode.previous == [] + - present_check_mode.sent.vzOOBBrCP.attributes.name == 'anstest' + - present_check_mode.sent.vzOOBBrCP.attributes.descr == 'Ansible Test' + - contract_present is changed + - contract_present.current.0.vzOOBBrCP.attributes.annotation == 'orchestrator:ansible' + - contract_present.sent == present_check_mode.sent + - present_idempotent is not changed + - present_update is changed + - present_update.sent != present_update.proposed + - present_update.sent.vzOOBBrCP.attributes.scope == "application-profile" + - present_missing_param is failed + - 'present_missing_param.msg == "state is present but all of the following are missing: contract"' + + - name: query contract + cisco.aci.aci_oob_contract: &aci_oob_contract_query + <<: *aci_oob_contract_present + state: query + register: query_contract + + - name: query all + cisco.aci.aci_oob_contract: + <<: *aci_oob_contract_query + contract: "{{ fakevar | default(omit) }}" + register: query_tenant + + - name: query assertions + ansible.builtin.assert: + that: + - query_contract is not changed + - query_contract.current | length == 1 + - '"tn-mgmt/oobbrc-anstest.json" in query_contract.url' + - query_tenant is not changed + - query_tenant.current | length == 1 + - query_tenant.current.0.fvTenant.children | length > 1 + - '"rsp-subtree-class=vzOOBBrCP" in query_tenant.filter_string' + - '"tn-mgmt.json" in query_tenant.url' + + + - name: delete contract - check mode works + cisco.aci.aci_oob_contract: &aci_oob_contract_absent + <<: *aci_oob_contract_present + state: absent + check_mode: true + register: absent_check_mode + + - name: delete contract - deletion works + cisco.aci.aci_oob_contract: + <<: *aci_oob_contract_absent + register: contract_absent + + - name: delete contract - idempotency works + cisco.aci.aci_oob_contract: + <<: *aci_oob_contract_absent + register: absent_idempotent + + - name: delete contract - cleanup second contract + cisco.aci.aci_oob_contract: + <<: *aci_oob_contract_absent + contract: anstest2 + + - name: missing param - fail message works + cisco.aci.aci_oob_contract: + <<: *aci_oob_contract_absent + contract: "{{ fakevar | default(omit) }}" + ignore_errors: true + register: absent_missing_param + + - name: absent assertions + ansible.builtin.assert: + that: + - absent_check_mode is changed + - absent_check_mode.previous != [] + - contract_absent is changed + - contract_absent.previous == absent_check_mode.previous + - absent_idempotent is not changed + - absent_idempotent.previous == [] + - absent_missing_param is failed + - 'absent_missing_param.msg == "state is absent but all of the following are missing: contract"' From ee8f461d015825d81584419f06c051212e2e2ec6 Mon Sep 17 00:00:00 2001 From: Ziaf007 Date: Sat, 14 Dec 2024 14:34:06 +0530 Subject: [PATCH 3/7] fixed test.yml for oob_contract. Only 1 issue remains now --- tests/integration/targets/aci_oob_contract/tasks/main.yml | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/tests/integration/targets/aci_oob_contract/tasks/main.yml b/tests/integration/targets/aci_oob_contract/tasks/main.yml index 57c71db9d..85e70772b 100644 --- a/tests/integration/targets/aci_oob_contract/tasks/main.yml +++ b/tests/integration/targets/aci_oob_contract/tasks/main.yml @@ -35,11 +35,19 @@ - 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 + - name: Ensure Contract doesn't exist + cisco.aci.aci_oob_contract: + <<: *aci_info + contract: anstest + state: absent + description: Ansible Test + - name: create contract - check mode works cisco.aci.aci_oob_contract: &aci_oob_contract_present <<: *aci_info contract: anstest description: Ansible Test + state: present check_mode: true register: present_check_mode From ba8f7b00ff15e81eb038a796ce3e4ec4f30fd417 Mon Sep 17 00:00:00 2001 From: Ziaf007 Date: Sun, 15 Dec 2024 18:19:14 +0530 Subject: [PATCH 4/7] fixed all issues in test.yml for aci_oob_contract. Module ready --- tests/integration/targets/aci_oob_contract/tasks/main.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/integration/targets/aci_oob_contract/tasks/main.yml b/tests/integration/targets/aci_oob_contract/tasks/main.yml index 85e70772b..be1cc30b0 100644 --- a/tests/integration/targets/aci_oob_contract/tasks/main.yml +++ b/tests/integration/targets/aci_oob_contract/tasks/main.yml @@ -18,7 +18,7 @@ validate_certs: '{{ aci_validate_certs | default(false) }}' use_ssl: '{{ aci_use_ssl | default(true) }}' use_proxy: '{{ aci_use_proxy | default(true) }}' - output_level: '{{ aci_output_level | default("info") }}' + output_level: '{{ aci_output_level | default("debug") }}' - name: Query system information cisco.aci.aci_system: From 9cddf5c969d378fb00497502e700c54aaf91831f Mon Sep 17 00:00:00 2001 From: Ziaf007 Date: Mon, 16 Dec 2024 19:18:48 +0530 Subject: [PATCH 5/7] fixed formatting via black. --- plugins/modules/aci_oob_contract.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/plugins/modules/aci_oob_contract.py b/plugins/modules/aci_oob_contract.py index 52df3a157..af3c85475 100644 --- a/plugins/modules/aci_oob_contract.py +++ b/plugins/modules/aci_oob_contract.py @@ -227,7 +227,7 @@ def main(): required_if=[ ["state", "absent", ["contract"]], ["state", "present", ["contract"]], - ] + ], ) contract = module.params.get("contract") @@ -235,7 +235,7 @@ def main(): scope = module.params.get("scope") priority = module.params.get("priority") state = module.params.get("state") - tenant = "mgmt" # hard coding tenant to 'mgmt' + tenant = "mgmt" # hard coding tenant to 'mgmt' name_alias = module.params.get("name_alias") aci = ACIModule(module) From 34bbca58ee9bdcacbfe2530de17f260b22aa431f Mon Sep 17 00:00:00 2001 From: Ziaf007 Date: Fri, 20 Dec 2024 22:50:34 +0530 Subject: [PATCH 6/7] changes based on the comments on the PR. --- plugins/modules/aci_oob_contract.py | 32 ++++++------ .../targets/aci_oob_contract/tasks/main.yml | 49 ++++++++++++------- 2 files changed, 47 insertions(+), 34 deletions(-) diff --git a/plugins/modules/aci_oob_contract.py b/plugins/modules/aci_oob_contract.py index af3c85475..e0e886d9d 100644 --- a/plugins/modules/aci_oob_contract.py +++ b/plugins/modules/aci_oob_contract.py @@ -1,5 +1,6 @@ #!/usr/bin/python # -*- coding: utf-8 -*- +# Copyright: (c) 2024, Faiz Mohammad (@Ziaf007) # GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) @@ -12,7 +13,7 @@ DOCUMENTATION = r""" --- module: aci_oob_contract -short_description: Manage out-of-band contract resources (vz:OOBBrCP) +short_description: Manage Out-of-Band contract resources (vz:OOBBrCP) description: - Manage out-of-band Contract resources on Cisco ACI fabrics. options: @@ -23,18 +24,18 @@ aliases: [ contract_name, name ] description: description: - - Description for the contract. + - Description for the OOB contract. type: str aliases: [ descr ] scope: description: - - The scope of a service contract. + - The scope of a the OOB contract. - The APIC defaults to C(context) when unset during creation. type: str choices: [ application-profile, context, global, tenant ] priority: description: - - The desired QoS class to be used. + - The desired Quality of Service (QoS) class to be used. - The APIC defaults to C(unspecified) when unset during creation. type: str choices: [ level1, level2, level3, unspecified ] @@ -52,7 +53,7 @@ seealso: - name: APIC Management Information Model reference - description: More information about the internal APIC class B(vz:BrCP). + description: More information about the internal APIC class B(vz:OOBBrCP). link: https://developer.cisco.com/docs/apic-mim-ref/ author: - Faiz Mohammad (@faizmoh) @@ -66,37 +67,38 @@ password: SomeSecretPassword contract: web_to_db description: Communication between web-servers and database + priority: unspecified scope: global state: present delegate_to: localhost -- name: Remove an existing contract - cisco.aci.aci_contract: +- name: Query a specific contract + cisco.aci.aci_oob_contract: host: apic username: admin password: SomeSecretPassword contract: web_to_db - state: absent + state: query delegate_to: localhost + register: query_result -- name: Query a specific contract - cisco.aci.aci_contract: +- name: Query all contracts + cisco.aci.aci_oob_contract: host: apic username: admin password: SomeSecretPassword - contract: web_to_db state: query delegate_to: localhost register: query_result -- name: Query all contracts - cisco.aci.aci_contract: +- name: Remove an existing contract + cisco.aci.aci_oob_contract: host: apic username: admin password: SomeSecretPassword - state: query + contract: web_to_db + state: absent delegate_to: localhost - register: query_result """ RETURN = r""" diff --git a/tests/integration/targets/aci_oob_contract/tasks/main.yml b/tests/integration/targets/aci_oob_contract/tasks/main.yml index be1cc30b0..b795b0d1d 100644 --- a/tests/integration/targets/aci_oob_contract/tasks/main.yml +++ b/tests/integration/targets/aci_oob_contract/tasks/main.yml @@ -1,5 +1,5 @@ # Test code for the ACI modules -# Copyright: (c) 2017, Jacob McGill (@jmcgill298) +# Copyright: (c) 2024, Faiz Mohammad (@Ziaf007) # GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) @@ -35,25 +35,29 @@ - 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 + + # CLEAN ENVIRONMENT - name: Ensure Contract doesn't exist cisco.aci.aci_oob_contract: <<: *aci_info contract: anstest state: absent description: Ansible Test - + + # CREATE - name: create contract - check mode works - cisco.aci.aci_oob_contract: &aci_oob_contract_present + cisco.aci.aci_oob_contract: &aci_oob_contract_present_CM <<: *aci_info contract: anstest description: Ansible Test - state: present + #state: present >>>> DEFAULTS TO 'PRESENT" ASSERTATION check_mode: true register: present_check_mode - name: create contract - creation works - cisco.aci.aci_oob_contract: - <<: *aci_oob_contract_present + cisco.aci.aci_oob_contract: &aci_oob_contract_present + <<: *aci_oob_contract_present_CM + state: present register: contract_present - name: create contract - idempotency works @@ -61,23 +65,11 @@ <<: *aci_oob_contract_present register: present_idempotent - - name: update contract - update works - cisco.aci.aci_oob_contract: - <<: *aci_oob_contract_present - scope: application-profile - register: present_update - - name: create contract - used for query cisco.aci.aci_oob_contract: <<: *aci_oob_contract_present contract: anstest2 - - name: missing param - failure message works - cisco.aci.aci_oob_contract: - <<: *aci_info - ignore_errors: true - register: present_missing_param - - name: present assertions ansible.builtin.assert: that: @@ -85,16 +77,35 @@ - present_check_mode.previous == [] - present_check_mode.sent.vzOOBBrCP.attributes.name == 'anstest' - present_check_mode.sent.vzOOBBrCP.attributes.descr == 'Ansible Test' + - present_check_mode.invocation.module_args.state == 'present' - contract_present is changed - contract_present.current.0.vzOOBBrCP.attributes.annotation == 'orchestrator:ansible' - contract_present.sent == present_check_mode.sent - present_idempotent is not changed + + # UPDATE + - name: update contract - update works + cisco.aci.aci_oob_contract: + <<: *aci_oob_contract_present + scope: application-profile + register: present_update + + - name: missing param - failure message works + cisco.aci.aci_oob_contract: + <<: *aci_info + ignore_errors: true + register: present_missing_param + + - name: update assertions + ansible.builtin.assert: + that: - present_update is changed - present_update.sent != present_update.proposed - present_update.sent.vzOOBBrCP.attributes.scope == "application-profile" - present_missing_param is failed - 'present_missing_param.msg == "state is present but all of the following are missing: contract"' + # QUERY - name: query contract cisco.aci.aci_oob_contract: &aci_oob_contract_query <<: *aci_oob_contract_present @@ -119,7 +130,7 @@ - '"rsp-subtree-class=vzOOBBrCP" in query_tenant.filter_string' - '"tn-mgmt.json" in query_tenant.url' - + # DELETE - name: delete contract - check mode works cisco.aci.aci_oob_contract: &aci_oob_contract_absent <<: *aci_oob_contract_present From f6d59ba60ca9dc929c9b3b56023829aa6023ecb8 Mon Sep 17 00:00:00 2001 From: Ziaf007 Date: Fri, 20 Dec 2024 22:53:54 +0530 Subject: [PATCH 7/7] fixed some typos. --- plugins/modules/aci_oob_contract.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/plugins/modules/aci_oob_contract.py b/plugins/modules/aci_oob_contract.py index e0e886d9d..876f0e8ce 100644 --- a/plugins/modules/aci_oob_contract.py +++ b/plugins/modules/aci_oob_contract.py @@ -19,7 +19,7 @@ options: contract: description: - - The name of the contract. + - The name of the OOB contract. type: str aliases: [ contract_name, name ] description: @@ -29,7 +29,7 @@ aliases: [ descr ] scope: description: - - The scope of a the OOB contract. + - The scope of the OOB contract. - The APIC defaults to C(context) when unset during creation. type: str choices: [ application-profile, context, global, tenant ]