Skip to content

Commit df1e193

Browse files
scttcperandrewshie-sentry
authored andcommitted
feat(aci): Add available detector types to validation error (#93203)
1 parent a1ce6a5 commit df1e193

File tree

7 files changed

+39
-7
lines changed

7 files changed

+39
-7
lines changed

src/sentry/workflow_engine/endpoints/organization_detector_details.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828
from sentry.utils.audit import create_audit_entry
2929
from sentry.workflow_engine.endpoints.serializers import DetectorSerializer
3030
from sentry.workflow_engine.endpoints.validators.detector_workflow import can_edit_detector
31+
from sentry.workflow_engine.endpoints.validators.utils import get_unknown_detector_type_error
3132
from sentry.workflow_engine.models import Detector
3233

3334

@@ -36,7 +37,8 @@ def get_detector_validator(
3637
):
3738
detector_type = grouptype.registry.get_by_slug(detector_type_slug)
3839
if detector_type is None:
39-
raise ValidationError({"detectorType": ["Unknown detector type"]})
40+
error_message = get_unknown_detector_type_error(detector_type_slug, project.organization)
41+
raise ValidationError({"detectorType": [error_message]})
4042

4143
if detector_type.detector_settings is None or detector_type.detector_settings.validator is None:
4244
raise ValidationError({"detectorType": ["Detector type not compatible with detectors"]})

src/sentry/workflow_engine/endpoints/organization_detector_index.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
from sentry.workflow_engine.endpoints.serializers import DetectorSerializer
2727
from sentry.workflow_engine.endpoints.utils.sortby import SortByParam
2828
from sentry.workflow_engine.endpoints.validators.base import BaseDetectorTypeValidator
29+
from sentry.workflow_engine.endpoints.validators.utils import get_unknown_detector_type_error
2930
from sentry.workflow_engine.models import Detector
3031

3132
# Maps API field name to database field name, with synthetic aggregate fields keeping
@@ -43,7 +44,8 @@ def get_detector_validator(
4344
) -> BaseDetectorTypeValidator:
4445
detector_type = grouptype.registry.get_by_slug(detector_type_slug)
4546
if detector_type is None:
46-
raise ValidationError({"detectorType": ["Unknown detector type"]})
47+
error_message = get_unknown_detector_type_error(detector_type_slug, project.organization)
48+
raise ValidationError({"detectorType": [error_message]})
4749

4850
if detector_type.detector_settings is None or detector_type.detector_settings.validator is None:
4951
raise ValidationError({"detectorType": ["Detector type not compatible with detectors"]})

src/sentry/workflow_engine/endpoints/validators/base/detector.py

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
BaseDataConditionValidator,
1111
BaseDataSourceValidator,
1212
)
13+
from sentry.workflow_engine.endpoints.validators.utils import get_unknown_detector_type_error
1314
from sentry.workflow_engine.models import (
1415
DataConditionGroup,
1516
DataSource,
@@ -31,7 +32,12 @@ class BaseDetectorTypeValidator(CamelSnakeSerializer):
3132
def validate_detector_type(self, value: str) -> type[GroupType]:
3233
detector_type = grouptype.registry.get_by_slug(value)
3334
if detector_type is None:
34-
raise serializers.ValidationError("Unknown detector type")
35+
organization = self.context.get("organization")
36+
if organization:
37+
error_message = get_unknown_detector_type_error(value, organization)
38+
else:
39+
error_message = f"Unknown detector type '{value}'"
40+
raise serializers.ValidationError(error_message)
3541
if (
3642
detector_type.detector_settings is None
3743
or detector_type.detector_settings.validator is None

src/sentry/workflow_engine/endpoints/validators/utils.py

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,9 @@
44
from jsonschema import ValidationError as JsonValidationError
55
from jsonschema import validate
66

7+
from sentry.issues import grouptype
8+
from sentry.models.organization import Organization
9+
710

811
def validate_json_schema(value, schema):
912
try:
@@ -33,3 +36,18 @@ def remove_items_by_api_input(
3336
if has_items_removed:
3437
filter_kwargs = {f"{values_list_field}__in": data_ids}
3538
instance.exclude(**filter_kwargs).delete()
39+
40+
41+
def get_unknown_detector_type_error(bad_value: str, organization: Organization) -> str:
42+
available_types = [
43+
gt.slug
44+
for gt in grouptype.registry.get_visible(organization)
45+
if gt.detector_settings is not None and gt.detector_settings.validator is not None
46+
]
47+
available_types.sort()
48+
49+
if available_types:
50+
available_str = ", ".join(available_types)
51+
return f"Unknown detector type '{bad_value}'. Must be one of: {available_str}"
52+
else:
53+
return f"Unknown detector type '{bad_value}'. No detector types are available."

tests/sentry/incidents/endpoints/validators/test_validators.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -202,7 +202,9 @@ def test_invalid_detector_type(self):
202202
validator = MetricAlertsDetectorValidator(data=data, context=self.context)
203203
assert not validator.is_valid()
204204
assert validator.errors.get("detectorType") == [
205-
ErrorDetail(string="Unknown detector type", code="invalid")
205+
ErrorDetail(
206+
string="Unknown detector type 'invalid_type'. Must be one of: error", code="invalid"
207+
)
206208
]
207209

208210
def test_too_many_conditions(self):

tests/sentry/workflow_engine/endpoints/test_organization_detector_index.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -321,7 +321,9 @@ def test_invalid_group_type(self):
321321
**data,
322322
status_code=400,
323323
)
324-
assert response.data == {"detectorType": ["Unknown detector type"]}
324+
assert response.data == {
325+
"detectorType": ["Unknown detector type 'invalid_type'. Must be one of: error"]
326+
}
325327

326328
def test_incompatible_group_type(self):
327329
with mock.patch("sentry.issues.grouptype.registry.get_by_slug") as mock_get:

tests/sentry/workflow_engine/endpoints/test_validators.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -131,7 +131,7 @@ def test_validate_detector_type_unknown(self):
131131
validator = self.validator_class()
132132
with pytest.raises(
133133
ValidationError,
134-
match="[ErrorDetail(string='Unknown detector type', code='invalid')]",
134+
match="[ErrorDetail(string='Unknown detector type 'unknown_type'. Must be one of: error', code='invalid')]",
135135
):
136136
validator.validate_detector_type("unknown_type")
137137

@@ -233,7 +233,7 @@ def test_validate_detector_type_unknown(self):
233233
validator = MockDetectorValidator(data={**self.valid_data, "detectorType": "unknown_type"})
234234
assert not validator.is_valid()
235235
assert validator.errors.get("detectorType") == [
236-
ErrorDetail(string="Unknown detector type", code="invalid")
236+
ErrorDetail(string="Unknown detector type 'unknown_type'", code="invalid")
237237
], validator.errors
238238

239239
def test_validate_detector_type_incompatible(self):

0 commit comments

Comments
 (0)