Skip to content
Snippets Groups Projects
Commit db86e21e authored by Aleksandr Kurbatov's avatar Aleksandr Kurbatov
Browse files

Merge branch 'add_custom_callback_module' into 'develop'

Add a custom callback plugin for managing logs

See merge request !277
parents 987f9a27 f17cb6a9
No related branches found
No related tags found
1 merge request!277Add a custom callback plugin for managing logs
Pipeline #95539 passed
../plugins/callback_plugins
\ No newline at end of file
# callback_plugins/filtering_syslog.py
import difflib
import syslog
import uuid
from datetime import datetime
from ansible.plugins.callback import CallbackBase
from ansible.utils.display import Display
display = Display()
class CallbackModule(CallbackBase):
"""
Logs all task results to syslog with timestamp and run ID.
One line per result. Only prints tasks tagged with 'print_action'.
Always prints and logs playbook summary.
"""
CALLBACK_VERSION = 2.0
CALLBACK_TYPE = 'stdout'
CALLBACK_NAME = 'filtering_syslog'
def __init__(self):
super().__init__()
syslog.openlog(ident="ansible", logoption=syslog.LOG_PID, facility=syslog.LOG_USER)
self.run_id = str(uuid.uuid4())[:8] # Shorten for readability
def _log_to_syslog(self, message: str):
timestamp = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
syslog.syslog(syslog.LOG_INFO, f"[{timestamp}] [run_id:{self.run_id}] {message}")
def _should_print(self, task):
return hasattr(task, "tags") and "print_action" in task.tags
def _pretty_print(self, result, status):
task_name = result.task_name or result._task.get_name()
host = result._host.get_name()
display.banner(f"TASK [{task_name}]")
display.display(f"{host} | {status}", color="green" if status == "ok" else "red")
# Display diff if present
if 'diff' in result._result:
display.display("DIFF:", color="blue")
_before = result._result['diff']['before']
_after = result._result['diff']['after']
difference = difflib.context_diff(_before.splitlines(), _after.splitlines(), n=10)
for line in difference:
display.display(line)
# Display full result if not ok
if status != "ok":
display.display(self._dump_results(result._result))
def v2_runner_on_ok(self, result):
task = result.task_name or result._task.get_name()
host = result._host.get_name()
self._log_to_syslog(f"{host} | OK | Task: {task}")
if self._should_print(result._task):
self._pretty_print(result, "ok")
def v2_runner_on_failed(self, result, ignore_errors=False):
task = result.task_name or result._task.get_name()
host = result._host.get_name()
self._log_to_syslog(f"{host} | FAILED | Task: {task}")
if self._should_print(result._task):
self._pretty_print(result, "failed")
def v2_runner_on_skipped(self, result):
task = result.task_name or result._task.get_name()
host = result._host.get_name()
self._log_to_syslog(f"{host} | SKIPPED | Task: {task}")
if self._should_print(result._task):
self._pretty_print(result, "skipped")
def v2_playbook_on_stats(self, stats):
summary = {}
for host in stats.processed.keys():
s = stats.summarize(host)
summary_line = f"{host} | SUMMARY | ok={s['ok']} changed={s['changed']} unreachable={s['unreachable']} failed={s['failures']} skipped={s['skipped']}"
self._log_to_syslog(summary_line)
display.display(summary_line)
display.banner("PLAYBOOK SUMMARY")
...@@ -14,6 +14,15 @@ ...@@ -14,6 +14,15 @@
diff: true diff: true
register: output register: output
check_mode: true check_mode: true
tags: [print_action]
- name: Fail if there is any diff
ansible.builtin.fail:
msg: Base config drift detected!!!
when: >
output.changed | ansible.builtin.bool
and
is_verification_workflow | ansible.builtin.bool
- name: Config deploy [CHECK ONLY][JUNIPER] - name: Config deploy [CHECK ONLY][JUNIPER]
when: > when: >
...@@ -27,6 +36,7 @@ ...@@ -27,6 +36,7 @@
check_commit: true check_commit: true
diff: true diff: true
register: output register: output
tags: [print_action]
- name: Fail if there is any diff - name: Fail if there is any diff
ansible.builtin.fail: ansible.builtin.fail:
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment