[PATCH 21/26] lucid: handle notify and empty host sets

Daniel Gomez <[email protected]> Tue, 19 May 2026 15:28:18 +0200
Newsgroups dev.linux.lists.kdevops
Message-ID <[email protected]>
From: Daniel Gomez <[email protected]>

Three playbook-level hooks that do not correspond to a task but
materially affect what the user sees: v2_playbook_on_notify fires
when a task triggers a notify, and the two no_hosts hooks fire when
a play has nothing left to run. CallbackBase inherits all three as
no-ops, so lucid previously went silent on notifications and on
prematurely empty plays, both of which are moments the user needs
signal on.

Notifications are progressive-verbosity: we always log them but only
display at -v or higher, because well-written playbooks trigger many
pending handlers and most of them never fire. The two no-hosts
hooks, by contrast, are always displayed. A pattern that matched
zero hosts almost always indicates a mistake, and an empty remaining
set signals an any_errors_fatal escalation where the playbook is
about to end; both need to reach the terminal regardless of the
user's verbosity setting.

Generated-by: Claude AI
Signed-off-by: Daniel Gomez <[email protected]>
---
 callback_plugins/lucid.py | 47 +++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 47 insertions(+)

diff --git a/callback_plugins/lucid.py b/callback_plugins/lucid.py
index 0b713726..a8d0a9c1 100644
--- a/callback_plugins/lucid.py
+++ b/callback_plugins/lucid.py
@@ -541,6 +541,53 @@ class CallbackModule(CallbackBase):
                 self._display.display(msg, color=C.COLOR_SKIP)
         self._write_to_log(msg)
 
+    def v2_playbook_on_notify(self, handler, host):
+        """A task triggered a notify on a host.
+
+        Well-written playbooks fan out many notifications, most of
+        which never translate to a handler run if nothing changed.
+        We log each notification unconditionally (the log is the
+        audit trail) but only surface them on screen at -v or
+        higher, matching the reference default callback's quiet
+        default so lucid doesn't drown the user in pending-handler
+        chatter.
+        """
+        handler_name = handler.get_name()
+        host_name = host.get_name() if hasattr(host, "get_name") else str(host)
+        msg = f"NOTIFY: {handler_name} on {host_name}"
+        if self._display.verbosity >= 1:
+            with self.output_lock:
+                self._display.display(msg, color=C.COLOR_VERBOSE)
+        self._write_to_log(msg)
+
+    def v2_playbook_on_no_hosts_matched(self):
+        """A play's hosts pattern matched zero inventory hosts.
+
+        This is almost always a user error (typo in the pattern,
+        wrong inventory loaded, stale group name), so we always
+        display it regardless of verbosity. Coloring matches the
+        reference default callback's skip palette so the line reads
+        as a skipped play rather than a failure.
+        """
+        msg = "skipping: no hosts matched"
+        with self.output_lock:
+            self._display.display(msg, color=C.COLOR_SKIP)
+        self._write_to_log(msg)
+
+    def v2_playbook_on_no_hosts_remaining(self):
+        """All hosts have been removed from the active set.
+
+        Fires when any_errors_fatal or max_fail_percentage escalates
+        a failure out of scope and there is nothing left to run
+        against. Always displayed in error color because the
+        playbook is about to end prematurely and the user needs to
+        see why.
+        """
+        msg = "NO MORE HOSTS LEFT"
+        with self.output_lock:
+            self._display.display(msg, color=C.COLOR_ERROR)
+        self._write_to_log(msg)
+
     def v2_playbook_on_handler_task_start(self, task):
         """A notified handler task is beginning to run.
 

-- 
2.53.0