From a3d2d56d428cc2fe80db9ea6259fc6f422251d5b Mon Sep 17 00:00:00 2001 From: TheBurchLog <5104941+TheBurchLog@users.noreply.github.com> Date: Tue, 27 Aug 2024 11:55:47 -0400 Subject: [PATCH 1/3] Added Register and Un Register commands for topics --- CHANGELOG.rst | 6 ++ brewtils/rest/publish_client.py | 96 +++++++++++++++++++++++++++++++- test/rest/publish_client_test.py | 74 ++++++++++++++++++++++++ 3 files changed, 175 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.rst b/CHANGELOG.rst index 97f91504..a1d4b1bd 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -1,6 +1,12 @@ Brewtils Changelog ================== +3.27.2 +------ +TBD + +- Expanded PublishClient to support Registering and Unregistering commands to Topics after a plugin has been initialized + 3.27.1 ------ 8/21/24 diff --git a/brewtils/rest/publish_client.py b/brewtils/rest/publish_client.py index 859652e6..f0327761 100644 --- a/brewtils/rest/publish_client.py +++ b/brewtils/rest/publish_client.py @@ -3,7 +3,7 @@ import brewtils.plugin from brewtils.errors import BrewtilsException -from brewtils.models import Event, Events, Request +from brewtils.models import Event, Events, Request, Subscriber, Topic from brewtils.rest.easy_client import EasyClient @@ -155,3 +155,97 @@ def _get_parent_for_request(self): return None return Request(id=str(parent.id)) + + def register_command(self, topic: str, cmd) -> Topic: + """Register a command to subscribe to the topic provided. The subscriber is marked as GENERATED, and will be + pruned after the system shuts down + + Args: + topic (str): Topic for the command to subscribe to + cmd (str, function): Command to register + + Raises: + BrewtilsException: If function is provided, it must be an annotated function. Only supports running plugins + + Returns: + Topic: Updated Topic Model + """ + + if not ( + brewtils.plugin.CONFIG.garden + and brewtils.plugin.CONFIG.name + and brewtils.plugin.CONFIG.version + and brewtils.plugin.CONFIG.instance_name + and brewtils.plugin.CONFIG.namespace + ): + raise BrewtilsException( + "Unable to identify Configuration for Plugin, only running Plugins can register commands" + ) + + if type(cmd) == str: + command_name = cmd + else: + if not hasattr(cmd, "_command"): + raise BrewtilsException( + f"Attempted to register command {getattr(cmd, '__name__', 'MISSING FUNC NAME')} that is not an annotated command" + ) + command_name = cmd._command.name + + return self._easy_client.update_topic( + topic_name=topic, + add=Subscriber( + garden=brewtils.plugin.CONFIG.garden, + namespace=brewtils.plugin.CONFIG.namespace, + system=brewtils.plugin.CONFIG.name, + version=brewtils.plugin.CONFIG.version, + instance=brewtils.plugin.CONFIG.instance_name, + command=command_name, + subscriber_type="GENERATED", + ), + ) + + def unregister_command(self, topic: str, cmd) -> Topic: + """Unregister a command to subscribe to the topic provided. + + Args: + topic (str): Topic for the command to subscribe to + cmd (str, function): Command to unregister + + Raises: + BrewtilsException: If function is provided, it must be an annotated function. Only supports running plugins + + Returns: + Topic: Updated Topic Model + """ + if not ( + brewtils.plugin.CONFIG.garden + and brewtils.plugin.CONFIG.name + and brewtils.plugin.CONFIG.version + and brewtils.plugin.CONFIG.instance_name + and brewtils.plugin.CONFIG.namespace + ): + raise BrewtilsException( + "Unable to identify Configuration for Plugin, only running Plugins can unregister commands" + ) + + if type(cmd) == str: + command_name = cmd + else: + if not hasattr(cmd, "_command"): + raise BrewtilsException( + f"Attempted to register command {getattr(cmd, '__name__', 'MISSING FUNC NAME')} that is not an annotated command" + ) + command_name = cmd._command.name + + return self._easy_client.update_topic( + topic_name=topic, + remove=Subscriber( + garden=brewtils.plugin.CONFIG.garden, + namespace=brewtils.plugin.CONFIG.namespace, + system=brewtils.plugin.CONFIG.name, + version=brewtils.plugin.CONFIG.version, + instance=brewtils.plugin.CONFIG.instance_name, + command=command_name, + subscriber_type="GENERATED", + ), + ) diff --git a/test/rest/publish_client_test.py b/test/rest/publish_client_test.py index 13ecc2d3..1308f1c5 100644 --- a/test/rest/publish_client_test.py +++ b/test/rest/publish_client_test.py @@ -2,6 +2,7 @@ from mock import Mock import brewtils.rest +from brewtils.decorators import command from brewtils.errors import BrewtilsException from brewtils.models import Event, Events, Request, System from brewtils.rest.publish_client import PublishClient @@ -12,6 +13,7 @@ def easy_client(monkeypatch): mock = Mock(name="easy_client") mock.publish_event.return_value = True + mock.update_topic.return_value = True monkeypatch.setattr( brewtils.rest.publish_client, "EasyClient", Mock(return_value=mock) @@ -93,3 +95,75 @@ def test_verify_generated_request(self, client, easy_client): assert SchemaParser.serialize_event( called_event ) == SchemaParser.serialize_event(event) + + def test_register_command(self, client, easy_client): + self.setup_config() + + @command + def _cmd(self, x): + return x + + client.register_command("topic", _cmd) + + easy_client.update_topic.assert_called() + + def test_register_command_string(self, client, easy_client): + self.setup_config() + + client.register_command("topic", "command") + + easy_client.update_topic.assert_called() + + def test_unregister_command(self, client, easy_client): + self.setup_config() + + @command + def _cmd(self, x): + return x + + client.unregister_command("topic", _cmd) + + easy_client.update_topic.assert_called() + + def test_unregister_command_string(self, client, easy_client): + self.setup_config() + + client.unregister_command("topic", "command") + + easy_client.update_topic.assert_called() + + def test_register_command_non_annotated(self, client): + self.setup_config() + + def _cmd(self, x): + return x + + with pytest.raises(BrewtilsException): + client.register_command("topic", _cmd) + + def test_unregister_command_non_annotated(self, client): + self.setup_config() + + def _cmd(self, x): + return x + + with pytest.raises(BrewtilsException): + client.unregister_command("topic", _cmd) + + def test_register_command_no_config(self, client): + + @command + def _cmd(self, x): + return x + + with pytest.raises(BrewtilsException): + client.register_command("topic", _cmd) + + def test_unregister_command_no_config(self, client): + + @command + def _cmd(self, x): + return x + + with pytest.raises(BrewtilsException): + client.unregister_command("topic", _cmd) From 62b234d2fa9afccb683a959b2ae7d04427eceff9 Mon Sep 17 00:00:00 2001 From: TheBurchLog <5104941+TheBurchLog@users.noreply.github.com> Date: Tue, 27 Aug 2024 12:05:13 -0400 Subject: [PATCH 2/3] formatting --- brewtils/rest/publish_client.py | 34 +++++++++++++++++++++++---------- 1 file changed, 24 insertions(+), 10 deletions(-) diff --git a/brewtils/rest/publish_client.py b/brewtils/rest/publish_client.py index f0327761..4e32932b 100644 --- a/brewtils/rest/publish_client.py +++ b/brewtils/rest/publish_client.py @@ -157,15 +157,16 @@ def _get_parent_for_request(self): return Request(id=str(parent.id)) def register_command(self, topic: str, cmd) -> Topic: - """Register a command to subscribe to the topic provided. The subscriber is marked as GENERATED, and will be - pruned after the system shuts down + """Register a command to subscribe to the topic provided. The subscriber is + marked as GENERATED, and will be pruned after the system shuts down Args: topic (str): Topic for the command to subscribe to cmd (str, function): Command to register Raises: - BrewtilsException: If function is provided, it must be an annotated function. Only supports running plugins + BrewtilsException: If function is provided, it must be an annotated + function. Only supports running plugins Returns: Topic: Updated Topic Model @@ -179,15 +180,21 @@ def register_command(self, topic: str, cmd) -> Topic: and brewtils.plugin.CONFIG.namespace ): raise BrewtilsException( - "Unable to identify Configuration for Plugin, only running Plugins can register commands" + ( + "Unable to identify Configuration for Plugin, " + "only running Plugins can register commands" + ) ) - if type(cmd) == str: + if isinstance(cmd, str): command_name = cmd else: if not hasattr(cmd, "_command"): raise BrewtilsException( - f"Attempted to register command {getattr(cmd, '__name__', 'MISSING FUNC NAME')} that is not an annotated command" + ( + f"Attempted to register command {getattr(cmd, '__name__', 'MISSING FUNC NAME')} " + "that is not an annotated command" + ) ) command_name = cmd._command.name @@ -212,7 +219,8 @@ def unregister_command(self, topic: str, cmd) -> Topic: cmd (str, function): Command to unregister Raises: - BrewtilsException: If function is provided, it must be an annotated function. Only supports running plugins + BrewtilsException: If function is provided, it must be + an annotated function. Only supports running plugins Returns: Topic: Updated Topic Model @@ -225,15 +233,21 @@ def unregister_command(self, topic: str, cmd) -> Topic: and brewtils.plugin.CONFIG.namespace ): raise BrewtilsException( - "Unable to identify Configuration for Plugin, only running Plugins can unregister commands" + ( + "Unable to identify Configuration for Plugin, only " + "running Plugins can unregister commands" + ) ) - if type(cmd) == str: + if isinstance(cmd, str): command_name = cmd else: if not hasattr(cmd, "_command"): raise BrewtilsException( - f"Attempted to register command {getattr(cmd, '__name__', 'MISSING FUNC NAME')} that is not an annotated command" + ( + f"Attempted to register command {getattr(cmd, '__name__', 'MISSING FUNC NAME')} " + "that is not an annotated command" + ) ) command_name = cmd._command.name From 268f0116881256db4dd9e55d9d753e6181508469 Mon Sep 17 00:00:00 2001 From: TheBurchLog <5104941+TheBurchLog@users.noreply.github.com> Date: Tue, 27 Aug 2024 12:06:31 -0400 Subject: [PATCH 3/3] formatting --- brewtils/rest/publish_client.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/brewtils/rest/publish_client.py b/brewtils/rest/publish_client.py index 4e32932b..2c44eb9d 100644 --- a/brewtils/rest/publish_client.py +++ b/brewtils/rest/publish_client.py @@ -192,7 +192,8 @@ def register_command(self, topic: str, cmd) -> Topic: if not hasattr(cmd, "_command"): raise BrewtilsException( ( - f"Attempted to register command {getattr(cmd, '__name__', 'MISSING FUNC NAME')} " + "Attempted to register command " + f"{getattr(cmd, '__name__', 'MISSING FUNC NAME')} " "that is not an annotated command" ) ) @@ -245,7 +246,8 @@ def unregister_command(self, topic: str, cmd) -> Topic: if not hasattr(cmd, "_command"): raise BrewtilsException( ( - f"Attempted to register command {getattr(cmd, '__name__', 'MISSING FUNC NAME')} " + "Attempted to register command " + f"{getattr(cmd, '__name__', 'MISSING FUNC NAME')} " "that is not an annotated command" ) )