Alerting: Support for Mimir configuration in Grafana Alertmanager (#106402)

This commit is contained in:
Yuri Tseretyan
2025-06-13 16:32:23 +02:00
committed by GitHub
parent 3c0d087186
commit b0ff51a903
6 changed files with 476 additions and 21 deletions
@@ -3,13 +3,17 @@ package definitions
import (
"context"
"encoding/json"
"errors"
"fmt"
"time"
"github.com/go-openapi/strfmt"
alertingTemplates "github.com/grafana/alerting/templates"
amv2 "github.com/prometheus/alertmanager/api/v2/models"
"github.com/prometheus/alertmanager/config"
"github.com/prometheus/alertmanager/pkg/labels"
"github.com/prometheus/common/model"
"gopkg.in/yaml.v3"
"github.com/grafana/alerting/definition"
@@ -263,6 +267,7 @@ type (
PostableApiReceiver = definition.PostableApiReceiver
PostableGrafanaReceivers = definition.PostableGrafanaReceivers
ReceiverType = definition.ReceiverType
MergeResult = definition.MergeResult
)
const (
@@ -643,13 +648,82 @@ type DatasourceUIDReference struct {
DatasourceUID string
}
type ExtraConfiguration struct {
Identifier string `yaml:"identifier" json:"identifier"`
MergeMatchers config.Matchers `yaml:"merge_matchers" json:"merge_matchers"`
TemplateFiles map[string]string `yaml:"template_files" json:"template_files"`
AlertmanagerConfig PostableApiAlertingConfig `yaml:"alertmanager_config" json:"alertmanager_config"`
}
func (c ExtraConfiguration) Validate() error {
if c.Identifier == "" {
return errors.New("identifier is required")
}
if len(c.MergeMatchers) == 0 {
return errors.New("at least one matcher is required")
}
for _, m := range c.MergeMatchers {
if m.Type != labels.MatchEqual {
return errors.New("only matchers with type equal are supported")
}
}
err := c.AlertmanagerConfig.Validate()
if err != nil {
return fmt.Errorf("invalid alertmanager configuration: %w", err)
}
return nil
}
// swagger:model
type PostableUserConfig struct {
TemplateFiles map[string]string `yaml:"template_files" json:"template_files"`
AlertmanagerConfig PostableApiAlertingConfig `yaml:"alertmanager_config" json:"alertmanager_config"`
ExtraConfigs []ExtraConfiguration `yaml:"extra_config,omitempty" json:"extra_config,omitempty"`
amSimple map[string]interface{} `yaml:"-" json:"-"`
}
func (c *PostableUserConfig) GetMergedAlertmanagerConfig() (MergeResult, error) {
if len(c.ExtraConfigs) == 0 {
return MergeResult{
Config: c.AlertmanagerConfig,
}, nil
}
// support only one config for now
mimirCfg := c.ExtraConfigs[0]
opts := definition.MergeOpts{
DedupSuffix: mimirCfg.Identifier,
SubtreeMatchers: mimirCfg.MergeMatchers,
}
if err := opts.Validate(); err != nil {
return MergeResult{}, fmt.Errorf("invalid merge options: %w", err)
}
return definition.Merge(c.AlertmanagerConfig, mimirCfg.AlertmanagerConfig, opts) // for now support only the first extra config
}
// GetMergedTemplateDefinitions converts the given PostableUserConfig's TemplateFiles to a slice of TemplateDefinitions.
func (c *PostableUserConfig) GetMergedTemplateDefinitions() []alertingTemplates.TemplateDefinition {
out := make([]alertingTemplates.TemplateDefinition, 0, len(c.TemplateFiles))
for name, tmpl := range c.TemplateFiles {
out = append(out, alertingTemplates.TemplateDefinition{
Name: name,
Template: tmpl,
Kind: alertingTemplates.GrafanaKind,
})
}
if len(c.ExtraConfigs) == 0 {
return out
}
// support only one config for now
for name, tmpl := range c.ExtraConfigs[0].TemplateFiles {
out = append(out, alertingTemplates.TemplateDefinition{
Name: name,
Template: tmpl,
Kind: alertingTemplates.MimirKind,
})
}
return out
}
func (c *PostableUserConfig) UnmarshalJSON(b []byte) error {
type plain PostableUserConfig
if err := json.Unmarshal(b, (*plain)(c)); err != nil {
@@ -661,6 +735,15 @@ func (c *PostableUserConfig) UnmarshalJSON(b []byte) error {
return err
}
if len(c.ExtraConfigs) > 1 {
return errors.New("only one extra config is supported")
}
for _, extraConfig := range c.ExtraConfigs {
if err := extraConfig.Validate(); err != nil {
return fmt.Errorf("extra configuration is invalid: %w", err)
}
}
type intermediate struct {
AlertmanagerConfig map[string]interface{} `yaml:"alertmanager_config" json:"alertmanager_config"`
}