From e738cc567bb52e267c172719c723048e67f129b5 Mon Sep 17 00:00:00 2001 From: Simone Spinelli <simone.spinelli@GA0503-SSPINELLI.local> Date: Tue, 17 Jun 2025 10:40:35 +0200 Subject: [PATCH 1/6] Add a custom callback plugin for managing logs --- .../callback_plugins/filtering_syslog.py | 70 +++++++++++++++++++ 1 file changed, 70 insertions(+) create mode 100644 geant/gap_ansible/plugins/callback_plugins/filtering_syslog.py diff --git a/geant/gap_ansible/plugins/callback_plugins/filtering_syslog.py b/geant/gap_ansible/plugins/callback_plugins/filtering_syslog.py new file mode 100644 index 00000000..7e8cf052 --- /dev/null +++ b/geant/gap_ansible/plugins/callback_plugins/filtering_syslog.py @@ -0,0 +1,70 @@ +# callback_plugins/filtering_syslog.py +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.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") -- GitLab From e12b34d925ee14072100177b0edb74d7f8ed7d21 Mon Sep 17 00:00:00 2001 From: Aleksandr Kurbatov <ak@geant.org> Date: Tue, 8 Jul 2025 19:15:29 +0100 Subject: [PATCH 2/6] Update `filtering_syslog` to use diff --- .../plugins/callback_plugins/filtering_syslog.py | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/geant/gap_ansible/plugins/callback_plugins/filtering_syslog.py b/geant/gap_ansible/plugins/callback_plugins/filtering_syslog.py index 7e8cf052..5199d63e 100644 --- a/geant/gap_ansible/plugins/callback_plugins/filtering_syslog.py +++ b/geant/gap_ansible/plugins/callback_plugins/filtering_syslog.py @@ -1,4 +1,5 @@ # callback_plugins/filtering_syslog.py +import difflib import syslog import uuid from datetime import datetime @@ -36,7 +37,19 @@ class CallbackModule(CallbackBase): display.banner(f"TASK [{task_name}]") display.display(f"{host} | {status}", color="green" if status == "ok" else "red") - display.display(self._dump_results(result._result)) + + # Display diff if present + if 'diff' in result._result: + display.display("DIFF:", color="blue") + _before = result._result['diff']['before'] + _after = result._result['diff']['after'] + for line in difflib.ndiff(_before.splitlines(), _after.splitlines()): + if line.startswith('+ ') or line.startswith('- ') or line.startswith('? '): + 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() -- GitLab From b9201c5a69cdf9ffa88b6ae0a334465d1868d8de Mon Sep 17 00:00:00 2001 From: Aleksandr Kurbatov <ak@geant.org> Date: Tue, 8 Jul 2025 19:15:58 +0100 Subject: [PATCH 3/6] Link to callback_plugins from the playbooks dir --- geant/gap_ansible/playbooks/callback_plugins | 1 + 1 file changed, 1 insertion(+) create mode 120000 geant/gap_ansible/playbooks/callback_plugins diff --git a/geant/gap_ansible/playbooks/callback_plugins b/geant/gap_ansible/playbooks/callback_plugins new file mode 120000 index 00000000..6a368d07 --- /dev/null +++ b/geant/gap_ansible/playbooks/callback_plugins @@ -0,0 +1 @@ +../plugins/callback_plugins \ No newline at end of file -- GitLab From 2b09d88848d28cbc15bdff7c4bbe0cd8e9ff9ff5 Mon Sep 17 00:00:00 2001 From: Aleksandr Kurbatov <ak@geant.org> Date: Tue, 8 Jul 2025 19:16:37 +0100 Subject: [PATCH 4/6] Update edge_port/tasks/deploy to use filter_syslog plugin --- .../gap_ansible/roles/edge_port/tasks/deploy.yaml | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/geant/gap_ansible/roles/edge_port/tasks/deploy.yaml b/geant/gap_ansible/roles/edge_port/tasks/deploy.yaml index 57cc6aa2..405a3fc0 100644 --- a/geant/gap_ansible/roles/edge_port/tasks/deploy.yaml +++ b/geant/gap_ansible/roles/edge_port/tasks/deploy.yaml @@ -14,6 +14,15 @@ diff: true register: output 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] when: > @@ -28,6 +37,11 @@ diff: true register: output +# - name: Display the output +# ansible.builtin.debug: +# msg: "{{ output }}" +# tags: [print_action] + - name: Fail if there is any diff ansible.builtin.fail: msg: Base config drift detected!!! -- GitLab From faac00258c6435e091b475aa2ff1b8ea3b668713 Mon Sep 17 00:00:00 2001 From: Aleksandr Kurbatov <ak@geant.org> Date: Wed, 9 Jul 2025 11:04:24 +0100 Subject: [PATCH 5/6] callback_plugin: difflib: ndiff -> context_diff --- .../plugins/callback_plugins/filtering_syslog.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/geant/gap_ansible/plugins/callback_plugins/filtering_syslog.py b/geant/gap_ansible/plugins/callback_plugins/filtering_syslog.py index 5199d63e..f2065551 100644 --- a/geant/gap_ansible/plugins/callback_plugins/filtering_syslog.py +++ b/geant/gap_ansible/plugins/callback_plugins/filtering_syslog.py @@ -43,9 +43,9 @@ class CallbackModule(CallbackBase): display.display("DIFF:", color="blue") _before = result._result['diff']['before'] _after = result._result['diff']['after'] - for line in difflib.ndiff(_before.splitlines(), _after.splitlines()): - if line.startswith('+ ') or line.startswith('- ') or line.startswith('? '): - display.display(line) + 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": -- GitLab From f17cb6a925ba630af98f60968f81307e7603e24a Mon Sep 17 00:00:00 2001 From: Aleksandr Kurbatov <ak@geant.org> Date: Wed, 9 Jul 2025 11:20:15 +0100 Subject: [PATCH 6/6] edge_port/tasks/deploy.yaml - Added separate output.changed evaluation after Nokia dry-run; - cleanup. --- geant/gap_ansible/roles/edge_port/tasks/deploy.yaml | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/geant/gap_ansible/roles/edge_port/tasks/deploy.yaml b/geant/gap_ansible/roles/edge_port/tasks/deploy.yaml index 405a3fc0..0d74fdfd 100644 --- a/geant/gap_ansible/roles/edge_port/tasks/deploy.yaml +++ b/geant/gap_ansible/roles/edge_port/tasks/deploy.yaml @@ -36,11 +36,7 @@ check_commit: true diff: true register: output - -# - name: Display the output -# ansible.builtin.debug: -# msg: "{{ output }}" -# tags: [print_action] + tags: [print_action] - name: Fail if there is any diff ansible.builtin.fail: -- GitLab