Skip to content

Commit 4a9e4a3

Browse files
fix(tools):missing parameters in create/update alert rule tools (#663)
1 parent 242c07b commit 4a9e4a3

5 files changed

Lines changed: 865 additions & 115 deletions

File tree

testdata/provisioning/alerting/alert_rules.yaml

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -176,3 +176,31 @@ groups:
176176
type: test
177177
rule: third
178178
isPaused: true
179+
- uid: recording_rule_1
180+
title: test_recording_rule
181+
condition: A
182+
data:
183+
- refId: A
184+
relativeTimeRange:
185+
from: 600
186+
to: 0
187+
datasourceUid: prometheus
188+
model:
189+
datasource:
190+
type: prometheus
191+
uid: prometheus
192+
editorMode: code
193+
expr: avg(rate(http_requests_total[5m]))
194+
instant: true
195+
range: false
196+
refId: A
197+
record:
198+
from: A
199+
metric: http_requests_avg
200+
target_datasource_uid: prometheus
201+
202+
annotations:
203+
description: "Recording avg HTTP request rate"
204+
labels:
205+
team: sre
206+
type: test

tools/alerting_manage_rules_handlers.go

Lines changed: 68 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -122,9 +122,11 @@ func getAlertRuleVersions(ctx context.Context, uid string) (any, error) {
122122
// are left at their zero values.
123123
func mergeRuleDetail(provisioned *models.ProvisionedAlertRule, runtime *alertingRule) alertRuleDetail {
124124
detail := alertRuleDetail{
125-
UID: provisioned.UID,
126-
Labels: provisioned.Labels,
127-
Annotations: provisioned.Annotations,
125+
UID: provisioned.UID,
126+
Labels: provisioned.Labels,
127+
Annotations: provisioned.Annotations,
128+
KeepFiringFor: provisioned.KeepFiringFor.String(),
129+
MissingSeriesEvalsToResolve: provisioned.MissingSeriesEvalsToResolve,
128130
}
129131

130132
if provisioned.Title != nil {
@@ -139,6 +141,8 @@ func mergeRuleDetail(provisioned *models.ProvisionedAlertRule, runtime *alerting
139141
if provisioned.Condition != nil {
140142
detail.Condition = *provisioned.Condition
141143
}
144+
// NoDataState, ExecErrState are set empty by grafana HTTP API for a recording rule
145+
// non-nil checks are applied as api expects to have a defined value for these fields
142146
if provisioned.NoDataState != nil {
143147
detail.NoDataState = *provisioned.NoDataState
144148
}
@@ -148,6 +152,9 @@ func mergeRuleDetail(provisioned *models.ProvisionedAlertRule, runtime *alerting
148152
if provisioned.For != nil {
149153
detail.For = provisioned.For.String()
150154
}
155+
if provisioned.Record != nil {
156+
detail.Record = (*Record)(provisioned.Record)
157+
}
151158

152159
detail.IsPaused = provisioned.IsPaused
153160
detail.NotificationSettings = provisioned.NotificationSettings
@@ -313,26 +320,41 @@ func createAlertRule(ctx context.Context, args CreateAlertRuleParams) (*models.P
313320

314321
duration, err := time.ParseDuration(args.For)
315322
if err != nil {
316-
return nil, fmt.Errorf("create alert rule: invalid duration format %q: %w", args.For, err)
323+
return nil, fmt.Errorf("create alert rule: invalid duration format for parameter for: %q: %w", args.For, err)
317324
}
318325

319326
convertedData, err := convertAlertQueries(args.Data)
320327
if err != nil {
321328
return nil, fmt.Errorf("create alert rule: %w", err)
322329
}
330+
keepFiringFor := time.Duration(0)
331+
if args.KeepFiringFor != "" {
332+
keepFiringFor, err = time.ParseDuration(args.KeepFiringFor)
333+
if err != nil {
334+
return nil, fmt.Errorf("create alert rule: invalid duration format for parameter keepFiringFor: %q: %w", args.KeepFiringFor, err)
335+
}
336+
}
337+
338+
notificationSettings := convertNotificationSettings(args.NotificationSettings)
339+
record := convertRecord(args.Record)
323340

324341
rule := &models.ProvisionedAlertRule{
325-
Title: &args.Title,
326-
RuleGroup: &args.RuleGroup,
327-
FolderUID: &args.FolderUID,
328-
Condition: &args.Condition,
329-
Data: convertedData,
330-
NoDataState: &args.NoDataState,
331-
ExecErrState: &args.ExecErrState,
332-
For: func() *strfmt.Duration { d := strfmt.Duration(duration); return &d }(),
333-
Annotations: args.Annotations,
334-
Labels: args.Labels,
335-
OrgID: &args.OrgID,
342+
Title: &args.Title,
343+
RuleGroup: &args.RuleGroup,
344+
FolderUID: &args.FolderUID,
345+
Condition: &args.Condition,
346+
Data: convertedData,
347+
NoDataState: &args.NoDataState,
348+
ExecErrState: &args.ExecErrState,
349+
For: func() *strfmt.Duration { d := strfmt.Duration(duration); return &d }(),
350+
Annotations: args.Annotations,
351+
Labels: args.Labels,
352+
OrgID: &args.OrgID,
353+
IsPaused: args.IsPaused,
354+
KeepFiringFor: func() strfmt.Duration { d := strfmt.Duration(keepFiringFor); return d }(),
355+
MissingSeriesEvalsToResolve: args.MissingSeriesEvalsToResolve,
356+
NotificationSettings: notificationSettings,
357+
Record: record,
336358
}
337359

338360
if args.UID != nil {
@@ -353,7 +375,6 @@ func createAlertRule(ctx context.Context, args CreateAlertRuleParams) (*models.P
353375
header := "true"
354376
params = params.WithXDisableProvenance(&header)
355377
}
356-
357378
response, err := c.Provisioning.PostAlertRule(params)
358379
if err != nil {
359380
return nil, fmt.Errorf("create alert rule: %w", err)
@@ -371,27 +392,45 @@ func updateAlertRule(ctx context.Context, args UpdateAlertRuleParams) (*models.P
371392

372393
duration, err := time.ParseDuration(args.For)
373394
if err != nil {
374-
return nil, fmt.Errorf("update alert rule: invalid duration format %q: %w", args.For, err)
395+
return nil, fmt.Errorf("update alert rule: invalid duration format for parameter for: %q: %w", args.For, err)
375396
}
376397

377398
convertedData, err := convertAlertQueries(args.Data)
378399
if err != nil {
379400
return nil, fmt.Errorf("update alert rule: %w", err)
380401
}
381402

403+
keepFiringFor := time.Duration(0)
404+
if args.KeepFiringFor != "" {
405+
keepFiringFor, err = time.ParseDuration(args.KeepFiringFor)
406+
if err != nil {
407+
return nil, fmt.Errorf("update alert rule: invalid duration format for parameter keepFiringFor: %q: %w", args.KeepFiringFor, err)
408+
}
409+
}
410+
411+
notificationSettings := convertNotificationSettings(args.NotificationSettings)
412+
413+
record := convertRecord(args.Record)
414+
415+
// MissingSeriesEvalsToResolve, Provenance are set to defaults
382416
rule := &models.ProvisionedAlertRule{
383-
UID: args.UID,
384-
Title: &args.Title,
385-
RuleGroup: &args.RuleGroup,
386-
FolderUID: &args.FolderUID,
387-
Condition: &args.Condition,
388-
Data: convertedData,
389-
NoDataState: &args.NoDataState,
390-
ExecErrState: &args.ExecErrState,
391-
For: func() *strfmt.Duration { d := strfmt.Duration(duration); return &d }(),
392-
Annotations: args.Annotations,
393-
Labels: args.Labels,
394-
OrgID: &args.OrgID,
417+
UID: args.UID,
418+
Title: &args.Title,
419+
RuleGroup: &args.RuleGroup,
420+
FolderUID: &args.FolderUID,
421+
Condition: &args.Condition,
422+
Data: convertedData,
423+
NoDataState: &args.NoDataState,
424+
ExecErrState: &args.ExecErrState,
425+
For: func() *strfmt.Duration { d := strfmt.Duration(duration); return &d }(),
426+
Annotations: args.Annotations,
427+
Labels: args.Labels,
428+
OrgID: &args.OrgID,
429+
IsPaused: args.IsPaused,
430+
MissingSeriesEvalsToResolve: args.MissingSeriesEvalsToResolve,
431+
KeepFiringFor: func() strfmt.Duration { d := strfmt.Duration(keepFiringFor); return d }(),
432+
NotificationSettings: notificationSettings,
433+
Record: record,
395434
}
396435

397436
if err := rule.Validate(strfmt.Default); err != nil {

0 commit comments

Comments
 (0)