2024-07-27 05:45:33 +08:00
|
|
|
package legacy_storage
|
|
|
|
|
|
|
|
import (
|
|
|
|
"encoding/base64"
|
2024-08-26 22:47:53 +08:00
|
|
|
"encoding/json"
|
2025-06-20 23:45:01 +08:00
|
|
|
"fmt"
|
2024-08-26 22:47:53 +08:00
|
|
|
"maps"
|
|
|
|
|
|
|
|
alertingNotify "github.com/grafana/alerting/notify"
|
2025-10-07 23:08:16 +08:00
|
|
|
"github.com/grafana/alerting/receivers/schema"
|
2024-08-26 22:47:53 +08:00
|
|
|
|
|
|
|
apimodels "github.com/grafana/grafana/pkg/services/ngalert/api/tooling/definitions"
|
|
|
|
"github.com/grafana/grafana/pkg/services/ngalert/models"
|
2024-07-27 05:45:33 +08:00
|
|
|
)
|
|
|
|
|
2024-10-05 04:52:38 +08:00
|
|
|
var NameToUid = models.NameToUid
|
2024-07-27 05:45:33 +08:00
|
|
|
|
|
|
|
func UidToName(uid string) (string, error) {
|
|
|
|
data, err := base64.RawURLEncoding.DecodeString(uid)
|
|
|
|
if err != nil {
|
|
|
|
return uid, err
|
|
|
|
}
|
|
|
|
return string(data), nil
|
|
|
|
}
|
2024-08-26 22:47:53 +08:00
|
|
|
|
|
|
|
func IntegrationToPostableGrafanaReceiver(integration *models.Integration) (*apimodels.PostableGrafanaReceiver, error) {
|
|
|
|
postable := &apimodels.PostableGrafanaReceiver{
|
|
|
|
UID: integration.UID,
|
|
|
|
Name: integration.Name,
|
2025-10-07 23:08:16 +08:00
|
|
|
Type: string(integration.Config.Type()),
|
2024-08-26 22:47:53 +08:00
|
|
|
DisableResolveMessage: integration.DisableResolveMessage,
|
|
|
|
SecureSettings: maps.Clone(integration.SecureSettings),
|
|
|
|
}
|
|
|
|
|
2024-08-30 01:00:55 +08:00
|
|
|
// Alertmanager will fail validation with nil Settings , so ensure we always have at least an empty map.
|
|
|
|
settings := integration.Settings
|
|
|
|
if settings == nil {
|
|
|
|
settings = make(map[string]any)
|
|
|
|
}
|
|
|
|
|
|
|
|
jsonBytes, err := json.Marshal(settings)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
2024-08-26 22:47:53 +08:00
|
|
|
}
|
2024-08-30 01:00:55 +08:00
|
|
|
postable.Settings = jsonBytes
|
2024-08-26 22:47:53 +08:00
|
|
|
return postable, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func ReceiverToPostableApiReceiver(r *models.Receiver) (*apimodels.PostableApiReceiver, error) {
|
|
|
|
integrations := apimodels.PostableGrafanaReceivers{
|
|
|
|
GrafanaManagedReceivers: make([]*apimodels.PostableGrafanaReceiver, 0, len(r.Integrations)),
|
|
|
|
}
|
|
|
|
for _, cfg := range r.Integrations {
|
|
|
|
postable, err := IntegrationToPostableGrafanaReceiver(cfg)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
integrations.GrafanaManagedReceivers = append(integrations.GrafanaManagedReceivers, postable)
|
|
|
|
}
|
|
|
|
|
|
|
|
return &apimodels.PostableApiReceiver{
|
|
|
|
Receiver: alertingNotify.ConfigReceiver{
|
|
|
|
Name: r.Name,
|
|
|
|
},
|
|
|
|
PostableGrafanaReceivers: integrations,
|
|
|
|
}, nil
|
|
|
|
}
|
2025-06-20 23:45:01 +08:00
|
|
|
|
2025-09-16 21:32:04 +08:00
|
|
|
func PostableApiReceiverToReceiver(postable *apimodels.PostableApiReceiver, provenance models.Provenance, origin models.ResourceOrigin) (*models.Receiver, error) {
|
2025-06-20 23:45:01 +08:00
|
|
|
integrations, err := PostableGrafanaReceiversToIntegrations(postable.GrafanaManagedReceivers)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
r := &models.Receiver{
|
|
|
|
UID: NameToUid(postable.GetName()), // TODO replace with stable UID.
|
|
|
|
Name: postable.GetName(),
|
|
|
|
Integrations: integrations,
|
|
|
|
Provenance: provenance,
|
2025-09-16 21:32:04 +08:00
|
|
|
Origin: origin,
|
2025-06-20 23:45:01 +08:00
|
|
|
}
|
|
|
|
r.Version = r.Fingerprint()
|
|
|
|
return r, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
// GetReceiverProvenance determines the provenance of a definitions.PostableApiReceiver based on the provenance of its integrations.
|
2025-09-16 21:32:04 +08:00
|
|
|
func GetReceiverProvenance(storedProvenances map[string]models.Provenance, r *apimodels.PostableApiReceiver, origin models.ResourceOrigin) models.Provenance {
|
|
|
|
if origin == models.ResourceOriginImported {
|
|
|
|
return models.ProvenanceConvertedPrometheus
|
|
|
|
}
|
|
|
|
|
2025-09-05 22:46:46 +08:00
|
|
|
if len(r.GrafanaManagedReceivers) == 0 || len(storedProvenances) == 0 {
|
2025-06-20 23:45:01 +08:00
|
|
|
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 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) {
|
2025-10-07 23:08:16 +08:00
|
|
|
integrationType, err := alertingNotify.IntegrationTypeFromString(p.Type)
|
2025-06-20 23:45:01 +08:00
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
2025-10-07 23:08:16 +08:00
|
|
|
config, ok := alertingNotify.GetSchemaVersionForIntegration(integrationType, schema.V1)
|
|
|
|
if !ok {
|
|
|
|
return nil, fmt.Errorf("integration type [%s] does not have schema of version %s", integrationType, schema.V1)
|
|
|
|
}
|
2025-06-20 23:45:01 +08:00
|
|
|
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 {
|
2025-10-07 23:08:16 +08:00
|
|
|
return nil, fmt.Errorf("integration '%s' of receiver '%s' has settings that cannot be parsed as JSON: %w", integration.Config.Type(), p.Name, err)
|
2025-06-20 23:45:01 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
for k, v := range p.SecureSettings {
|
|
|
|
if v != "" {
|
|
|
|
integration.SecureSettings[k] = v
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return integration, nil
|
|
|
|
}
|