Alerting: decouple api models from domain\dto models: separate Provenance status + converters (#63594)

* move conversions of domain models to api models and reverse from definition package to api package
This commit is contained in:
Yuri Tseretyan
2023-02-27 17:57:15 -05:00
committed by GitHub
parent dc01e1ee6a
commit f561e71de8
21 changed files with 182 additions and 165 deletions
@@ -17,7 +17,6 @@ import (
"github.com/prometheus/common/model"
"gopkg.in/yaml.v3"
"github.com/grafana/grafana/pkg/services/ngalert/models"
"github.com/grafana/grafana/pkg/services/secrets"
"github.com/grafana/grafana/pkg/util"
)
@@ -567,11 +566,13 @@ func (c *PostableUserConfig) UnmarshalYAML(value *yaml.Node) error {
return nil
}
type Provenance string
// swagger:model
type GettableUserConfig struct {
TemplateFiles map[string]string `yaml:"template_files" json:"template_files"`
TemplateFileProvenances map[string]models.Provenance `yaml:"template_file_provenances,omitempty" json:"template_file_provenances,omitempty"`
AlertmanagerConfig GettableApiAlertingConfig `yaml:"alertmanager_config" json:"alertmanager_config"`
TemplateFiles map[string]string `yaml:"template_files" json:"template_files"`
TemplateFileProvenances map[string]Provenance `yaml:"template_file_provenances,omitempty" json:"template_file_provenances,omitempty"`
AlertmanagerConfig GettableApiAlertingConfig `yaml:"alertmanager_config" json:"alertmanager_config"`
// amSimple stores a map[string]interface of the decoded alertmanager config.
// This enables circumventing the underlying alertmanager secret type
@@ -635,7 +636,7 @@ func (c *GettableUserConfig) GetGrafanaReceiverMap() map[string]*GettableGrafana
type GettableApiAlertingConfig struct {
Config `yaml:",inline"`
MuteTimeProvenances map[string]models.Provenance `yaml:"muteTimeProvenances,omitempty" json:"muteTimeProvenances,omitempty"`
MuteTimeProvenances map[string]Provenance `yaml:"muteTimeProvenances,omitempty" json:"muteTimeProvenances,omitempty"`
// Override with our superset receiver type
Receivers []*GettableApiReceiver `yaml:"receivers,omitempty" json:"receivers,omitempty"`
}
@@ -722,7 +723,7 @@ type Route struct {
GroupInterval *model.Duration `yaml:"group_interval,omitempty" json:"group_interval,omitempty"`
RepeatInterval *model.Duration `yaml:"repeat_interval,omitempty" json:"repeat_interval,omitempty"`
Provenance models.Provenance `yaml:"provenance,omitempty" json:"provenance,omitempty"`
Provenance Provenance `yaml:"provenance,omitempty" json:"provenance,omitempty"`
}
// UnmarshalYAML implements the yaml.Unmarshaler interface for Route. This is a copy of alertmanager's upstream except it removes validation on the label key.
@@ -1006,13 +1007,13 @@ func (r RawMessage) MarshalYAML() (interface{}, error) {
}
type GettableGrafanaReceiver struct {
UID string `json:"uid"`
Name string `json:"name"`
Type string `json:"type"`
DisableResolveMessage bool `json:"disableResolveMessage"`
Settings RawMessage `json:"settings,omitempty"`
SecureFields map[string]bool `json:"secureFields"`
Provenance models.Provenance `json:"provenance,omitempty"`
UID string `json:"uid"`
Name string `json:"name"`
Type string `json:"type"`
DisableResolveMessage bool `json:"disableResolveMessage"`
Settings RawMessage `json:"settings,omitempty"`
SecureFields map[string]bool `json:"secureFields"`
Provenance Provenance `json:"provenance,omitempty"`
}
type PostableGrafanaReceiver struct {
@@ -393,6 +393,6 @@ type GettableGrafanaRule struct {
RuleGroup string `json:"rule_group" yaml:"rule_group"`
NoDataState NoDataState `json:"no_data_state" yaml:"no_data_state"`
ExecErrState ExecutionErrorState `json:"exec_err_state" yaml:"exec_err_state"`
Provenance models.Provenance `json:"provenance,omitempty" yaml:"provenance,omitempty"`
Provenance Provenance `json:"provenance,omitempty" yaml:"provenance,omitempty"`
IsPaused bool `json:"is_paused" yaml:"is_paused"`
}
@@ -133,60 +133,11 @@ type ProvisionedAlertRule struct {
// example: {"team": "sre-team-1"}
Labels map[string]string `json:"labels,omitempty"`
// readonly: true
Provenance models.Provenance `json:"provenance,omitempty"`
Provenance Provenance `json:"provenance,omitempty"`
// example: false
IsPaused bool `json:"isPaused"`
}
func (a *ProvisionedAlertRule) UpstreamModel() (models.AlertRule, error) {
return models.AlertRule{
ID: a.ID,
UID: a.UID,
OrgID: a.OrgID,
NamespaceUID: a.FolderUID,
RuleGroup: a.RuleGroup,
Title: a.Title,
Condition: a.Condition,
Data: a.Data,
Updated: a.Updated,
NoDataState: a.NoDataState,
ExecErrState: a.ExecErrState,
For: time.Duration(a.For),
Annotations: a.Annotations,
Labels: a.Labels,
IsPaused: a.IsPaused,
}, nil
}
func NewAlertRule(rule models.AlertRule, provenance models.Provenance) ProvisionedAlertRule {
return ProvisionedAlertRule{
ID: rule.ID,
UID: rule.UID,
OrgID: rule.OrgID,
FolderUID: rule.NamespaceUID,
RuleGroup: rule.RuleGroup,
Title: rule.Title,
For: model.Duration(rule.For),
Condition: rule.Condition,
Data: rule.Data,
Updated: rule.Updated,
NoDataState: rule.NoDataState,
ExecErrState: rule.ExecErrState,
Annotations: rule.Annotations,
Labels: rule.Labels,
Provenance: provenance,
IsPaused: rule.IsPaused,
}
}
func NewAlertRules(rules []*models.AlertRule) ProvisionedAlertRules {
result := make([]ProvisionedAlertRule, 0, len(rules))
for _, r := range rules {
result = append(result, NewAlertRule(*r, models.ProvenanceNone))
}
return result
}
// swagger:route GET /api/v1/provisioning/folder/{FolderUID}/rule-groups/{Group} provisioning stable RouteGetAlertRuleGroup
//
// Get a rule group.
@@ -268,32 +219,3 @@ type AlertRuleGroup struct {
// AlertingFileExport is the full provisioned file export.
// swagger:model
type AlertingFileExport = file.AlertingFileExport
func (a *AlertRuleGroup) ToModel() (models.AlertRuleGroup, error) {
ruleGroup := models.AlertRuleGroup{
Title: a.Title,
FolderUID: a.FolderUID,
Interval: a.Interval,
}
for i := range a.Rules {
converted, err := a.Rules[i].UpstreamModel()
if err != nil {
return models.AlertRuleGroup{}, err
}
ruleGroup.Rules = append(ruleGroup.Rules, converted)
}
return ruleGroup, nil
}
func NewAlertRuleGroupFromModel(d models.AlertRuleGroup) AlertRuleGroup {
rules := make([]ProvisionedAlertRule, 0, len(d.Rules))
for i := range d.Rules {
rules = append(rules, NewAlertRule(d.Rules[i], d.Provenance))
}
return AlertRuleGroup{
Title: d.Title,
FolderUID: d.FolderUID,
Interval: d.Interval,
Rules: rules,
}
}
@@ -1,35 +0,0 @@
package definitions
import (
"testing"
"github.com/stretchr/testify/require"
)
func TestToModel(t *testing.T) {
t.Run("if no rules are provided the rule field should be nil", func(t *testing.T) {
ruleGroup := AlertRuleGroup{
Title: "123",
FolderUID: "123",
Interval: 10,
}
tm, err := ruleGroup.ToModel()
require.NoError(t, err)
require.Nil(t, tm.Rules)
})
t.Run("if rules are provided the rule field should be not nil", func(t *testing.T) {
ruleGroup := AlertRuleGroup{
Title: "123",
FolderUID: "123",
Interval: 10,
Rules: []ProvisionedAlertRule{
{
UID: "1",
},
},
}
tm, err := ruleGroup.ToModel()
require.NoError(t, err)
require.Len(t, tm.Rules, 1)
})
}
@@ -2,8 +2,6 @@ package definitions
import (
"github.com/prometheus/alertmanager/config"
"github.com/grafana/grafana/pkg/services/ngalert/models"
)
// swagger:route GET /api/v1/provisioning/mute-timings provisioning stable RouteGetMuteTimings
@@ -71,7 +69,7 @@ type MuteTimingPayload struct {
// swagger:model
type MuteTimeInterval struct {
config.MuteTimeInterval `json:",inline" yaml:",inline"`
Provenance models.Provenance `json:"provenance,omitempty"`
Provenance Provenance `json:"provenance,omitempty"`
}
func (mt *MuteTimeInterval) ResourceType() string {
@@ -1,9 +1,5 @@
package definitions
import (
"github.com/grafana/grafana/pkg/services/ngalert/models"
)
// swagger:route GET /api/v1/provisioning/templates provisioning stable RouteGetTemplates
//
// Get all notification templates.
@@ -47,9 +43,9 @@ type RouteGetTemplateParam struct {
// swagger:model
type NotificationTemplate struct {
Name string `json:"name"`
Template string `json:"template"`
Provenance models.Provenance `json:"provenance,omitempty"`
Name string `json:"name"`
Template string `json:"template"`
Provenance Provenance `json:"provenance,omitempty"`
}
// swagger:model