]> git.ipfire.org Git - thirdparty/knot-resolver.git/commitdiff
fixup! controller: dispatcher to inject notify feature to supervisord docs-python-refac-o5rd0i/deployments/9525 python-refactoring-controller
authorAleš Mrázek <ales.mrazek@nic.cz>
Mon, 13 Jul 2026 09:37:54 +0000 (11:37 +0200)
committerAleš Mrázek <ales.mrazek@nic.cz>
Mon, 13 Jul 2026 09:37:54 +0000 (11:37 +0200)
python/knot_resolver/controller/notify/notify_dispatcher.py
tests/python/knot_resolver/controller/notify/test_notify_dispatcher.py [new file with mode: 0644]

index 5e701645cb90bbde785b761ece2b21418ed23d79..be670da34c73abc35a53f96b71fd4bae15f8d7a9 100644 (file)
@@ -121,7 +121,7 @@ if NOTIFY_SUPPORT:
 
             if not is_subprocess_x_type_notify(subprocess):
                 self._logger.warning(
-                    "ignoring notify message '%s' from %s, that is not configured to send it",
+                    "ignoring notify message %s from %s, that is not configured to send it",
                     data,
                     subprocess.config.name,
                 )
@@ -140,8 +140,8 @@ if NOTIFY_SUPPORT:
                     subprocess.config.name,
                 )
             else:
-                self._logger.warn(
-                    "ignoring unrecognized data on $NOTIFY_SOCKET sent from '%s', PID=%d, data='%b'",
+                self._logger.warning(
+                    "ignoring unrecognized data on $NOTIFY_SOCKET sent from '%s', PID=%d, data=%s",
                     subprocess.config.name,
                     pid,
                     data,
diff --git a/tests/python/knot_resolver/controller/notify/test_notify_dispatcher.py b/tests/python/knot_resolver/controller/notify/test_notify_dispatcher.py
new file mode 100644 (file)
index 0000000..113ec1a
--- /dev/null
@@ -0,0 +1,100 @@
+import logging
+import os
+from types import SimpleNamespace
+from unittest.mock import MagicMock, Mock
+
+from supervisor.events import ProcessStateStartingEvent, ProcessStateStoppingEvent
+from supervisor.process import Subprocess
+from supervisor.supervisord import Supervisor
+
+from knot_resolver.controller.config import X_TYPE_NOTIFY, X_TYPE_VAR_NAME
+from knot_resolver.controller.notify.notify_dispatcher import NotifyDispatcher, NotifyPlugin
+from knot_resolver.controller.notify.notify_socket import send_notify_message
+
+
+def test_notify_plugin() -> None:
+    plugin = NotifyPlugin()
+    assert plugin.starting_subprocesses == {}
+
+    fake_pid1 = 123
+    subprocess1 = MagicMock(spec=Subprocess)
+    subprocess1.pid = fake_pid1
+
+    starting_event1 = MagicMock(spec=ProcessStateStartingEvent)
+    starting_event1.process = subprocess1
+
+    plugin.track_starting_subprocesses(starting_event1)
+    assert fake_pid1 in plugin.starting_subprocesses
+
+    fake_pid2 = 321
+    subprocess2 = MagicMock(spec=Subprocess)
+    subprocess2.pid = fake_pid2
+
+    starting_event2 = MagicMock(spec=ProcessStateStartingEvent)
+    starting_event2.process = subprocess2
+
+    plugin.track_starting_subprocesses(starting_event2)
+    assert fake_pid2 in plugin.starting_subprocesses
+
+    stopping_event = MagicMock(spec=ProcessStateStoppingEvent)
+    stopping_event.process = subprocess1
+
+    plugin.track_starting_subprocesses(stopping_event)
+    assert fake_pid1 not in plugin.starting_subprocesses
+    assert fake_pid2 in plugin.starting_subprocesses
+
+
+def test_notify_dispatcher(caplog) -> None:
+    plugin = NotifyPlugin()
+
+    supervisor = MagicMock(spec=Supervisor)
+    supervisor.options = Mock()
+    supervisor.options.logger = logging.getLogger(__name__)
+
+    subprocess = MagicMock(spec=Subprocess)
+    subprocess.pid = os.getpid()
+
+    dispatcher = NotifyDispatcher(supervisor, plugin)
+
+    caplog.clear()
+    with caplog.at_level(logging.INFO):
+        send_notify_message(READY=1)
+        dispatcher.handle_read_event()
+    assert any("ignoring notify message from unregistered subprocess" in record.message for record in caplog.records)
+
+    starting_event = MagicMock(spec=ProcessStateStartingEvent)
+    starting_event.process = subprocess
+    plugin.track_starting_subprocesses(starting_event)
+
+    caplog.clear()
+    with caplog.at_level(logging.INFO):
+        send_notify_message(READY=1)
+        dispatcher.handle_read_event()
+    assert any("that is not configured to send it" in record.message for record in caplog.records)
+
+    subprocess.config = SimpleNamespace(
+        name="subprocess",
+        environment={
+            X_TYPE_VAR_NAME: X_TYPE_NOTIFY,
+        },
+    )
+
+    caplog.clear()
+    with caplog.at_level(logging.INFO):
+        send_notify_message(READY=1)
+        dispatcher.handle_read_event()
+    assert any("received READY notify message" in record.message for record in caplog.records)
+
+    caplog.clear()
+    with caplog.at_level(logging.INFO):
+        send_notify_message(STOPPING=1)
+        dispatcher.handle_read_event()
+    assert any("received STOPPING notify message" in record.message for record in caplog.records)
+
+    caplog.clear()
+    with caplog.at_level(logging.INFO):
+        send_notify_message(UNRECOGNIZED=1)
+        dispatcher.handle_read_event()
+    assert any("ignoring unrecognized data on $NOTIFY_SOCKET" in record.message for record in caplog.records)
+
+    dispatcher.close()