From 57d6adbc7c4008143ac18fc7076607be227e12d3 Mon Sep 17 00:00:00 2001 From: Bart Peeters Date: Mon, 21 Nov 2022 19:58:25 +0100 Subject: [PATCH] Alerting: Support Prometheus durations in Provisioning API (#58293) Provisioning API should support Prometheus durations --- .../definitions/provisioning_alert_rules.go | 6 +----- .../provisioning/alerting/rules_types.go | 10 +++++---- .../provisioning/alerting/rules_types_test.go | 21 +++++++++++++++++++ 3 files changed, 28 insertions(+), 9 deletions(-) diff --git a/pkg/services/ngalert/api/tooling/definitions/provisioning_alert_rules.go b/pkg/services/ngalert/api/tooling/definitions/provisioning_alert_rules.go index 75c86d20b39..8924b6cc2a5 100644 --- a/pkg/services/ngalert/api/tooling/definitions/provisioning_alert_rules.go +++ b/pkg/services/ngalert/api/tooling/definitions/provisioning_alert_rules.go @@ -104,10 +104,6 @@ type ProvisionedAlertRule struct { } func (a *ProvisionedAlertRule) UpstreamModel() (models.AlertRule, error) { - forDur, err := time.ParseDuration(a.For.String()) - if err != nil { - return models.AlertRule{}, err - } return models.AlertRule{ ID: a.ID, UID: a.UID, @@ -120,7 +116,7 @@ func (a *ProvisionedAlertRule) UpstreamModel() (models.AlertRule, error) { Updated: a.Updated, NoDataState: a.NoDataState, ExecErrState: a.ExecErrState, - For: forDur, + For: time.Duration(a.For), Annotations: a.Annotations, Labels: a.Labels, }, nil diff --git a/pkg/services/provisioning/alerting/rules_types.go b/pkg/services/provisioning/alerting/rules_types.go index c74b9a2da1b..b300d918c46 100644 --- a/pkg/services/provisioning/alerting/rules_types.go +++ b/pkg/services/provisioning/alerting/rules_types.go @@ -9,6 +9,8 @@ import ( "github.com/grafana/grafana/pkg/services/ngalert/models" "github.com/grafana/grafana/pkg/services/provisioning/values" + + "github.com/prometheus/common/model" ) type RuleDelete struct { @@ -39,11 +41,11 @@ func (ruleGroupV1 *AlertRuleGroupV1) MapToModel() (AlertRuleGroup, error) { if ruleGroup.OrgID < 1 { ruleGroup.OrgID = 1 } - interval, err := time.ParseDuration(ruleGroupV1.Interval.Value()) + interval, err := model.ParseDuration(ruleGroupV1.Interval.Value()) if err != nil { return AlertRuleGroup{}, err } - ruleGroup.Interval = interval + ruleGroup.Interval = time.Duration(interval) ruleGroup.Folder = ruleGroupV1.Folder.Value() if strings.TrimSpace(ruleGroup.Folder) == "" { return AlertRuleGroup{}, errors.New("rule group has no folder set") @@ -91,11 +93,11 @@ func (rule *AlertRuleV1) mapToModel(orgID int64) (models.AlertRule, error) { return models.AlertRule{}, fmt.Errorf("rule '%s' failed to parse: no UID set", alertRule.Title) } alertRule.OrgID = orgID - duration, err := time.ParseDuration(rule.For.Value()) + duration, err := model.ParseDuration(rule.For.Value()) if err != nil { return models.AlertRule{}, fmt.Errorf("rule '%s' failed to parse: %w", alertRule.Title, err) } - alertRule.For = duration + alertRule.For = time.Duration(duration) dashboardUID := rule.DashboardUID.Value() alertRule.DashboardUID = &dashboardUID panelID := rule.PanelID.Value() diff --git a/pkg/services/provisioning/alerting/rules_types_test.go b/pkg/services/provisioning/alerting/rules_types_test.go index 877d4f84b14..0eac93e2404 100644 --- a/pkg/services/provisioning/alerting/rules_types_test.go +++ b/pkg/services/provisioning/alerting/rules_types_test.go @@ -2,6 +2,7 @@ package alerting import ( "testing" + "time" "github.com/grafana/grafana/pkg/services/ngalert/models" "github.com/grafana/grafana/pkg/services/provisioning/values" @@ -51,6 +52,16 @@ func TestRuleGroup(t *testing.T) { _, err = rg.MapToModel() require.Error(t, err) }) + t.Run("a rule group with an interval containing 'd' should work", func(t *testing.T) { + rg := validRuleGroupV1(t) + var interval values.StringValue + err := yaml.Unmarshal([]byte("2d"), &interval) + require.NoError(t, err) + rg.Interval = interval + rgMapped, err := rg.MapToModel() + require.NoError(t, err) + require.Equal(t, 48*time.Hour, rgMapped.Interval) + }) t.Run("a rule group with an empty org id should default to 1", func(t *testing.T) { rg := validRuleGroupV1(t) rg.OrgID = values.Int64Value{} @@ -103,6 +114,16 @@ func TestRules(t *testing.T) { _, err = rule.mapToModel(1) require.Error(t, err) }) + t.Run("a rule with a for duration containing 'd' should work", func(t *testing.T) { + rule := validRuleV1(t) + forDuration := values.StringValue{} + err := yaml.Unmarshal([]byte("2d"), &forDuration) + rule.For = forDuration + require.NoError(t, err) + ruleMapped, err := rule.mapToModel(1) + require.NoError(t, err) + require.Equal(t, 48*time.Hour, ruleMapped.For) + }) t.Run("a rule with out a condition should error", func(t *testing.T) { rule := validRuleV1(t) rule.Condition = values.StringValue{}