172 lines
5.9 KiB
Go
172 lines
5.9 KiB
Go
package notifier
|
|
|
|
import (
|
|
"encoding/json"
|
|
"fmt"
|
|
|
|
alertingNotify "github.com/grafana/alerting/notify"
|
|
alertingTemplates "github.com/grafana/alerting/templates"
|
|
|
|
apimodels "github.com/grafana/grafana/pkg/services/ngalert/api/tooling/definitions"
|
|
"github.com/grafana/grafana/pkg/services/ngalert/models"
|
|
"github.com/grafana/grafana/pkg/services/ngalert/notifier/legacy_storage"
|
|
)
|
|
|
|
func PostableApiReceiversToReceivers(postables []*apimodels.PostableApiReceiver, storedProvenances map[string]models.Provenance) ([]*models.Receiver, error) {
|
|
receivers := make([]*models.Receiver, 0, len(postables))
|
|
for _, postable := range postables {
|
|
r, err := PostableApiReceiverToReceiver(postable, getReceiverProvenance(storedProvenances, postable))
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
receivers = append(receivers, r)
|
|
}
|
|
return receivers, nil
|
|
}
|
|
|
|
func PostableApiReceiverToReceiver(postable *apimodels.PostableApiReceiver, provenance models.Provenance) (*models.Receiver, error) {
|
|
integrations, err := PostableGrafanaReceiversToIntegrations(postable.GrafanaManagedReceivers)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
r := &models.Receiver{
|
|
UID: legacy_storage.NameToUid(postable.GetName()), // TODO replace with stable UID.
|
|
Name: postable.GetName(),
|
|
Integrations: integrations,
|
|
Provenance: provenance,
|
|
}
|
|
r.Version = r.Fingerprint()
|
|
return r, nil
|
|
}
|
|
|
|
func PostableGrafanaReceiversToIntegrations(postables []*apimodels.PostableGrafanaReceiver) ([]*models.Integration, error) {
|
|
integrations := make([]*models.Integration, 0, len(postables))
|
|
for _, cfg := range postables {
|
|
integration, err := PostableGrafanaReceiverToIntegration(cfg)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
integrations = append(integrations, integration)
|
|
}
|
|
|
|
return integrations, nil
|
|
}
|
|
|
|
func PostableGrafanaReceiverToIntegration(p *apimodels.PostableGrafanaReceiver) (*models.Integration, error) {
|
|
config, err := models.IntegrationConfigFromType(p.Type)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
integration := &models.Integration{
|
|
UID: p.UID,
|
|
Name: p.Name,
|
|
Config: config,
|
|
DisableResolveMessage: p.DisableResolveMessage,
|
|
Settings: make(map[string]any, len(p.Settings)),
|
|
SecureSettings: make(map[string]string, len(p.SecureSettings)),
|
|
}
|
|
|
|
if p.Settings != nil {
|
|
if err := json.Unmarshal(p.Settings, &integration.Settings); err != nil {
|
|
return nil, fmt.Errorf("integration '%s' of receiver '%s' has settings that cannot be parsed as JSON: %w", integration.Config.Type, p.Name, err)
|
|
}
|
|
}
|
|
|
|
for k, v := range p.SecureSettings {
|
|
if v != "" {
|
|
integration.SecureSettings[k] = v
|
|
}
|
|
}
|
|
|
|
return integration, nil
|
|
}
|
|
|
|
// getReceiverProvenance determines the provenance of a definitions.PostableApiReceiver based on the provenance of its integrations.
|
|
func getReceiverProvenance(storedProvenances map[string]models.Provenance, r *apimodels.PostableApiReceiver) models.Provenance {
|
|
if len(r.GrafanaManagedReceivers) == 0 {
|
|
return models.ProvenanceNone
|
|
}
|
|
|
|
// Current provisioning works on the integration level, so we need some way to determine the provenance of the
|
|
// entire receiver. All integrations in a receiver should have the same provenance, but we don't want to rely on
|
|
// this assumption in case the first provenance is None and a later one is not. To this end, we return the first
|
|
// non-zero provenance we find.
|
|
for _, contactPoint := range r.GrafanaManagedReceivers {
|
|
if p, exists := storedProvenances[contactPoint.UID]; exists && p != models.ProvenanceNone {
|
|
return p
|
|
}
|
|
}
|
|
return models.ProvenanceNone
|
|
}
|
|
|
|
func PostableGrafanaReceiverToGrafanaIntegrationConfig(p *apimodels.PostableGrafanaReceiver) *alertingNotify.GrafanaIntegrationConfig {
|
|
return &alertingNotify.GrafanaIntegrationConfig{
|
|
UID: p.UID,
|
|
Name: p.Name,
|
|
Type: p.Type,
|
|
DisableResolveMessage: p.DisableResolveMessage,
|
|
Settings: json.RawMessage(p.Settings),
|
|
SecureSettings: p.SecureSettings,
|
|
}
|
|
}
|
|
|
|
func PostableApiReceiverToApiReceiver(r *apimodels.PostableApiReceiver) *alertingNotify.APIReceiver {
|
|
integrations := alertingNotify.GrafanaIntegrations{
|
|
Integrations: make([]*alertingNotify.GrafanaIntegrationConfig, 0, len(r.GrafanaManagedReceivers)),
|
|
}
|
|
for _, cfg := range r.GrafanaManagedReceivers {
|
|
integrations.Integrations = append(integrations.Integrations, PostableGrafanaReceiverToGrafanaIntegrationConfig(cfg))
|
|
}
|
|
|
|
return &alertingNotify.APIReceiver{
|
|
ConfigReceiver: r.Receiver,
|
|
GrafanaIntegrations: integrations,
|
|
}
|
|
}
|
|
|
|
func PostableApiAlertingConfigToApiReceivers(c apimodels.PostableApiAlertingConfig) []*alertingNotify.APIReceiver {
|
|
apiReceivers := make([]*alertingNotify.APIReceiver, 0, len(c.Receivers))
|
|
for _, receiver := range c.Receivers {
|
|
apiReceivers = append(apiReceivers, PostableApiReceiverToApiReceiver(receiver))
|
|
}
|
|
return apiReceivers
|
|
}
|
|
|
|
// ToTemplateDefinitions converts the given PostableUserConfig's TemplateFiles to a slice of TemplateDefinitions.
|
|
func ToTemplateDefinitions(cfg *apimodels.PostableUserConfig) []alertingTemplates.TemplateDefinition {
|
|
out := make([]alertingTemplates.TemplateDefinition, 0, len(cfg.TemplateFiles))
|
|
for name, tmpl := range cfg.TemplateFiles {
|
|
out = append(out, alertingTemplates.TemplateDefinition{
|
|
Name: name,
|
|
Template: tmpl,
|
|
})
|
|
}
|
|
return out
|
|
}
|
|
|
|
// Silence-specific compat functions to convert between grafana/alerting and model types.
|
|
|
|
func GettableSilenceToSilence(s alertingNotify.GettableSilence) *models.Silence {
|
|
sil := models.Silence(s)
|
|
return &sil
|
|
}
|
|
|
|
func GettableSilencesToSilences(silences alertingNotify.GettableSilences) []*models.Silence {
|
|
res := make([]*models.Silence, 0, len(silences))
|
|
for _, sil := range silences {
|
|
res = append(res, GettableSilenceToSilence(*sil))
|
|
}
|
|
return res
|
|
}
|
|
|
|
func SilenceToPostableSilence(s models.Silence) *alertingNotify.PostableSilence {
|
|
var id string
|
|
if s.ID != nil {
|
|
id = *s.ID
|
|
}
|
|
return &alertingNotify.PostableSilence{
|
|
ID: id,
|
|
Silence: s.Silence,
|
|
}
|
|
}
|