Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added Register and Un Register commands for topics #502

Merged
merged 3 commits into from
Aug 27, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions CHANGELOG.rst
Original file line number Diff line number Diff line change
@@ -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
Expand Down
112 changes: 111 additions & 1 deletion brewtils/rest/publish_client.py
Original file line number Diff line number Diff line change
Expand Up @@ -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


Expand Down Expand Up @@ -155,3 +155,113 @@ 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 isinstance(cmd, str):
command_name = cmd
else:
if not hasattr(cmd, "_command"):
raise BrewtilsException(
(
"Attempted to register command "
f"{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 isinstance(cmd, str):
command_name = cmd
else:
if not hasattr(cmd, "_command"):
raise BrewtilsException(
(
"Attempted to register command "
f"{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",
),
)
74 changes: 74 additions & 0 deletions test/rest/publish_client_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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)
Expand Down Expand Up @@ -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)
Loading