Skip to content
Open
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
18 changes: 8 additions & 10 deletions lib/group_repository.py
Original file line number Diff line number Diff line change
Expand Up @@ -576,27 +576,25 @@ def get_ungrouped_group(identity: Identity) -> Group:
return ungrouped_group


def serialize_group(group: Group | dict, org_id: str, account: str | None = None) -> dict:
def serialize_group(
group: Group | dict, org_id: str, account: str | None = None, *, with_host_count: bool = True
) -> dict:
"""
Serialize a group with host count.
Serialize a group, optionally including host count.
Delegates to the appropriate serializer based on whether the group is from the database or RBAC v2.

Args:
group: Either a Group ORM object (from DB) or a dict (from RBAC v2)
org_id: The organization ID
account: The account_number (optional, only used for RBAC v2 workspaces)

Returns:
Dictionary containing serialized group data with host_count
with_host_count: When False, skip the host count query (used during MQ ingestion
where an accurate count is not needed and the query is expensive).
"""
if isinstance(group, dict):
# RBAC v2 workspace (dict from RBAC API)
# Extract group_id from dict and get host count using batch function
group_id = group["id"]
host_count = get_host_counts_batch(org_id, [group_id])[group_id]
host_count = get_host_counts_batch(org_id, [group_id])[group_id] if with_host_count else 0
return serialize_rbac_workspace_with_host_count(group, org_id, account, host_count)
else:
# Database Group (ORM object)
group_id = str(group.id)
host_count = get_host_counts_batch(org_id, [group_id])[group_id]
host_count = get_host_counts_batch(org_id, [group_id])[group_id] if with_host_count else 0
return serialize_db_group_with_host_count(group, host_count)
4 changes: 3 additions & 1 deletion lib/host_repository.py
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,9 @@ def add_host(
matched_host = find_existing_host(identity, canonical_facts)

group = get_or_create_ungrouped_hosts_group_for_identity(identity)
input_host.groups = [serialize_group(group, identity.org_id, getattr(identity, "account_number", None))]
input_host.groups = [
serialize_group(group, identity.org_id, getattr(identity, "account_number", None), with_host_count=False)
]

if matched_host:
defer_to_reporter = operation_args.get("defer_to_reporter")
Expand Down
43 changes: 43 additions & 0 deletions tests/test_models.py
Original file line number Diff line number Diff line change
Expand Up @@ -2838,3 +2838,46 @@ def test_update_display_name_writes_when_reporter_changed(db_create_host, models

assert existing_host.display_name == "my-host"
assert existing_host.display_name_reporter == "yupana"


def test_serialize_group_with_host_count_false(flask_app, mocker): # noqa: ARG001
"""serialize_group(with_host_count=False) should skip the host count query."""
from lib.group_repository import serialize_group

mock_group = mocker.Mock()
mock_group.id = "test-group-id"
mock_group.name = "Test Group"
mock_group.org_id = "test_org"

count_spy = mocker.patch("lib.group_repository.get_host_counts_batch")
Comment on lines +2843 to +2852
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

suggestion (testing): Add coverage for the RBAC workspace (dict) branch of serialize_group.

These tests only cover the DB/ORM Group path of serialize_group. Please also add tests for the RBAC v2 workspace (dict) path that:

  1. Call serialize_group with a dict and with_host_count=False, asserting get_host_counts_batch is not called and serialize_rbac_workspace_with_host_count receives host_count=0.
  2. Call serialize_group with a dict and with_host_count=True (or default), asserting get_host_counts_batch is called once with the expected arguments and that the returned host_count is included in the serialized result.

This will ensure both code paths behave consistently and the host-count optimization applies to RBAC workspaces as well.

mocker.patch(
"lib.group_repository.serialize_db_group_with_host_count",
return_value={"id": "test-group-id", "name": "Test Group", "host_count": 0},
)

result = serialize_group(mock_group, "test_org", with_host_count=False)

count_spy.assert_not_called()
assert result["host_count"] == 0


def test_serialize_group_with_host_count_true(flask_app, mocker): # noqa: ARG001
"""serialize_group(with_host_count=True) should query for host count (default behavior)."""
from lib.group_repository import serialize_group

mock_group = mocker.Mock()
mock_group.id = "test-group-id"

count_spy = mocker.patch(
"lib.group_repository.get_host_counts_batch",
return_value={"test-group-id": 42},
)
mocker.patch(
"lib.group_repository.serialize_db_group_with_host_count",
return_value={"id": "test-group-id", "host_count": 42},
)

result = serialize_group(mock_group, "test_org")

count_spy.assert_called_once()
assert result["host_count"] == 42
Loading