mirror of
https://github.com/hanzoai/sentinel.git
synced 2026-09-29 22:34:33 +00:00
196 lines
7.5 KiB
Python
196 lines
7.5 KiB
Python
from __future__ import annotations
|
|
|
|
from unittest.mock import patch
|
|
|
|
import responses
|
|
from django.http import HttpRequest, HttpResponse
|
|
from django.test import RequestFactory, override_settings
|
|
|
|
from sentry.middleware.integrations.classifications import IntegrationClassification
|
|
from sentry.middleware.integrations.parsers.jira import JiraRequestParser
|
|
from sentry.models.integrations.integration import Integration
|
|
from sentry.silo.base import SiloMode
|
|
from sentry.testutils.cases import TestCase
|
|
from sentry.testutils.helpers.options import override_options
|
|
from sentry.testutils.outbox import (
|
|
assert_no_webhook_outboxes,
|
|
assert_no_webhook_payloads,
|
|
assert_webhook_outboxes_with_shard_id,
|
|
assert_webhook_payloads_for_mailbox,
|
|
)
|
|
from sentry.testutils.region import override_regions
|
|
from sentry.testutils.silo import control_silo_test
|
|
from sentry.types.region import Region, RegionCategory
|
|
|
|
region = Region("us", 1, "http://us.testserver", RegionCategory.MULTI_TENANT)
|
|
eu_region = Region("eu", 2, "http://eu.testserver", RegionCategory.MULTI_TENANT)
|
|
|
|
region_config = (region, eu_region)
|
|
|
|
|
|
@control_silo_test
|
|
class JiraRequestParserTest(TestCase):
|
|
factory = RequestFactory()
|
|
path_base = f"{IntegrationClassification.integration_prefix}jira"
|
|
|
|
def get_response(self, req: HttpRequest) -> HttpResponse:
|
|
return HttpResponse(status=200, content="passthrough")
|
|
|
|
def get_integration(self) -> Integration:
|
|
self.organization = self.create_organization(owner=self.user, region="us")
|
|
return self.create_integration(
|
|
organization=self.organization, external_id="jira:1", provider="jira"
|
|
)
|
|
|
|
@override_settings(SILO_MODE=SiloMode.CONTROL)
|
|
@override_regions(region_config)
|
|
def test_get_integration_from_request(self):
|
|
request = self.factory.post(path=f"{self.path_base}/issue-updated/")
|
|
parser = JiraRequestParser(request, self.get_response)
|
|
assert parser.get_integration_from_request() is None
|
|
integration = self.get_integration()
|
|
|
|
with patch(
|
|
"sentry.middleware.integrations.parsers.jira.parse_integration_from_request"
|
|
) as mock_parse:
|
|
mock_parse.return_value = integration
|
|
assert parser.get_integration_from_request() == integration
|
|
|
|
@override_settings(SILO_MODE=SiloMode.CONTROL)
|
|
@override_regions(region_config)
|
|
def test_get_response_routing_to_control(self):
|
|
paths = [
|
|
"/ui-hook/",
|
|
"/descriptor/",
|
|
"/installed/",
|
|
"/uninstalled/",
|
|
"/search/org/123/",
|
|
"/configure/",
|
|
]
|
|
for path in paths:
|
|
request = self.factory.post(path=f"{self.path_base}{path}")
|
|
parser = JiraRequestParser(request, self.get_response)
|
|
|
|
response = parser.get_response()
|
|
assert isinstance(response, HttpResponse)
|
|
assert response.status_code == 200
|
|
assert response.content == b"passthrough"
|
|
assert_no_webhook_outboxes()
|
|
|
|
@responses.activate
|
|
@override_settings(SILO_MODE=SiloMode.CONTROL)
|
|
@override_regions(region_config)
|
|
def test_get_response_routing_to_region_sync(self):
|
|
responses.add(
|
|
responses.POST,
|
|
region.to_url("/extensions/jira/issue/LR-123/"),
|
|
body="region response",
|
|
status=200,
|
|
)
|
|
request = self.factory.post(path=f"{self.path_base}/issue/LR-123/")
|
|
parser = JiraRequestParser(request, self.get_response)
|
|
|
|
with patch.object(parser, "get_integration_from_request") as method:
|
|
method.return_value = self.get_integration()
|
|
response = parser.get_response()
|
|
|
|
assert isinstance(response, HttpResponse)
|
|
assert response.status_code == 200
|
|
assert response.content == b"region response"
|
|
assert_no_webhook_outboxes()
|
|
|
|
@responses.activate
|
|
@override_settings(SILO_MODE=SiloMode.CONTROL)
|
|
@override_regions(region_config)
|
|
def test_get_response_routing_to_region_async(self):
|
|
request = self.factory.post(path=f"{self.path_base}/issue-updated/")
|
|
parser = JiraRequestParser(request, self.get_response)
|
|
|
|
integration = self.get_integration()
|
|
assert_no_webhook_outboxes()
|
|
with patch.object(parser, "get_integration_from_request") as method:
|
|
method.return_value = integration
|
|
response = parser.get_response()
|
|
|
|
assert isinstance(response, HttpResponse)
|
|
assert response.status_code == 202
|
|
assert response.content == b""
|
|
|
|
assert len(responses.calls) == 0
|
|
assert_webhook_outboxes_with_shard_id(
|
|
factory_request=request,
|
|
expected_shard_id=integration.id,
|
|
region_names=[region.name],
|
|
)
|
|
|
|
@responses.activate
|
|
@override_settings(SILO_MODE=SiloMode.CONTROL)
|
|
@override_regions(region_config)
|
|
@override_options({"hybridcloud.webhookpayload.rollout": 1.0})
|
|
def test_get_response_routing_to_region_async_webhookpayload(self):
|
|
request = self.factory.post(path=f"{self.path_base}/issue-updated/")
|
|
parser = JiraRequestParser(request, self.get_response)
|
|
|
|
integration = self.get_integration()
|
|
assert_no_webhook_payloads()
|
|
with patch.object(parser, "get_integration_from_request") as method:
|
|
method.return_value = integration
|
|
response = parser.get_response()
|
|
|
|
assert isinstance(response, HttpResponse)
|
|
assert response.status_code == 202
|
|
assert response.content == b""
|
|
|
|
assert len(responses.calls) == 0
|
|
|
|
assert_webhook_payloads_for_mailbox(
|
|
mailbox_name=f"jira:{integration.id}", region_names=[region.name], request=request
|
|
)
|
|
|
|
@override_regions(region_config)
|
|
@override_settings(SILO_MODE=SiloMode.CONTROL)
|
|
@responses.activate
|
|
def test_get_response_invalid_path(self):
|
|
# Invalid path
|
|
request = self.factory.post(path="/new-route/for/no/reason/")
|
|
parser = JiraRequestParser(request, self.get_response)
|
|
|
|
with patch.object(parser, "get_integration_from_request") as method:
|
|
method.return_value = self.get_integration()
|
|
response = parser.get_response()
|
|
|
|
assert isinstance(response, HttpResponse)
|
|
assert response.status_code == 200
|
|
assert response.content == b"passthrough"
|
|
assert len(responses.calls) == 0
|
|
assert_no_webhook_outboxes()
|
|
|
|
@override_regions(region_config)
|
|
@override_settings(SILO_MODE=SiloMode.CONTROL)
|
|
@responses.activate
|
|
def test_get_response_multiple_regions(self):
|
|
responses.add(
|
|
responses.POST,
|
|
eu_region.to_url("/extensions/jira/issue/LR-123/"),
|
|
body="region response",
|
|
status=200,
|
|
)
|
|
request = self.factory.post(path=f"{self.path_base}/issue/LR-123/")
|
|
parser = JiraRequestParser(request, self.get_response)
|
|
|
|
# Add a second organization. Jira only supports single regions.
|
|
other_org = self.create_organization(owner=self.user, region="eu")
|
|
integration = self.get_integration()
|
|
integration.add_organization(other_org.id)
|
|
|
|
with patch.object(parser, "get_integration_from_request") as method:
|
|
method.return_value = integration
|
|
response = parser.get_response()
|
|
|
|
# Response should go to first region
|
|
assert isinstance(response, HttpResponse)
|
|
assert response.status_code == 200
|
|
assert response.content == b"region response"
|
|
assert len(responses.calls) == 1
|
|
assert_no_webhook_outboxes()
|