diff --git a/CHANGELOG.rst b/CHANGELOG.rst index 68642e04..1d2c3ab3 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -5,6 +5,7 @@ Brewtils Changelog ------ TBD +- Expanded Topics Rest API to support Topic Name as a key - Expanded Topic/Subscriber models to include counters - Formalized Status Info model and added helper features to track the history of the status changes. - Added support models for tracking primary replication @@ -14,6 +15,7 @@ TBD - Removed 2.0 Legacy support for Principle and LegacyRole models - Fixed bug in SystemClient to properly assign requester field from parent request + 3.26.4 ------ 7/12/24 diff --git a/brewtils/rest/client.py b/brewtils/rest/client.py index ad7cfacc..8f45eac4 100644 --- a/brewtils/rest/client.py +++ b/brewtils/rest/client.py @@ -161,6 +161,7 @@ def __init__(self, *args, **kwargs): self.admin_url = self.base_url + "api/v1/admin/" self.forward_url = self.base_url + "api/v1/forward" self.topic_url = self.base_url + "api/v1/topics/" + self.topic_name_url = self.base_url + "api/v1/topics/name/" # Deprecated self.logging_config_url = self.base_url + "api/v1/config/logging/" @@ -954,17 +955,23 @@ def get_tokens(self, username=None, password=None): return response @enable_auth - def get_topic(self, topic_id): - # type: (str, **Any) -> Response + def get_topic(self, topic_id=None, topic_name=None): + # type: (str, str, **Any) -> Response """Performs a GET on the Topic URL Args: - topic_id: Topic id + topic_id (Optional[str]): Topic id + topic_name (Optional[str]): Topic name Returns: Requests Response object """ - return self.session.get(self.topic_url + topic_id) + if topic_id: + return self.session.get(self.topic_url + topic_id) + if topic_name: + return self.session.get(self.topic_name_url + topic_name) + + raise RuntimeError("Unable to find Topic ID or Topic Name to Get") @enable_auth def get_topics(self): @@ -992,30 +999,46 @@ def post_topics(self, payload): ) @enable_auth - def patch_topic(self, topic_id, payload): - # type: (str, str) -> Response + def patch_topic(self, topic_id=None, topic_name=None, operations=None): + # type: (str, str, str) -> Response """Performs a PATCH on a Topic URL Args: - topic_id: Topic id - payload: Serialized PatchOperation + topic_id (Optional[str]): Topic id + topic_name (Optional[str]): Topic name + operations: Serialized PatchOperation Returns: Requests Response object """ - return self.session.patch( - self.topic_url + topic_id, data=payload, headers=self.JSON_HEADERS - ) + if topic_id: + return self.session.patch( + self.topic_url + topic_id, data=operations, headers=self.JSON_HEADERS + ) + if topic_name: + return self.session.patch( + self.topic_name_url + topic_name, + data=operations, + headers=self.JSON_HEADERS, + ) + + raise RuntimeError("Unable to find Topic ID or Topic Name to Patch") @enable_auth - def delete_topic(self, topic_id): - # type: (str) -> Response + def delete_topic(self, topic_id=None, topic_name=None): + # type: (str, str) -> Response """Performs a DELETE on a Topic URL Args: - topic_id: Topic id + topic_id (Optional[str]): Topic id + topic_name (Optional[str]): Topic name Returns: Requests Response object """ - return self.session.delete(self.topic_url + topic_id) + if topic_id: + return self.session.delete(self.topic_url + topic_id) + if topic_name: + return self.session.delete(self.topic_name_url + topic_name) + + raise RuntimeError("Unable to find Topic ID or Topic Name to Delete") diff --git a/brewtils/rest/easy_client.py b/brewtils/rest/easy_client.py index 704ec7ed..9c2c5f86 100644 --- a/brewtils/rest/easy_client.py +++ b/brewtils/rest/easy_client.py @@ -1157,17 +1157,18 @@ def _check_chunked_file_validity(self, file_id): return False, metadata_json @wrap_response(parse_method="parse_topic", parse_many=False, default_exc=FetchError) - def get_topic(self, topic_id): + def get_topic(self, topic_id=None, topic_name=None): """Get a topic Args: - topic_id: Topic id + topic_id (Optional[str]): Topic id + topic_name (Optional[str]): Topic name Returns: The Topic """ - return self.client.get_topic(topic_id) + return self.client.get_topic(topic_id=topic_id, topic_name=topic_name) @wrap_response(parse_method="parse_topic", parse_many=True, default_exc=FetchError) def get_topics(self): @@ -1193,11 +1194,12 @@ def create_topic(self, topic): return self.client.post_topics(SchemaParser.serialize_topic(topic)) @wrap_response(return_boolean=True, raise_404=True) - def remove_topic(self, topic_id): + def remove_topic(self, topic_id=None, topic_name=None): """Remove a unique Topic Args: - topic_id: Topic id + topic_id (Optional[str]): Topic id + topic_name (Optional[str]): Topic name Returns: bool: True if removal was successful @@ -1206,14 +1208,15 @@ def remove_topic(self, topic_id): NotFoundError: Couldn't find a Topic matching given parameters """ - return self.client.delete_topic(topic_id) + return self.client.delete_topic(topic_id=topic_id, topic_name=topic_name) @wrap_response(parse_method="parse_topic", parse_many=False, default_exc=SaveError) - def update_topic(self, topic_id, add=None, remove=None): + def update_topic(self, topic_id=None, topic_name=None, add=None, remove=None): """Update a Topic Args: - topic_id (str): The Topic ID + topic_id (Optional[str]): Topic id + topic_name (Optional[str]): Topic name add (Optional[str]): Add subscriber remove (Optional[str]): Remove subscriber @@ -1229,5 +1232,7 @@ def update_topic(self, topic_id, add=None, remove=None): operations.append(PatchOperation("remove", value=remove)) return self.client.patch_topic( - topic_id, SchemaParser.serialize_patch(operations, many=True) + topic_id=topic_id, + topic_name=topic_name, + operations=SchemaParser.serialize_patch(operations, many=True), ) diff --git a/test/rest/client_test.py b/test/rest/client_test.py index 57e267dc..25befa44 100644 --- a/test/rest/client_test.py +++ b/test/rest/client_test.py @@ -473,10 +473,14 @@ def test_client_cert_without_username_password(self, monkeypatch): assert get_tokens_mock.called is True - def test_get_topic(self, client, session_mock): - client.get_topic("id") + def test_get_topic_id(self, client, session_mock): + client.get_topic(topic_id="id") session_mock.get.assert_called_with(client.topic_url + "id") + def test_get_topic_name(self, client, session_mock): + client.get_topic(topic_name="topic_name") + session_mock.get.assert_called_with(client.topic_name_url + "topic_name") + def test_get_topics(self, client, session_mock): client.get_topics() session_mock.get_assert_called_with(client.topic_url, params={}) @@ -487,14 +491,26 @@ def test_post_topics(self, client, session_mock): client.topic_url, data="payload", headers=client.JSON_HEADERS ) - def test_patch_topic(self, client, session_mock): - client.patch_topic("id", "payload") + def test_patch_topic_id(self, client, session_mock): + client.patch_topic(topic_id="id", operations="payload") session_mock.patch.assert_called_with( client.topic_url + "id", data="payload", headers=client.JSON_HEADERS, ) - def test_delete_topic(self, client, session_mock): - client.delete_topic("id") + def test_patch_topic_name(self, client, session_mock): + client.patch_topic(topic_name="topic_name", operations="payload") + session_mock.patch.assert_called_with( + client.topic_name_url + "topic_name", + data="payload", + headers=client.JSON_HEADERS, + ) + + def test_delete_topic_id(self, client, session_mock): + client.delete_topic(topic_id="id") session_mock.delete.assert_called_with(client.topic_url + "id") + + def test_delete_topic_name(self, client, session_mock): + client.delete_topic(topic_name="topic_name") + session_mock.delete.assert_called_with(client.topic_name_url + "topic_name")