15
15
from apps .base .messaging import get_messaging_backends
16
16
from apps .integrations .legacy_prefix import has_legacy_prefix
17
17
from apps .labels .models import LabelKeyCache , LabelValueCache
18
+ from apps .labels .types import LabelKey
18
19
from apps .user_management .models import Organization
19
20
from common .api_helpers .custom_fields import TeamPrimaryKeyRelatedField
20
21
from common .api_helpers .exceptions import BadRequest
25
26
from .labels import LabelsSerializerMixin
26
27
27
28
28
- class AlertGroupCustomLabelKey (typing .TypedDict ):
29
- id : str
30
- name : str
31
-
32
-
33
- class AlertGroupCustomLabelValue (typing .TypedDict ):
29
+ # AlertGroupCustomLabelValue represents custom alert group label value for API requests
30
+ # It handles two types of label's value:
31
+ # 1. Just Label Value from a label repo for a static label
32
+ # 2. Templated Label value which is actually a jinja template for a dynamic label.
33
+ class AlertGroupCustomLabelValueAPI (typing .TypedDict ):
34
34
id : str | None # None for templated labels, label value ID for plain labels
35
35
name : str # Jinja template for templated labels, label value name for plain labels
36
+ prescribed : bool # Indicates of selected label value is prescribed. Not applicable for templated values.
36
37
37
38
38
- class AlertGroupCustomLabel (typing .TypedDict ):
39
- key : AlertGroupCustomLabelKey
40
- value : AlertGroupCustomLabelValue
39
+ # AlertGroupCustomLabel represents Alert group custom label for API requests
40
+ # Key is just a LabelKey from label repo, while value could be value from repo or a jinja template.
41
+ class AlertGroupCustomLabelAPI (typing .TypedDict ):
42
+ key : LabelKey
43
+ value : AlertGroupCustomLabelValueAPI
41
44
42
45
43
- AlertGroupCustomLabels = list [AlertGroupCustomLabel ]
46
+ AlertGroupCustomLabelsAPI = list [AlertGroupCustomLabelAPI ]
44
47
45
48
46
49
class IntegrationAlertGroupLabels (typing .TypedDict ):
47
50
inheritable : dict [str , bool ]
48
- custom : AlertGroupCustomLabels
51
+ custom : AlertGroupCustomLabelsAPI
49
52
template : str | None
50
53
51
54
@@ -55,11 +58,13 @@ class CustomLabelSerializer(serializers.Serializer):
55
58
class CustomLabelKeySerializer (serializers .Serializer ):
56
59
id = serializers .CharField ()
57
60
name = serializers .CharField ()
61
+ prescribed = serializers .BooleanField (required = False , default = False )
58
62
59
63
class CustomLabelValueSerializer (serializers .Serializer ):
60
64
# ID is null for templated labels. For such labels, the "name" value is a Jinja2 template.
61
65
id = serializers .CharField (allow_null = True )
62
66
name = serializers .CharField ()
67
+ prescribed = serializers .BooleanField (required = False , default = False )
63
68
64
69
key = CustomLabelKeySerializer ()
65
70
value = CustomLabelValueSerializer ()
@@ -112,16 +117,26 @@ def update(
112
117
return instance
113
118
114
119
@staticmethod
115
- def _create_custom_labels (organization : Organization , labels : AlertGroupCustomLabels ) -> None :
120
+ def _create_custom_labels (organization : Organization , labels : AlertGroupCustomLabelsAPI ) -> None :
116
121
"""Create LabelKeyCache and LabelValueCache objects for custom labels."""
117
122
118
123
label_keys = [
119
- LabelKeyCache (id = label ["key" ]["id" ], name = label ["key" ]["name" ], organization = organization )
124
+ LabelKeyCache (
125
+ id = label ["key" ]["id" ],
126
+ name = label ["key" ]["name" ],
127
+ prescribed = label ["key" ]["prescribed" ],
128
+ organization = organization ,
129
+ )
120
130
for label in labels
121
131
]
122
132
123
133
label_values = [
124
- LabelValueCache (id = label ["value" ]["id" ], name = label ["value" ]["name" ], key_id = label ["key" ]["id" ])
134
+ LabelValueCache (
135
+ id = label ["value" ]["id" ],
136
+ name = label ["value" ]["name" ],
137
+ prescribed = label ["value" ]["prescribed" ],
138
+ key_id = label ["key" ]["id" ],
139
+ )
125
140
for label in labels
126
141
if label ["value" ]["id" ] # don't create LabelValueCache objects for templated labels
127
142
]
@@ -147,8 +162,8 @@ def to_representation(cls, instance: AlertReceiveChannel) -> IntegrationAlertGro
147
162
148
163
@staticmethod
149
164
def _custom_labels_to_internal_value (
150
- custom_labels : AlertGroupCustomLabels ,
151
- ) -> AlertReceiveChannel .AlertGroupCustomLabels :
165
+ custom_labels : AlertGroupCustomLabelsAPI ,
166
+ ) -> AlertReceiveChannel .AlertGroupCustomLabelsDB :
152
167
"""Convert custom labels from API representation to the schema used by the JSONField on the model."""
153
168
154
169
return [
@@ -158,8 +173,8 @@ def _custom_labels_to_internal_value(
158
173
159
174
@staticmethod
160
175
def _custom_labels_to_representation (
161
- custom_labels : AlertReceiveChannel .AlertGroupCustomLabels ,
162
- ) -> AlertGroupCustomLabels :
176
+ custom_labels : AlertReceiveChannel .AlertGroupCustomLabelsDB ,
177
+ ) -> AlertGroupCustomLabelsAPI :
163
178
"""
164
179
Inverse of the _custom_labels_to_internal_value method above.
165
180
Fetches label names from DB cache, so the API response schema is consistent with other label endpoints.
@@ -170,33 +185,37 @@ def _custom_labels_to_representation(
170
185
if custom_labels is None :
171
186
return []
172
187
173
- # get up-to-date label key names
174
- label_key_names = {
175
- k .id : k .name
176
- for k in LabelKeyCache .objects .filter (id__in = [label [0 ] for label in custom_labels ]).only ("id" , "name" )
188
+ # build index of keys id to name and prescribed flag
189
+ label_key_index = {
190
+ k .id : {"name" : k .name , "prescribed" : k .prescribed }
191
+ for k in LabelKeyCache .objects .filter (id__in = [label [0 ] for label in custom_labels ]).only (
192
+ "id" , "name" , "prescribed"
193
+ )
177
194
}
178
195
179
- # get up-to-date label value names
180
- label_value_names = {
181
- v .id : v .name
196
+ # build index of values id to name and prescribed flag
197
+ label_value_index = {
198
+ v .id : { "name" : v .name , "prescribed" : v . prescribed }
182
199
for v in LabelValueCache .objects .filter (id__in = [label [1 ] for label in custom_labels if label [1 ]]).only (
183
- "id" , "name"
200
+ "id" , "name" , "prescribed"
184
201
)
185
202
}
186
203
187
204
return [
188
205
{
189
206
"key" : {
190
207
"id" : key_id ,
191
- "name" : label_key_names [key_id ],
208
+ "name" : label_key_index [key_id ]["name" ],
209
+ "prescribed" : label_key_index [key_id ]["prescribed" ],
192
210
},
193
211
"value" : {
194
212
"id" : value_id if value_id else None ,
195
- "name" : label_value_names [value_id ] if value_id else typing .cast (str , template ),
213
+ "name" : label_value_index [value_id ]["name" ] if value_id else typing .cast (str , template ),
214
+ "prescribed" : label_value_index [key_id ]["prescribed" ],
196
215
},
197
216
}
198
217
for key_id , value_id , template in custom_labels
199
- if key_id in label_key_names and (value_id in label_value_names or not value_id )
218
+ if key_id in label_value_index and (value_id in label_value_index or not value_id )
200
219
]
201
220
202
221
0 commit comments