diff --git a/plugins/modules/aci_syslog_group.py b/plugins/modules/aci_syslog_group.py index 205c3593b..55302bd11 100644 --- a/plugins/modules/aci_syslog_group.py +++ b/plugins/modules/aci_syslog_group.py @@ -1,6 +1,8 @@ #!/usr/bin/python # -*- coding: utf-8 -*- +# Copyright: (c) 2021, Tim Cragg (@timcragg) +# Copyright: (c) 2025, Dev Sinha (@DevSinha13) # GNU General 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,47 +20,70 @@ options: admin_state: description: - - Administrative state of the syslog group + - Administrative state of the syslog group. type: str choices: [ enabled, disabled ] console_logging: description: - - Log events to console + - Log events to console. type: str choices: [ enabled, disabled ] console_log_severity: description: - - Severity of events to log to console + - Severity of events to log to console. + - If unset during creation, value defaults to C(alerts). type: str - choices: [ alerts, critical, debugging, emergencies, error, information, notifications, warnings ] + choices: [ alerts, critical, emergencies] local_file_logging: description: - - Log to local file + - Log to local file. type: str choices: [ enabled, disabled ] local_file_log_severity: description: - - Severity of events to log to local file + - Severity of events to log to local file. + - If unset during creation, value defaults to C(alerts). type: str choices: [ alerts, critical, debugging, emergencies, error, information, notifications, warnings ] format: description: - - Format of the syslog messages. If omitted when creating a group, ACI defaults to using aci format. + - Format of the syslog messages. + - If unset during creation the value defaults to C(aci). + - C(rfc5424-ts) is only available starting from ACI version 5.2(8). + type: str + choices: [ aci, nxos, rfc5424-ts ] + local_file_log_format: + description: + - The format of the local file log messages. + - If unset during creation and O(format) is provided then it is set to the same value as format. If O(format) is not provided it is set to C(aci). + - C(rfc5424-ts) is only available starting from ACI version 5.2(8). type: str - choices: [ aci, nxos ] + choices: [ aci, nxos, rfc5424-ts ] + console_log_format: + description: + - Format of the console log messages. + - If unset during creation and O(format) is provided then it is set to the same value as format. If O(format) is not provided it is set to C(aci). + - C(rfc5424-ts) is only available starting from ACI version 5.2(8). + type: str + choices: [ aci, nxos, rfc5424-ts ] include_ms: description: - - Include milliseconds in log timestamps + - Include milliseconds in log timestamps. type: bool include_time_zone: description: - - Include timezone in log timestamps + - Include timezone in log timestamps. type: bool name: description: - - Name of the syslog group + - Name of the syslog group. type: str aliases: [ syslog_group, syslog_group_name ] + description: + description: + - Description for the syslog group. + type: str + aliases: [ descr ] state: description: - Use C(present) or C(absent) for adding or removing. @@ -76,6 +101,7 @@ link: https://developer.cisco.com/docs/apic-mim-ref/ author: - Tim Cragg (@timcragg) +- Dev Sinha (@DevSinha13) """ EXAMPLES = r""" @@ -89,9 +115,27 @@ local_file_log_severity: warnings console_logging: enabled console_log_severity: critical + description: syslog group state: present delegate_to: localhost +- name: Create a syslog group with local_file_log_format and console_log_format + cisco.aci.aci_syslog_group: + host: apic + username: admin + password: SomeSecretPassword + format: aci + name: my_syslog_group + local_file_logging: enabled + local_file_log_severity: warnings + console_logging: enabled + console_log_severity: critical + local_file_log_format: rfc5424-ts + console_log_format: rfc5424-ts + description: syslog group + state: present + + - name: Disable logging to local file cisco.aci.aci_syslog_group: host: apic @@ -246,10 +290,12 @@ def main(): argument_spec.update(aci_annotation_spec()) argument_spec.update( name=dict(type="str", aliases=["syslog_group", "syslog_group_name"]), - format=dict(type="str", choices=["aci", "nxos"]), + format=dict(type="str", choices=["aci", "nxos", "rfc5424-ts"]), + local_file_log_format=dict(type="str", choices=["aci", "nxos", "rfc5424-ts"]), + console_log_format=dict(type="str", choices=["aci", "nxos", "rfc5424-ts"]), admin_state=dict(type="str", choices=["enabled", "disabled"]), console_logging=dict(type="str", choices=["enabled", "disabled"]), - console_log_severity=dict(type="str", choices=["alerts", "critical", "debugging", "emergencies", "error", "information", "notifications", "warnings"]), + console_log_severity=dict(type="str", choices=["alerts", "critical", "emergencies"]), local_file_logging=dict(type="str", choices=["enabled", "disabled"]), local_file_log_severity=dict( type="str", choices=["alerts", "critical", "debugging", "emergencies", "error", "information", "notifications", "warnings"] @@ -257,6 +303,7 @@ def main(): include_ms=dict(type="bool"), include_time_zone=dict(type="bool"), state=dict(type="str", default="present", choices=["absent", "present", "query"]), + description=dict(type="str", aliases=["descr"]), ) module = AnsibleModule( @@ -275,11 +322,20 @@ def main(): admin_state = module.params.get("admin_state") console_logging = module.params.get("console_logging") console_log_severity = module.params.get("console_log_severity") + console_log_format = module.params.get("console_log_format") + local_file_log_format = module.params.get("local_file_log_format") local_file_logging = module.params.get("local_file_logging") local_file_log_severity = module.params.get("local_file_log_severity") include_ms = aci.boolean(module.params.get("include_ms")) include_time_zone = aci.boolean(module.params.get("include_time_zone")) state = module.params.get("state") + description = module.params.get("description") + + if console_log_format is None: + console_log_format = format + + if local_file_log_format is None: + local_file_log_format = format aci.construct_url( root_class=dict( @@ -297,6 +353,7 @@ def main(): class_config = dict( name=name, format=format, + descr=description, includeMilliSeconds=include_ms, ) if include_time_zone is not None: @@ -312,12 +369,12 @@ def main(): ), dict( syslogFile=dict( - attributes=dict(adminState=local_file_logging, format=format, severity=local_file_log_severity), + attributes=dict(adminState=local_file_logging, format=local_file_log_format, severity=local_file_log_severity), ), ), dict( syslogConsole=dict( - attributes=dict(adminState=console_logging, format=format, severity=console_log_severity), + attributes=dict(adminState=console_logging, format=console_log_format, severity=console_log_severity), ), ), ], diff --git a/tests/integration/targets/aci_syslog_group/tasks/main.yml b/tests/integration/targets/aci_syslog_group/tasks/main.yml index 34a2ddf63..922d8dfe4 100644 --- a/tests/integration/targets/aci_syslog_group/tasks/main.yml +++ b/tests/integration/targets/aci_syslog_group/tasks/main.yml @@ -1,5 +1,6 @@ # Test code for the ACI modules # Copyright: (c) 2021, Tim Cragg (@timcragg) +# Copyright: (c) 2025, Dev Sinha (@DevSinha13) # GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) @@ -34,8 +35,14 @@ name: ansible_syslog_group state: absent -# ADD syslog group -- name: Add syslog group (version >= 4) +- name: Remove ansible_syslog_new if it already exists + cisco.aci.aci_syslog_group: + <<: *aci_info + name: ansible_syslog_new + state: absent + +# ADD syslog group(Check mode) +- name: Add syslog group (version >= 4) - (Check mode) cisco.aci.aci_syslog_group: &aci_syslog_present <<: *aci_info name: ansible_syslog_group @@ -47,11 +54,20 @@ console_log_severity: critical include_ms: true include_time_zone: true + description: Description for the syslog group state: present + check_mode: true + register: add_syslog_group_cm + when: version.current.0.topSystem.attributes.version is version('4', '>=') + +#ADD syslog group +- name: Add syslog group (version >= 4) - (No check mode) + cisco.aci.aci_syslog_group: + <<: *aci_syslog_present register: add_syslog_group when: version.current.0.topSystem.attributes.version is version('4', '>=') -- name: Add syslog group (version < 4) +- name: Add syslog group (version < 4) - (Check mode) cisco.aci.aci_syslog_group: &aci_syslog_present_32 <<: *aci_info name: ansible_syslog_group @@ -62,49 +78,97 @@ console_logging: enabled console_log_severity: critical include_ms: true + description: Description for the syslog group state: present + check_mode: true + register: add_syslog_group_32_cm + when: version.current.0.topSystem.attributes.version is version('4', '<') + +- name: Add syslog group (version < 4) - No Check mode + cisco.aci.aci_syslog_group: + <<: *aci_syslog_present_32 register: add_syslog_group_32 when: version.current.0.topSystem.attributes.version is version('4', '<') +- name: Sort children by name for 32 + ansible.builtin.set_fact: + sorted_children_32: "{{ add_syslog_group_32.current[0].syslogGroup.children | map('dict2items') | sort(attribute='0.key') | map('items2dict') | list }}" + when: version.current.0.topSystem.attributes.version is version('4', '<') + +- name: Sort children by name + ansible.builtin.set_fact: + sorted_children: "{{ add_syslog_group.current[0].syslogGroup.children | map('dict2items') | sort(attribute='0.key') | map('items2dict') | list }}" + when: version.current.0.topSystem.attributes.version is version('4', '>=') + +- name: Verify that ansible_syslog_group has been created with correct attributes in check mode(version >= 4) + ansible.builtin.assert: + that: + - add_syslog_group_cm is changed + - add_syslog_group_cm.proposed.syslogGroup.attributes.dn == "uni/fabric/slgroup-ansible_syslog_group" + - add_syslog_group_cm.proposed.syslogGroup.attributes.name == "ansible_syslog_group" + - add_syslog_group_cm.proposed.syslogGroup.attributes.format == "aci" + - add_syslog_group_cm.proposed.syslogGroup.attributes.includeMilliSeconds == "yes" + - add_syslog_group_cm.proposed.syslogGroup.attributes.includeTimeZone == "yes" + - add_syslog_group_cm.proposed.syslogGroup.attributes.annotation == 'orchestrator:ansible' + - add_syslog_group_cm.proposed.syslogGroup.attributes.descr == 'Description for the syslog group' + when: version.current.0.topSystem.attributes.version is version('4', '>=') + + - name: Verify that ansible_syslog_group has been created with correct attributes (version > 4) ansible.builtin.assert: that: + - add_syslog_group is changed - 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" - add_syslog_group.current.0.syslogGroup.attributes.format == "aci" - add_syslog_group.current.0.syslogGroup.attributes.includeMilliSeconds == "yes" - add_syslog_group.current.0.syslogGroup.attributes.includeTimeZone == "yes" - add_syslog_group.current.0.syslogGroup.attributes.annotation == 'orchestrator:ansible' + - add_syslog_group.current.0.syslogGroup.attributes.descr == 'Description for the syslog group' when: version.current.0.topSystem.attributes.version is version('4', '>=') +- name: Verify that ansible_syslog_group has been created with correct attributes in check mode (version < 4) + ansible.builtin.assert: + that: + - add_syslog_group_32_cm is changed + - add_syslog_group_32_cm.proposed.syslogGroup.attributes.dn == "uni/fabric/slgroup-ansible_syslog_group" + - add_syslog_group_32_cm.proposed.syslogGroup.attributes.name == "ansible_syslog_group" + - add_syslog_group_32_cm.proposed.syslogGroup.attributes.format == "aci" + - add_syslog_group_32_cm.proposed.syslogGroup.attributes.includeMilliSeconds == "yes" + - add_syslog_group_32_cm.proposed.syslogGroup.attributes.annotation == 'orchestrator:ansible' + - add_syslog_group_32_cm.proposed.syslogGroup.attributes.descr == 'Description for the syslog group' + when: version.current.0.topSystem.attributes.version is version('4', '<') + - name: Verify that ansible_syslog_group has been created with correct attributes (version < 4) ansible.builtin.assert: that: + - add_syslog_group_32 is changed - 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" - add_syslog_group_32.current.0.syslogGroup.attributes.format == "aci" - add_syslog_group_32.current.0.syslogGroup.attributes.includeMilliSeconds == "yes" - add_syslog_group_32.current.0.syslogGroup.attributes.annotation == 'orchestrator:ansible' + - add_syslog_group_32.current.0.syslogGroup.attributes.descr == 'Description for the syslog group' when: version.current.0.topSystem.attributes.version is version('4', '<') - name: Verify that ansible_syslog_group children have correct attributes (version >= 4) 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" - - add_syslog_group.current.0.syslogGroup.children.1.syslogFile.attributes.adminState == "enabled" - - add_syslog_group.current.0.syslogGroup.children.1.syslogFile.attributes.severity == "warnings" - - add_syslog_group.current.0.syslogGroup.children.2.syslogProf.attributes.adminState == "enabled" + - sorted_children.0.syslogConsole.attributes.adminState == "enabled" + - sorted_children.0.syslogConsole.attributes.severity == "critical" + - sorted_children.1.syslogFile.attributes.adminState == "enabled" + - sorted_children.1.syslogFile.attributes.severity == "warnings" + - sorted_children.2.syslogProf.attributes.adminState == "enabled" when: version.current.0.topSystem.attributes.version is version('4', '>=') - name: Verify that ansible_syslog_group children have correct attributes (version < 4) 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" - - add_syslog_group_32.current.0.syslogGroup.children.1.syslogFile.attributes.adminState == "enabled" - - add_syslog_group_32.current.0.syslogGroup.children.1.syslogFile.attributes.severity == "warnings" - - add_syslog_group_32.current.0.syslogGroup.children.2.syslogProf.attributes.adminState == "enabled" + - sorted_children_32.0.syslogConsole.attributes.adminState == "enabled" + - sorted_children_32.0.syslogConsole.attributes.severity == "critical" + - sorted_children_32.1.syslogFile.attributes.adminState == "enabled" + - sorted_children_32.1.syslogFile.attributes.severity == "warnings" + - sorted_children_32.2.syslogProf.attributes.adminState == "enabled" when: version.current.0.topSystem.attributes.version is version('4', '<') # ADD syslog group again to check idempotency @@ -145,6 +209,7 @@ console_log_severity: emergencies include_ms: false include_time_zone: false + description: Updated syslog group state: present register: update_syslog_group when: version.current.0.topSystem.attributes.version is version('4', '>=') @@ -160,10 +225,22 @@ console_logging: disabled console_log_severity: emergencies include_ms: false + description: Updated syslog_group_32 state: present register: update_syslog_group_32 when: version.current.0.topSystem.attributes.version is version('4', '<') + +- name: Sort updated children by name for 32 + ansible.builtin.set_fact: + updated_sorted_children_32: "{{ update_syslog_group_32.current[0].syslogGroup.children | map('dict2items') | sort(attribute='0.key') | map('items2dict') | list }}" + when: version.current.0.topSystem.attributes.version is version('4', '<') + +- name: Sort updated children by name + ansible.builtin.set_fact: + updated_sorted_children: "{{ update_syslog_group.current[0].syslogGroup.children | map('dict2items') | sort(attribute='0.key') | map('items2dict') | list }}" + when: version.current.0.topSystem.attributes.version is version('4', '>=') + - name: Verify that ansible_syslog_group has been updated with correct attributes (version >= 4) ansible.builtin.assert: that: @@ -172,6 +249,7 @@ - update_syslog_group.current.0.syslogGroup.attributes.format == "nxos" - update_syslog_group.current.0.syslogGroup.attributes.includeMilliSeconds == "no" - update_syslog_group.current.0.syslogGroup.attributes.includeTimeZone == "no" + - update_syslog_group.current.0.syslogGroup.attributes.descr == "Updated syslog group" when: version.current.0.topSystem.attributes.version is version('4', '>=') - name: Verify that ansible_syslog_group has been updated with correct attributes (version < 4) @@ -181,28 +259,66 @@ - update_syslog_group_32.current.0.syslogGroup.attributes.name == "ansible_syslog_group" - update_syslog_group_32.current.0.syslogGroup.attributes.format == "nxos" - update_syslog_group_32.current.0.syslogGroup.attributes.includeMilliSeconds == "no" + - update_syslog_group_32.current.0.syslogGroup.attributes.descr == "Updated syslog_group_32" when: version.current.0.topSystem.attributes.version is version('4', '<') - name: Verify that ansible_syslog_group children have correct attributes (version >= 4) 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" - - update_syslog_group.current.0.syslogGroup.children.1.syslogFile.attributes.adminState == "enabled" - - update_syslog_group.current.0.syslogGroup.children.1.syslogFile.attributes.severity == "debugging" - - update_syslog_group.current.0.syslogGroup.children.2.syslogProf.attributes.adminState == "disabled" + - updated_sorted_children.0.syslogConsole.attributes.adminState == "disabled" + - updated_sorted_children.0.syslogConsole.attributes.severity == "emergencies" + - updated_sorted_children.1.syslogFile.attributes.adminState == "enabled" + - updated_sorted_children.1.syslogFile.attributes.severity == "debugging" + - updated_sorted_children.2.syslogProf.attributes.adminState == "disabled" when: version.current.0.topSystem.attributes.version is version('4', '>=') - name: Verify that ansible_syslog_group children have correct attributes (version < 4) 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" - - update_syslog_group_32.current.0.syslogGroup.children.1.syslogFile.attributes.adminState == "enabled" - - update_syslog_group_32.current.0.syslogGroup.children.1.syslogFile.attributes.severity == "debugging" - - update_syslog_group_32.current.0.syslogGroup.children.2.syslogProf.attributes.adminState == "disabled" + - updated_sorted_children_32.0.syslogConsole.attributes.adminState == "disabled" + - updated_sorted_children_32.0.syslogConsole.attributes.severity == "emergencies" + - updated_sorted_children_32.1.syslogFile.attributes.adminState == "enabled" + - updated_sorted_children_32.1.syslogFile.attributes.severity == "debugging" + - updated_sorted_children_32.2.syslogProf.attributes.adminState == "disabled" when: version.current.0.topSystem.attributes.version is version('4', '<') +- name: Execute tasks only for non-cloud sites + when: version.current.0.topSystem.attributes.version is version('6', '>=') + block: + # ADD syslog group with rfc5424-ts as format + - name: Add syslog new (version >= 6) + cisco.aci.aci_syslog_group: + <<: *aci_info + name: ansible_syslog_new + admin_state: enabled + format: rfc5424-ts + local_file_logging: enabled + local_file_log_severity: warnings + console_log_severity: critical + console_logging: enabled + local_file_log_format: rfc5424-ts + console_log_format: rfc5424-ts + description: Description for the syslog group + state: present + register: add_syslog_new_format + + - name: Sort updated children by name + ansible.builtin.set_fact: + sorted_new: "{{ add_syslog_new_format.current[0].syslogGroup.children | map('dict2items') | sort(attribute='0.key') | map('items2dict') | list }}" + + + - name: Verify that the format rfc5424-ts is valid for syslog group and children + ansible.builtin.assert: + that: + - add_syslog_new_format is changed + - add_syslog_new_format.current.0.syslogGroup.attributes.dn == "uni/fabric/slgroup-ansible_syslog_new" + - add_syslog_new_format.current.0.syslogGroup.attributes.name == "ansible_syslog_new" + - add_syslog_new_format.current.0.syslogGroup.attributes.format == "rfc5424-ts" + - add_syslog_new_format.current.0.syslogGroup.attributes.annotation == 'orchestrator:ansible' + - add_syslog_new_format.current.0.syslogGroup.attributes.descr == 'Description for the syslog group' + - sorted_new.0.syslogConsole.attributes.format == "rfc5424-ts" + - sorted_new.1.syslogFile.attributes.format == "rfc5424-ts" + # QUERY syslog group - name: Query the syslog group cisco.aci.aci_syslog_group: @@ -229,8 +345,17 @@ that: - query_syslog_group_all is not changed -# DELETE syslog group -- name: Remove the syslog group +# DELETE syslog group(check mode) +- name: Remove the syslog group (check mode) + cisco.aci.aci_syslog_group: + <<: *aci_info + name: ansible_syslog_group + state: absent + check_mode: true + register: remove_syslog_group_cm + +# Delete syslog group +- name: Remove the syslog group cisco.aci.aci_syslog_group: <<: *aci_info name: ansible_syslog_group @@ -240,6 +365,16 @@ - name: Verify remove_syslog_group ansible.builtin.assert: that: + - remove_syslog_group_cm is changed + - remove_syslog_group_cm.proposed == {} + - remove_syslog_group_cm.previous == remove_syslog_group.previous + - remove_syslog_group.current == [] - remove_syslog_group is changed - remove_syslog_group.previous.0.syslogGroup.attributes.dn == "uni/fabric/slgroup-ansible_syslog_group" - remove_syslog_group.previous.0.syslogGroup.attributes.name == "ansible_syslog_group" + +- name: Remove ansible_syslog_new if it already exists + cisco.aci.aci_syslog_group: + <<: *aci_info + name: ansible_syslog_new + state: absent \ No newline at end of file