Skip to content

Commit d325053

Browse files
fix(tempest): Only use credentials of active orgs (#99101)
Since there might be some credentials in the DB of orgs that don't have access ATM we need to check for that.
1 parent 27eadb3 commit d325053

File tree

2 files changed

+46
-3
lines changed

2 files changed

+46
-3
lines changed

src/sentry/tempest/tasks.py

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
from sentry.taskworker.config import TaskworkerConfig
1414
from sentry.taskworker.namespaces import tempest_tasks
1515
from sentry.tempest.models import MessageType, TempestCredentials
16+
from sentry.tempest.utils import has_tempest_access
1617

1718
logger = logging.getLogger(__name__)
1819

@@ -27,7 +28,12 @@
2728
)
2829
def poll_tempest(**kwargs):
2930
# FIXME: Once we have more traffic this needs to be done smarter.
30-
for credentials in TempestCredentials.objects.all():
31+
for credentials in TempestCredentials.objects.select_related("project__organization").all():
32+
# Bruno wants to keeps the customers credentials around so need to
33+
# skip if the credentials are associated with an org that no longer has tempest access.
34+
if not has_tempest_access(credentials.project.organization):
35+
continue
36+
3137
if credentials.latest_fetched_item_id is None:
3238
fetch_latest_item_id.apply_async(
3339
kwargs={"credentials_id": credentials.id},

tests/sentry/tempest/test_tempest.py

Lines changed: 39 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -146,11 +146,13 @@ def test_poll_tempest_crashes_error(self, mock_fetch: MagicMock) -> None:
146146
mock_fetch.assert_called_once()
147147
assert "Fetching the crashes failed." in cm.output[0]
148148

149+
@patch("sentry.tempest.tasks.has_tempest_access")
149150
@patch("sentry.tempest.tasks.fetch_latest_item_id")
150151
@patch("sentry.tempest.tasks.poll_tempest_crashes")
151152
def test_poll_tempest_no_latest_id(
152-
self, mock_poll_crashes: MagicMock, mock_fetch_latest: MagicMock
153+
self, mock_poll_crashes: MagicMock, mock_fetch_latest: MagicMock, mock_has_access: MagicMock
153154
) -> None:
155+
mock_has_access.return_value = True
154156
# Ensure latest_fetched_item_id is None
155157
self.credentials.latest_fetched_item_id = None
156158
self.credentials.save()
@@ -164,11 +166,13 @@ def test_poll_tempest_no_latest_id(
164166
)
165167
mock_poll_crashes.apply_async.assert_not_called()
166168

169+
@patch("sentry.tempest.tasks.has_tempest_access")
167170
@patch("sentry.tempest.tasks.fetch_latest_item_id")
168171
@patch("sentry.tempest.tasks.poll_tempest_crashes")
169172
def test_poll_tempest_with_latest_id(
170-
self, mock_poll_crashes: MagicMock, mock_fetch_latest: MagicMock
173+
self, mock_poll_crashes: MagicMock, mock_fetch_latest: MagicMock, mock_has_access: MagicMock
171174
) -> None:
175+
mock_has_access.return_value = True
172176
# Set an existing ID
173177
self.credentials.latest_fetched_item_id = "42"
174178
self.credentials.save()
@@ -238,3 +242,36 @@ def test_poll_tempest_crashes_invalidates_config(
238242
# Second call -> should reuse existing ProjectKey and thus not invalidate config
239243
poll_tempest_crashes(self.credentials.id)
240244
mock_invalidate.assert_not_called()
245+
246+
@patch("sentry.tempest.tasks.has_tempest_access")
247+
@patch("sentry.tempest.tasks.fetch_latest_item_id")
248+
@patch("sentry.tempest.tasks.poll_tempest_crashes")
249+
def test_poll_tempest_skips_credentials_without_access(
250+
self, mock_poll_crashes: MagicMock, mock_fetch_latest: MagicMock, mock_has_access: MagicMock
251+
) -> None:
252+
"""Test that poll_tempest skips credentials when organization doesn't have tempest access"""
253+
org_with_access = self.create_organization()
254+
project_with_access = self.create_project(organization=org_with_access)
255+
credentials_with_access = self.create_tempest_credentials(project_with_access)
256+
credentials_with_access.latest_fetched_item_id = "42"
257+
credentials_with_access.save()
258+
259+
org_without_access = self.create_organization()
260+
project_without_access = self.create_project(organization=org_without_access)
261+
credentials_without_access = self.create_tempest_credentials(project_without_access)
262+
credentials_without_access.latest_fetched_item_id = "42"
263+
credentials_without_access.save()
264+
265+
def mock_access_check(organization):
266+
return organization.id == org_with_access.id
267+
268+
mock_has_access.side_effect = mock_access_check
269+
270+
poll_tempest()
271+
272+
assert mock_has_access.call_count == 3
273+
mock_poll_crashes.apply_async.assert_called_once_with(
274+
kwargs={"credentials_id": credentials_with_access.id},
275+
headers={"sentry-propagate-traces": False},
276+
)
277+
mock_fetch_latest.apply_async.assert_not_called()

0 commit comments

Comments
 (0)