Skip to content

Commit

Permalink
Merge branch '3.27.0_staged' into file-trigger
Browse files Browse the repository at this point in the history
  • Loading branch information
TheBurchLog committed Aug 12, 2024
2 parents fb9a129 + d6b7971 commit e53cdcb
Show file tree
Hide file tree
Showing 8 changed files with 101 additions and 36 deletions.
3 changes: 3 additions & 0 deletions CHANGELOG.rst
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ 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
- New Models for User, UserToken, Role, and AliasUserMap
Expand All @@ -13,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
Expand Down
13 changes: 10 additions & 3 deletions brewtils/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -1851,6 +1851,7 @@ def __init__(
instance=None,
command=None,
subscriber_type=None,
consumer_count=0,
):
self.garden = garden
self.namespace = namespace
Expand All @@ -1859,14 +1860,15 @@ def __init__(
self.instance = instance
self.command = command
self.subscriber_type = subscriber_type or "DYNAMIC"
self.consumer_count = consumer_count

def __str__(self):
return "%s" % self.__dict__

def __repr__(self):
return (
"<Subscriber: garden=%s, namespace=%s, system=%s, version=%s, instance=%s, "
"command=%s, subscriber_type=%s>"
"command=%s, subscriber_type=%s, consumer_count=%s>"
% (
self.garden,
self.namespace,
Expand All @@ -1875,6 +1877,7 @@ def __repr__(self):
self.instance,
self.command,
self.subscriber_type,
self.consumer_count,
)
)

Expand All @@ -1897,18 +1900,22 @@ def __eq__(self, other):
class Topic(BaseModel):
schema = "TopicSchema"

def __init__(self, id=None, name=None, subscribers=None): # noqa # shadows built-in
def __init__(
self, id=None, name=None, subscribers=None, publisher_count=0
): # noqa # shadows built-in
self.id = id
self.name = name
self.subscribers = subscribers or []
self.publisher_count = publisher_count

def __str__(self):
return "%s: %s" % (self.name, [str(s) for s in self.subscribers])

def __repr__(self):
return "<Topic: name=%s, subscribers=%s>" % (
return "<Topic: name=%s, subscribers=%s, publisher_count=%s>" % (
self.name,
self.subscribers,
self.publisher_count,
)


Expand Down
53 changes: 38 additions & 15 deletions brewtils/rest/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -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/"
Expand Down Expand Up @@ -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):
Expand Down Expand Up @@ -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")
23 changes: 14 additions & 9 deletions brewtils/rest/easy_client.py
Original file line number Diff line number Diff line change
Expand Up @@ -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):
Expand All @@ -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
Expand All @@ -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
Expand All @@ -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),
)
2 changes: 2 additions & 0 deletions brewtils/schemas.py
Original file line number Diff line number Diff line change
Expand Up @@ -604,12 +604,14 @@ class SubscriberSchema(BaseSchema):
instance = fields.Str(allow_none=True)
command = fields.Str(allow_none=True)
subscriber_type = fields.Str(allow_none=True)
consumer_count = fields.Int(allow_none=True)


class TopicSchema(BaseSchema):
id = fields.Str(allow_none=True)
name = fields.Str(allow_none=True)
subscribers = fields.List(fields.Nested(SubscriberSchema, allow_none=True))
publisher_count = fields.Int(allow_none=True)


class ReplicationSchema(BaseSchema):
Expand Down
8 changes: 7 additions & 1 deletion brewtils/test/fixtures.py
Original file line number Diff line number Diff line change
Expand Up @@ -1092,6 +1092,7 @@ def subscriber_dict():
"instance": "inst",
"command": "run",
"subscriber_type": "DYNAMIC",
"consumer_count": 10,
}


Expand All @@ -1103,7 +1104,12 @@ def bg_subscriber(subscriber_dict):
@pytest.fixture
def topic_dict(subscriber_dict):
"""Topic as dict"""
return {"id": "5d174df1", "name": "foo", "subscribers": [subscriber_dict]}
return {
"id": "5d174df1",
"name": "foo",
"subscribers": [subscriber_dict],
"publisher_count": 10,
}


@pytest.fixture
Expand Down
7 changes: 5 additions & 2 deletions test/models_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -718,7 +718,7 @@ def subscriber1():

@pytest.fixture
def topic1(subscriber1):
return Topic(name="foo.*", subscribers=[subscriber1])
return Topic(name="foo.*", subscribers=[subscriber1], publisher_count=10)


class TestSubscriber(object):
Expand All @@ -739,9 +739,12 @@ def test_str(self, topic1, subscriber1):
assert str(topic1) == "%s: %s" % (topic1.name, [str(subscriber1)])

def test_repr(self, topic1, subscriber1):
assert repr(topic1) == "<Topic: name=%s, subscribers=%s>" % (
assert repr(
topic1
) == "<Topic: name=%s, subscribers=%s, publisher_count=%s>" % (
topic1.name,
[subscriber1],
topic1.publisher_count,
)


Expand Down
28 changes: 22 additions & 6 deletions test/rest/client_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -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={})
Expand All @@ -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")

0 comments on commit e53cdcb

Please sign in to comment.