Browse Source

ref(HC): Update silo annotations in testutils methods (#52389)

Gabe Villalobos 1 year ago
parent
commit
7d28c2b21a

+ 11 - 8
src/sentry/receivers/releases.py

@@ -7,6 +7,7 @@ from django.db.models.signals import post_save, pre_save
 from django.utils import timezone
 
 from sentry import analytics
+from sentry.db.postgres.transactions import in_test_hide_transaction_boundary
 from sentry.models import (
     Activity,
     Commit,
@@ -95,7 +96,8 @@ def resolved_in_commit(instance, created, **kwargs):
         repo = None
 
     if instance.author:
-        user_list = list(instance.author.find_users())
+        with in_test_hide_transaction_boundary():
+            user_list = list(instance.author.find_users())
     else:
         user_list = ()
 
@@ -104,13 +106,14 @@ def resolved_in_commit(instance, created, **kwargs):
     self_assign_issue: str = "0"
     if user_list:
         acting_user = user_list[0]
-        self_assign_issue = get_option_from_list(
-            user_option_service.get_many(
-                filter={"user_ids": [acting_user.id], "keys": ["self_assign_issue"]}
-            ),
-            key="self_assign_issue",
-            default="0",
-        )
+        with in_test_hide_transaction_boundary():
+            self_assign_issue = get_option_from_list(
+                user_option_service.get_many(
+                    filter={"user_ids": [acting_user.id], "keys": ["self_assign_issue"]}
+                ),
+                key="self_assign_issue",
+                default="0",
+            )
 
     for group in groups:
         try:

+ 2 - 1
src/sentry/sentry_apps/apps.py

@@ -15,6 +15,7 @@ from sentry_sdk.api import push_scope
 from sentry import analytics, audit_log
 from sentry.constants import SentryAppStatus
 from sentry.coreapi import APIError
+from sentry.db.postgres.transactions import in_test_hide_transaction_boundary
 from sentry.models import (
     ApiApplication,
     ApiToken,
@@ -273,7 +274,7 @@ class SentryAppCreator:
             ), "Internal apps should not require installation verification"
 
     def run(self, *, user: User, request: Request | None = None) -> SentryApp:
-        with transaction.atomic():
+        with transaction.atomic(), in_test_hide_transaction_boundary():
             slug = self._generate_and_validate_slug()
             proxy = self._create_proxy_user(slug=slug)
             api_app = self._create_api_application(proxy=proxy)

+ 6 - 5
src/sentry/testutils/cases.py

@@ -137,6 +137,7 @@ from sentry.search.events.constants import (
     SPAN_METRICS_MAP,
 )
 from sentry.sentry_metrics import indexer
+from sentry.silo import SiloMode
 from sentry.snuba.metrics.datasource import get_series
 from sentry.tagstore.snuba import SnubaTagStorage
 from sentry.testutils.factories import get_fixture_path
@@ -167,7 +168,7 @@ from . import assert_status_code
 from .factories import Factories
 from .fixtures import Fixtures
 from .helpers import AuthProvider, Feature, TaskRunner, override_options, parse_queries
-from .silo import exempt_from_silo_limits
+from .silo import assume_test_silo_mode
 from .skips import requires_snuba
 
 DEFAULT_USER_AGENT = "Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/41.0.2228.0 Safari/537.36"
@@ -279,13 +280,13 @@ class BaseTestCase(Fixtures):
         self, user, organization_id=None, organization_ids=None, superuser=False, superuser_sso=True
     ):
         if isinstance(user, OrganizationMember):
-            with exempt_from_silo_limits():
+            with assume_test_silo_mode(SiloMode.CONTROL):
                 user = User.objects.get(id=user.user_id)
 
         user.backend = settings.AUTHENTICATION_BACKENDS[0]
 
         request = self.make_request()
-        with exempt_from_silo_limits():
+        with override_settings(SILO_MODE=SiloMode.MONOLITH):
             login(request, user)
         request.user = user
 
@@ -1001,7 +1002,7 @@ class IntegrationTestCase(TestCase):
         super().setUp()
 
         self.organization = self.create_organization(name="foo", owner=self.user)
-        with exempt_from_silo_limits():
+        with assume_test_silo_mode(SiloMode.REGION):
             rpc_organization = serialize_rpc_organization(self.organization)
 
         self.login_as(self.user)
@@ -1972,7 +1973,7 @@ class IntegrationRepositoryTestCase(APITestCase):
     def add_create_repository_responses(self, repository_config):
         raise NotImplementedError(f"implement for {type(self).__module__}.{type(self).__name__}")
 
-    @exempt_from_silo_limits()
+    @assume_test_silo_mode(SiloMode.MONOLITH)
     def create_repository(
         self, repository_config, integration_id, organization_slug=None, add_responses=True
     ):

+ 96 - 93
src/sentry/testutils/factories.py

@@ -21,7 +21,7 @@ from django.utils.encoding import force_str
 from django.utils.text import slugify
 
 from sentry.constants import SentryAppInstallationStatus, SentryAppStatus
-from sentry.db.postgres.roles import in_test_psql_role_override
+from sentry.db.postgres.transactions import in_test_hide_transaction_boundary
 from sentry.event_manager import EventManager
 from sentry.incidents.logic import (
     create_alert_rule,
@@ -107,8 +107,9 @@ from sentry.sentry_apps.apps import SentryAppCreator
 from sentry.services.hybrid_cloud.app.serial import serialize_sentry_app_installation
 from sentry.services.hybrid_cloud.hook import hook_service
 from sentry.signals import project_created
+from sentry.silo import SiloMode
 from sentry.snuba.dataset import Dataset
-from sentry.testutils.silo import exempt_from_silo_limits
+from sentry.testutils.silo import assume_test_silo_mode
 from sentry.types.activity import ActivityType
 from sentry.types.integrations import ExternalProviders
 from sentry.utils import json, loremipsum
@@ -260,7 +261,7 @@ def _patch_artifact_manifest(path, org=None, release=None, project=None, extra_f
 # TODO(dcramer): consider moving to something more scalable like factoryboy
 class Factories:
     @staticmethod
-    @exempt_from_silo_limits()
+    @assume_test_silo_mode(SiloMode.REGION)
     def create_organization(name=None, owner=None, **kwargs):
         if not name:
             name = petname.generate(2, " ", letters=10).title()
@@ -272,7 +273,7 @@ class Factories:
         return org
 
     @staticmethod
-    @exempt_from_silo_limits()
+    @assume_test_silo_mode(SiloMode.CONTROL)
     def create_org_mapping(org=None, **kwds):
         if org:
             kwds.setdefault("organization_id", org.id)
@@ -283,8 +284,7 @@ class Factories:
         return OrganizationMapping.objects.create(**kwds)
 
     @staticmethod
-    @exempt_from_silo_limits()
-    @in_test_psql_role_override("postgres")
+    @assume_test_silo_mode(SiloMode.REGION)
     def create_member(teams=None, team_roles=None, **kwargs):
         kwargs.setdefault("role", "member")
         teamRole = kwargs.pop("teamRole", None)
@@ -314,7 +314,7 @@ class Factories:
         return om
 
     @staticmethod
-    @exempt_from_silo_limits()
+    @assume_test_silo_mode(SiloMode.REGION)
     def create_team_membership(team, member=None, user=None, role=None):
         if member is None:
             member, created = OrganizationMember.objects.get_or_create(
@@ -328,14 +328,14 @@ class Factories:
         )
 
     @staticmethod
-    @exempt_from_silo_limits()
+    @assume_test_silo_mode(SiloMode.CONTROL)
     def create_api_key(organization, scope_list=None, **kwargs):
         return ApiKey.objects.create(
             organization_id=organization.id if organization else None, scope_list=scope_list
         )
 
     @staticmethod
-    @exempt_from_silo_limits()
+    @assume_test_silo_mode(SiloMode.REGION)
     def create_team(organization, **kwargs):
         if not kwargs.get("name"):
             kwargs["name"] = petname.generate(2, " ", letters=10).title()
@@ -350,7 +350,7 @@ class Factories:
         return team
 
     @staticmethod
-    @exempt_from_silo_limits()
+    @assume_test_silo_mode(SiloMode.REGION)
     def create_environment(project, **kwargs):
         name = kwargs.get("name", petname.generate(3, " ", letters=10)[:64])
 
@@ -362,7 +362,7 @@ class Factories:
         return env
 
     @staticmethod
-    @exempt_from_silo_limits()
+    @assume_test_silo_mode(SiloMode.REGION)
     def create_project(organization=None, teams=None, fire_project_created=False, **kwargs):
         if not kwargs.get("name"):
             kwargs["name"] = petname.generate(2, " ", letters=10).title()
@@ -377,18 +377,19 @@ class Factories:
                 for team in teams:
                     project.add_team(team)
             if fire_project_created:
-                project_created.send(
-                    project=project, user=AnonymousUser(), default_rules=True, sender=Factories
-                )
+                with in_test_hide_transaction_boundary():
+                    project_created.send(
+                        project=project, user=AnonymousUser(), default_rules=True, sender=Factories
+                    )
         return project
 
     @staticmethod
-    @exempt_from_silo_limits()
+    @assume_test_silo_mode(SiloMode.REGION)
     def create_project_bookmark(project, user):
         return ProjectBookmark.objects.create(project_id=project.id, user_id=user.id)
 
     @staticmethod
-    @exempt_from_silo_limits()
+    @assume_test_silo_mode(SiloMode.REGION)
     def create_project_rule(project, action_data=None, condition_data=None):
         action_data = action_data or [
             {
@@ -417,7 +418,7 @@ class Factories:
         )
 
     @staticmethod
-    @exempt_from_silo_limits()
+    @assume_test_silo_mode(SiloMode.REGION)
     def create_slack_project_rule(project, integration_id, channel_id=None, channel_name=None):
         action_data = [
             {
@@ -431,12 +432,12 @@ class Factories:
         return Factories.create_project_rule(project, action_data)
 
     @staticmethod
-    @exempt_from_silo_limits()
+    @assume_test_silo_mode(SiloMode.REGION)
     def create_project_key(project):
         return project.key_set.get_or_create()[0]
 
     @staticmethod
-    @exempt_from_silo_limits()
+    @assume_test_silo_mode(SiloMode.REGION)
     def create_release(
         project: Project,
         user: Optional[User] = None,
@@ -507,7 +508,7 @@ class Factories:
         return release
 
     @staticmethod
-    @exempt_from_silo_limits()
+    @assume_test_silo_mode(SiloMode.REGION)
     def create_release_file(release_id, file=None, name=None, dist_id=None):
         if file is None:
             file = Factories.create_file(
@@ -531,7 +532,7 @@ class Factories:
         )
 
     @staticmethod
-    @exempt_from_silo_limits()
+    @assume_test_silo_mode(SiloMode.REGION)
     def create_artifact_bundle_zip(
         org=None, release=None, project=None, extra_files=None, fixture_path="artifact_bundle"
     ):
@@ -557,7 +558,7 @@ class Factories:
         return bundle.getvalue()
 
     @classmethod
-    @exempt_from_silo_limits()
+    @assume_test_silo_mode(SiloMode.REGION)
     def create_release_archive(cls, org, release: str, project=None, dist=None):
         bundle = cls.create_artifact_bundle_zip(org, release, project)
         file_ = File.objects.create(name="release-artifacts.zip")
@@ -566,7 +567,7 @@ class Factories:
         return update_artifact_index(release, dist, file_)
 
     @classmethod
-    @exempt_from_silo_limits()
+    @assume_test_silo_mode(SiloMode.REGION)
     def create_artifact_bundle(
         cls,
         org,
@@ -595,7 +596,7 @@ class Factories:
         return artifact_bundle
 
     @staticmethod
-    @exempt_from_silo_limits()
+    @assume_test_silo_mode(SiloMode.REGION)
     def create_code_mapping(project, repo=None, organization_integration=None, **kwargs):
         kwargs.setdefault("stack_root", "")
         kwargs.setdefault("source_root", "")
@@ -611,7 +612,7 @@ class Factories:
         )
 
     @staticmethod
-    @exempt_from_silo_limits()
+    @assume_test_silo_mode(SiloMode.REGION)
     def create_repo(project, name=None, provider=None, integration_id=None, url=None):
         repo, _ = Repository.objects.get_or_create(
             organization_id=project.organization_id,
@@ -624,7 +625,7 @@ class Factories:
         return repo
 
     @staticmethod
-    @exempt_from_silo_limits()
+    @assume_test_silo_mode(SiloMode.REGION)
     def create_commit(
         repo, project=None, author=None, release=None, message=None, key=None, date_added=None
     ):
@@ -657,7 +658,7 @@ class Factories:
         return commit
 
     @staticmethod
-    @exempt_from_silo_limits()
+    @assume_test_silo_mode(SiloMode.REGION)
     def create_commit_author(organization_id=None, project=None, user=None, email=None):
         if email:
             user_email = email
@@ -670,14 +671,14 @@ class Factories:
         )[0]
 
     @staticmethod
-    @exempt_from_silo_limits()
+    @assume_test_silo_mode(SiloMode.REGION)
     def create_commit_file_change(commit, filename):
         return CommitFileChange.objects.get_or_create(
             organization_id=commit.organization_id, commit=commit, filename=filename, type="M"
         )
 
     @staticmethod
-    @exempt_from_silo_limits()
+    @assume_test_silo_mode(SiloMode.CONTROL)
     def create_user(email=None, **kwargs):
         if email is None:
             email = uuid4().hex + "@example.com"
@@ -698,7 +699,7 @@ class Factories:
         return user
 
     @staticmethod
-    @exempt_from_silo_limits()
+    @assume_test_silo_mode(SiloMode.CONTROL)
     def create_useremail(user, email, **kwargs):
         if not email:
             email = uuid4().hex + "@example.com"
@@ -774,7 +775,7 @@ class Factories:
         return event
 
     @staticmethod
-    @exempt_from_silo_limits()
+    @assume_test_silo_mode(SiloMode.REGION)
     def create_group(project, **kwargs):
         kwargs.setdefault("message", "Hello world")
         kwargs.setdefault("data", {})
@@ -785,12 +786,12 @@ class Factories:
         return Group.objects.create(project=project, **kwargs)
 
     @staticmethod
-    @exempt_from_silo_limits()
+    @assume_test_silo_mode(SiloMode.REGION)
     def create_file(**kwargs):
         return File.objects.create(**kwargs)
 
     @staticmethod
-    @exempt_from_silo_limits()
+    @assume_test_silo_mode(SiloMode.REGION)
     def create_file_from_path(path, name=None, **kwargs):
         if name is None:
             name = os.path.basename(path)
@@ -801,7 +802,7 @@ class Factories:
         return file
 
     @staticmethod
-    @exempt_from_silo_limits()
+    @assume_test_silo_mode(SiloMode.REGION)
     def create_event_attachment(event, file=None, **kwargs):
         if file is None:
             file = Factories.create_file(
@@ -820,7 +821,7 @@ class Factories:
         )
 
     @staticmethod
-    @exempt_from_silo_limits()
+    @assume_test_silo_mode(SiloMode.REGION)
     def create_dif_file(
         project,
         debug_id=None,
@@ -864,7 +865,7 @@ class Factories:
         )
 
     @staticmethod
-    @exempt_from_silo_limits()
+    @assume_test_silo_mode(SiloMode.REGION)
     def create_dif_from_path(path, object_name=None, **kwargs):
         if object_name is None:
             object_name = os.path.basename(path)
@@ -874,12 +875,12 @@ class Factories:
         return Factories.create_dif_file(file=file, object_name=object_name, **kwargs)
 
     @staticmethod
-    @exempt_from_silo_limits()
+    @assume_test_silo_mode(SiloMode.CONTROL)
     def add_user_permission(user, permission):
         UserPermission.objects.create(user=user, permission=permission)
 
     @staticmethod
-    @exempt_from_silo_limits()
+    @assume_test_silo_mode(SiloMode.CONTROL)
     def create_sentry_app(**kwargs):
         published = kwargs.pop("published", False)
         args = Factories._sentry_app_kwargs(**kwargs)
@@ -892,7 +893,7 @@ class Factories:
         return app
 
     @staticmethod
-    @exempt_from_silo_limits()
+    @assume_test_silo_mode(SiloMode.CONTROL)
     def create_internal_integration(**kwargs):
         args = Factories._sentry_app_kwargs(**kwargs)
         args["verify_install"] = False
@@ -901,7 +902,7 @@ class Factories:
         return app
 
     @staticmethod
-    @exempt_from_silo_limits()
+    @assume_test_silo_mode(SiloMode.CONTROL)
     def create_internal_integration_token(install, **kwargs):
         user = kwargs.pop("user")
         request = kwargs.pop("request", None)
@@ -929,7 +930,7 @@ class Factories:
         return _kwargs
 
     @staticmethod
-    @exempt_from_silo_limits()
+    @assume_test_silo_mode(SiloMode.REGION)
     def create_sentry_app_installation(
         organization=None, slug=None, user=None, status=None, prevent_token_exchange=False
     ):
@@ -938,35 +939,37 @@ class Factories:
 
         Factories.create_project(organization=organization)
 
-        install = SentryAppInstallationCreator(
-            slug=(slug or Factories.create_sentry_app(organization=organization).slug),
-            organization_id=organization.id,
-        ).run(
-            user=(user or Factories.create_user()),
-            request=None,
-        )
+        with assume_test_silo_mode(SiloMode.CONTROL):
+            install = SentryAppInstallationCreator(
+                slug=(slug or Factories.create_sentry_app(organization=organization).slug),
+                organization_id=organization.id,
+            ).run(
+                user=(user or Factories.create_user()),
+                request=None,
+            )
 
-        install.status = SentryAppInstallationStatus.INSTALLED if status is None else status
-        install.save()
-        rpc_install = serialize_sentry_app_installation(install, install.sentry_app)
-        if not prevent_token_exchange and (install.sentry_app.status != SentryAppStatus.INTERNAL):
+            install.status = SentryAppInstallationStatus.INSTALLED if status is None else status
+            install.save()
+            rpc_install = serialize_sentry_app_installation(install, install.sentry_app)
+            if not prevent_token_exchange and (
+                install.sentry_app.status != SentryAppStatus.INTERNAL
+            ):
 
-            token_exchange.GrantExchanger.run(
-                install=rpc_install,
-                code=install.api_grant.code,
-                client_id=install.sentry_app.application.client_id,
-                user=install.sentry_app.proxy_user,
-            )
-            install = SentryAppInstallation.objects.get(id=install.id)
+                token_exchange.GrantExchanger.run(
+                    install=rpc_install,
+                    code=install.api_grant.code,
+                    client_id=install.sentry_app.application.client_id,
+                    user=install.sentry_app.proxy_user,
+                )
+                install = SentryAppInstallation.objects.get(id=install.id)
         return install
 
     @staticmethod
-    @exempt_from_silo_limits()
+    @assume_test_silo_mode(SiloMode.CONTROL)
     def create_stacktrace_link_schema():
         return {"type": "stacktrace-link", "uri": "/redirect/"}
 
     @staticmethod
-    @exempt_from_silo_limits()
     def create_issue_link_schema():
         return {
             "type": "issue-link",
@@ -1005,7 +1008,6 @@ class Factories:
         }
 
     @staticmethod
-    @exempt_from_silo_limits()
     def create_alert_rule_action_schema():
         return {
             "type": "alert-rule-action",
@@ -1035,7 +1037,7 @@ class Factories:
         }
 
     @staticmethod
-    @exempt_from_silo_limits()
+    @assume_test_silo_mode(SiloMode.CONTROL)
     def create_service_hook(actor=None, org=None, project=None, events=None, url=None, **kwargs):
         if not actor:
             actor = Factories.create_user()
@@ -1069,7 +1071,7 @@ class Factories:
         return ServiceHook.objects.get(id=hook_id)
 
     @staticmethod
-    @exempt_from_silo_limits()
+    @assume_test_silo_mode(SiloMode.CONTROL)
     def create_sentry_app_feature(feature=None, sentry_app=None, description=None):
         if not sentry_app:
             sentry_app = Factories.create_sentry_app()
@@ -1101,7 +1103,7 @@ class Factories:
         return _kwargs
 
     @staticmethod
-    @exempt_from_silo_limits()
+    @assume_test_silo_mode(SiloMode.REGION)
     def create_doc_integration(features=None, has_avatar: bool = False, **kwargs) -> DocIntegration:
         doc = DocIntegration.objects.create(**Factories._doc_integration_kwargs(**kwargs))
         if features:
@@ -1111,7 +1113,7 @@ class Factories:
         return doc
 
     @staticmethod
-    @exempt_from_silo_limits()
+    @assume_test_silo_mode(SiloMode.CONTROL)
     def create_doc_integration_features(
         features=None, doc_integration=None
     ) -> List[IntegrationFeature]:
@@ -1131,18 +1133,20 @@ class Factories:
         )
 
     @staticmethod
-    @exempt_from_silo_limits()
+    @assume_test_silo_mode(SiloMode.REGION)
     def create_doc_integration_avatar(doc_integration=None, **kwargs) -> DocIntegrationAvatar:
         if not doc_integration:
             doc_integration = Factories.create_doc_integration()
         photo = File.objects.create(name="test.png", type="avatar.file")
         photo.putfile(io.BytesIO(b"imaginethiswasphotobytes"))
-        return DocIntegrationAvatar.objects.create(
-            doc_integration=doc_integration, avatar_type=0, file_id=photo.id
-        )
+
+        with assume_test_silo_mode(SiloMode.CONTROL):
+            return DocIntegrationAvatar.objects.create(
+                doc_integration=doc_integration, avatar_type=0, file_id=photo.id
+            )
 
     @staticmethod
-    @exempt_from_silo_limits()
+    @assume_test_silo_mode(SiloMode.CONTROL)
     def create_userreport(group, project=None, event_id=None, **kwargs):
         return UserReport.objects.create(
             group_id=group.id,
@@ -1155,7 +1159,6 @@ class Factories:
         )
 
     @staticmethod
-    @exempt_from_silo_limits()
     def create_session():
         engine = import_module(settings.SESSION_ENGINE)
 
@@ -1164,7 +1167,7 @@ class Factories:
         return session
 
     @staticmethod
-    @exempt_from_silo_limits()
+    @assume_test_silo_mode(SiloMode.REGION)
     def create_platform_external_issue(
         group=None, service_type=None, display_name=None, web_url=None
     ):
@@ -1177,7 +1180,7 @@ class Factories:
         )
 
     @staticmethod
-    @exempt_from_silo_limits()
+    @assume_test_silo_mode(SiloMode.REGION)
     def create_integration_external_issue(group=None, integration=None, key=None, **kwargs):
         external_issue = ExternalIssue.objects.create(
             organization_id=group.organization.id, integration_id=integration.id, key=key, **kwargs
@@ -1194,7 +1197,7 @@ class Factories:
         return external_issue
 
     @staticmethod
-    @exempt_from_silo_limits()
+    @assume_test_silo_mode(SiloMode.REGION)
     def create_incident(
         organization,
         projects,
@@ -1236,14 +1239,14 @@ class Factories:
         return incident
 
     @staticmethod
-    @exempt_from_silo_limits()
+    @assume_test_silo_mode(SiloMode.REGION)
     def create_incident_activity(incident, type, comment=None, user_id=None):
         return IncidentActivity.objects.create(
             incident=incident, type=type, comment=comment, user_id=user_id
         )
 
     @staticmethod
-    @exempt_from_silo_limits()
+    @assume_test_silo_mode(SiloMode.REGION)
     def create_alert_rule(
         organization,
         projects,
@@ -1298,7 +1301,7 @@ class Factories:
         return alert_rule
 
     @staticmethod
-    @exempt_from_silo_limits()
+    @assume_test_silo_mode(SiloMode.REGION)
     def create_alert_rule_trigger(alert_rule, label=None, alert_threshold=100):
         if not label:
             label = petname.generate(2, " ", letters=10).title()
@@ -1306,7 +1309,7 @@ class Factories:
         return create_alert_rule_trigger(alert_rule, label, alert_threshold)
 
     @staticmethod
-    @exempt_from_silo_limits()
+    @assume_test_silo_mode(SiloMode.REGION)
     def create_incident_trigger(incident, alert_rule_trigger, status=None):
         if status is None:
             status = TriggerStatus.ACTIVE.value
@@ -1316,7 +1319,7 @@ class Factories:
         )
 
     @staticmethod
-    @exempt_from_silo_limits()
+    @assume_test_silo_mode(SiloMode.REGION)
     def create_alert_rule_trigger_action(
         trigger,
         type=AlertRuleTriggerAction.Type.EMAIL,
@@ -1337,7 +1340,7 @@ class Factories:
         )
 
     @staticmethod
-    @exempt_from_silo_limits()
+    @assume_test_silo_mode(SiloMode.REGION)
     def create_external_user(user: User, **kwargs: Any) -> ExternalActor:
         kwargs.setdefault("provider", ExternalProviders.GITHUB.value)
         kwargs.setdefault("external_name", "")
@@ -1346,7 +1349,7 @@ class Factories:
         return ExternalActor.objects.create(actor_id=actor_id, **kwargs)
 
     @staticmethod
-    @exempt_from_silo_limits()
+    @assume_test_silo_mode(SiloMode.REGION)
     def create_external_team(team: Team, **kwargs: Any) -> ExternalActor:
         kwargs.setdefault("provider", ExternalProviders.GITHUB.value)
         kwargs.setdefault("external_name", "@getsentry/ecosystem")
@@ -1354,7 +1357,7 @@ class Factories:
         return ExternalActor.objects.create(actor=team.actor, **kwargs)
 
     @staticmethod
-    @exempt_from_silo_limits()
+    @assume_test_silo_mode(SiloMode.REGION)
     def create_codeowners(project, code_mapping, **kwargs):
         kwargs.setdefault("raw", "")
 
@@ -1363,7 +1366,7 @@ class Factories:
         )
 
     @staticmethod
-    @exempt_from_silo_limits()
+    @assume_test_silo_mode(SiloMode.CONTROL)
     def create_slack_integration(
         organization: Organization, external_id: str, **kwargs: Any
     ) -> Integration:
@@ -1380,7 +1383,7 @@ class Factories:
         return integration
 
     @staticmethod
-    @exempt_from_silo_limits()
+    @assume_test_silo_mode(SiloMode.CONTROL)
     def create_integration(
         organization: Organization,
         external_id: str,
@@ -1394,7 +1397,7 @@ class Factories:
         return integration
 
     @staticmethod
-    @exempt_from_silo_limits()
+    @assume_test_silo_mode(SiloMode.CONTROL)
     def create_identity_provider(integration: Integration, **kwargs: Any) -> IdentityProvider:
         return IdentityProvider.objects.create(
             type=integration.provider,
@@ -1403,7 +1406,7 @@ class Factories:
         )
 
     @staticmethod
-    @exempt_from_silo_limits()
+    @assume_test_silo_mode(SiloMode.CONTROL)
     def create_identity(
         user: Any, identity_provider: IdentityProvider, external_id: str, **kwargs: Any
     ) -> Identity:
@@ -1417,7 +1420,7 @@ class Factories:
         )
 
     @staticmethod
-    @exempt_from_silo_limits()
+    @assume_test_silo_mode(SiloMode.REGION)
     def create_group_history(
         group: Group,
         status: int,
@@ -1446,7 +1449,7 @@ class Factories:
         )
 
     @staticmethod
-    @exempt_from_silo_limits()
+    @assume_test_silo_mode(SiloMode.REGION)
     def create_comment(issue, project, user, text="hello world"):
         data = {"text": text}
         return Activity.objects.create(
@@ -1458,7 +1461,7 @@ class Factories:
         )
 
     @staticmethod
-    @exempt_from_silo_limits()
+    @assume_test_silo_mode(SiloMode.REGION)
     def create_sentry_function(name, code, **kwargs):
         return SentryFunction.objects.create(
             name=name,
@@ -1469,7 +1472,7 @@ class Factories:
         )
 
     @staticmethod
-    @exempt_from_silo_limits()
+    @assume_test_silo_mode(SiloMode.REGION)
     def create_saved_search(name: str, **kwargs):
         if "owner" in kwargs:
             owner = kwargs.pop("owner")
@@ -1477,7 +1480,7 @@ class Factories:
         return SavedSearch.objects.create(name=name, **kwargs)
 
     @staticmethod
-    @exempt_from_silo_limits()
+    @assume_test_silo_mode(SiloMode.REGION)
     def create_notification_action(
         organization: Optional[Organization] = None,
         projects: Optional[List[Project]] = None,
@@ -1506,6 +1509,6 @@ class Factories:
         return action
 
     @staticmethod
-    @exempt_from_silo_limits()
+    @assume_test_silo_mode(SiloMode.REGION)
     def snooze_rule(**kwargs):
         return RuleSnooze.objects.create(**kwargs)

+ 6 - 15
src/sentry/testutils/fixtures.py

@@ -16,10 +16,11 @@ from sentry.models import (
 )
 from sentry.models.actor import Actor, get_actor_id_for_user
 from sentry.services.hybrid_cloud.user import RpcUser
+from sentry.silo import SiloMode
 from sentry.testutils.factories import Factories
 from sentry.testutils.helpers.datetime import before_now, iso_format
 from sentry.testutils.outbox import outbox_runner
-from sentry.testutils.silo import exempt_from_silo_limits
+from sentry.testutils.silo import assume_test_silo_mode
 
 # XXX(dcramer): this is a compatibility layer to transition to pytest-based fixtures
 # all of the memoized fixtures are copypasta due to our inability to use pytest fixtures
@@ -29,29 +30,25 @@ from sentry.types.activity import ActivityType
 
 class Fixtures:
     @cached_property
-    @exempt_from_silo_limits()
     def session(self):
         return Factories.create_session()
 
     @cached_property
-    @exempt_from_silo_limits()
     def projectkey(self):
         return self.create_project_key(project=self.project)
 
     @cached_property
-    @exempt_from_silo_limits()
     def user(self):
         return self.create_user("admin@localhost", is_superuser=True)
 
     @cached_property
-    @exempt_from_silo_limits()
     def organization(self):
         # XXX(dcramer): ensure that your org slug doesnt match your team slug
         # and the same for your project slug
         return self.create_organization(name="baz", slug="baz", owner=self.user)
 
     @cached_property
-    @exempt_from_silo_limits()
+    @assume_test_silo_mode(SiloMode.REGION)
     def team(self):
         team = self.create_team(organization=self.organization, name="foo", slug="foo")
         # XXX: handle legacy team fixture
@@ -61,30 +58,24 @@ class Fixtures:
         return team
 
     @cached_property
-    @exempt_from_silo_limits()
     def project(self):
         return self.create_project(
             name="Bar", slug="bar", teams=[self.team], fire_project_created=True
         )
 
     @cached_property
-    @exempt_from_silo_limits()
     def release(self):
         return self.create_release(project=self.project, version="foo-1.0")
 
     @cached_property
-    @exempt_from_silo_limits()
     def environment(self):
         return self.create_environment(name="development", project=self.project)
 
     @cached_property
-    @exempt_from_silo_limits()
     def group(self):
-        # こんにちは konichiwa
         return self.create_group(message="\u3053\u3093\u306b\u3061\u306f")
 
     @cached_property
-    @exempt_from_silo_limits()
     def event(self):
         return self.store_event(
             data={
@@ -96,7 +87,7 @@ class Fixtures:
         )
 
     @cached_property
-    @exempt_from_silo_limits()
+    @assume_test_silo_mode(SiloMode.REGION)
     def activity(self):
         return Activity.objects.create(
             group=self.group,
@@ -107,7 +98,7 @@ class Fixtures:
         )
 
     @cached_property
-    @exempt_from_silo_limits()
+    @assume_test_silo_mode(SiloMode.CONTROL)
     def integration(self):
         integration = Integration.objects.create(
             provider="github", name="GitHub", external_id="github:1"
@@ -116,7 +107,7 @@ class Fixtures:
         return integration
 
     @cached_property
-    @exempt_from_silo_limits()
+    @assume_test_silo_mode(SiloMode.CONTROL)
     def organization_integration(self):
         return self.integration.add_organization(self.organization, self.user)
 

+ 2 - 1
src/sentry/testutils/helpers/api_gateway.py

@@ -2,6 +2,7 @@ from urllib.parse import parse_qs
 
 import responses
 from django.conf import settings
+from django.db import router
 from django.test import override_settings
 from django.urls import re_path
 from rest_framework.permissions import AllowAny
@@ -135,7 +136,7 @@ class ApiGatewayTestCase(APITestCase):
             adding_headers={"test": "header"},
         )
 
-        with in_test_psql_role_override("postgres"):
+        with in_test_psql_role_override("postgres", using=router.db_for_write(OrganizationMapping)):
             OrganizationMapping.objects.get(organization_id=self.organization.id).update(
                 region_name="region1"
             )

+ 3 - 2
src/sentry/testutils/helpers/slack.py

@@ -16,7 +16,8 @@ from sentry.models import (
     Team,
     User,
 )
-from sentry.testutils.silo import exempt_from_silo_limits
+from sentry.silo import SiloMode
+from sentry.testutils.silo import assume_test_silo_mode
 from sentry.types.integrations import EXTERNAL_PROVIDERS, ExternalProviders
 from sentry.utils import json
 
@@ -31,7 +32,7 @@ def get_response_text(data: SlackBody) -> str:
     )
 
 
-@exempt_from_silo_limits()
+@assume_test_silo_mode(SiloMode.CONTROL)
 def install_slack(organization: Organization, workspace_id: str = "TXXXXXXX1") -> Integration:
     integration = Integration.objects.create(
         external_id=workspace_id,

+ 13 - 7
tests/sentry/hybrid_cloud/test_rpc.py

@@ -158,17 +158,23 @@ class DispatchRemoteCallTest(TestCase):
         mock_response.read.return_value = serial_response
         mock_urlopen.return_value.__enter__.return_value = mock_response
 
-    @override_settings(SILO_MODE=SiloMode.REGION, DEV_HYBRID_CLOUD_RPC_SENDER=_REGION_SILO_CREDS)
     @mock.patch("sentry.services.hybrid_cloud.rpc.urlopen")
     def test_region_to_control_happy_path(self, mock_urlopen):
         org = self.create_organization()
-        response_value = RpcUserOrganizationContext(organization=serialize_rpc_organization(org))
-        self._set_up_mock_response(mock_urlopen, response_value.dict())
 
-        result = dispatch_remote_call(
-            None, "organization", "get_organization_by_id", {"id": org.id}
-        )
-        assert result == response_value
+        with override_settings(
+            SILO_MODE=SiloMode.REGION,
+            DEV_HYBRID_CLOUD_RPC_SENDER=self._REGION_SILO_CREDS,
+        ):
+            response_value = RpcUserOrganizationContext(
+                organization=serialize_rpc_organization(org)
+            )
+            self._set_up_mock_response(mock_urlopen, response_value.dict())
+
+            result = dispatch_remote_call(
+                None, "organization", "get_organization_by_id", {"id": org.id}
+            )
+            assert result == response_value
 
     @override_settings(SILO_MODE=SiloMode.REGION, DEV_HYBRID_CLOUD_RPC_SENDER=_REGION_SILO_CREDS)
     @mock.patch("sentry.services.hybrid_cloud.rpc.urlopen")