Files
grafana/pkg/services/ngalert/migration/ualert.go

116 lines
3.5 KiB
Go

package migration
import (
"context"
"fmt"
apimodels "github.com/grafana/grafana/pkg/services/ngalert/api/tooling/definitions"
migrationStore "github.com/grafana/grafana/pkg/services/ngalert/migration/store"
"github.com/grafana/grafana/pkg/services/ngalert/models"
)
func (om *OrgMigration) migrateAlerts(ctx context.Context, alerts []*migrationStore.DashAlert, dashboardUID string, folderUID string) ([]*AlertPair, error) {
log := om.log.New(
"dashboardUID", dashboardUID,
"newFolderUID", folderUID,
)
pairs := make([]*AlertPair, 0, len(alerts))
for _, da := range alerts {
al := log.New("ruleID", da.ID, "ruleName", da.Name)
alertRule, err := om.migrateAlert(ctx, al, da, dashboardUID, folderUID)
if err != nil {
return nil, fmt.Errorf("migrate alert: %w", err)
}
pairs = append(pairs, &AlertPair{AlertRule: alertRule, DashAlert: da})
}
return pairs, nil
}
func (om *OrgMigration) migrateDashboard(ctx context.Context, dashID int64, alerts []*migrationStore.DashAlert) ([]*AlertPair, error) {
dash, newFolder, err := om.getOrCreateMigratedFolder(ctx, om.log, dashID)
if err != nil {
return nil, fmt.Errorf("get or create migrated folder: %w", err)
}
pairs, err := om.migrateAlerts(ctx, alerts, dash.UID, newFolder.UID)
if err != nil {
return nil, fmt.Errorf("migrate and save alerts: %w", err)
}
return pairs, nil
}
func (om *OrgMigration) migrateOrgAlerts(ctx context.Context) ([]*AlertPair, error) {
mappedAlerts, cnt, err := om.migrationStore.GetOrgDashboardAlerts(ctx, om.orgID)
if err != nil {
return nil, fmt.Errorf("load alerts: %w", err)
}
om.log.Info("Alerts found to migrate", "alerts", cnt)
pairs := make([]*AlertPair, 0, cnt)
for dashID, alerts := range mappedAlerts {
dashPairs, err := om.migrateDashboard(ctx, dashID, alerts)
if err != nil {
return nil, fmt.Errorf("migrate and save dashboard '%d': %w", dashID, err)
}
pairs = append(pairs, dashPairs...)
}
return pairs, nil
}
func (om *OrgMigration) migrateOrgChannels(ctx context.Context, pairs []*AlertPair) (*apimodels.PostableUserConfig, error) {
channels, err := om.migrationStore.GetNotificationChannels(ctx, om.orgID)
if err != nil {
return nil, fmt.Errorf("load notification channels: %w", err)
}
amConfig, err := om.migrateChannels(channels, pairs)
if err != nil {
return nil, err
}
return amConfig, nil
}
func (om *OrgMigration) migrateOrg(ctx context.Context) error {
om.log.Info("Migrating alerts for organisation")
pairs, err := om.migrateOrgAlerts(ctx)
if err != nil {
return fmt.Errorf("migrate alerts: %w", err)
}
// This must happen before we insert the rules into the database because it modifies the alert labels. This will
// be changed in the future when we improve how notification policies are created.
amConfig, err := om.migrateOrgChannels(ctx, pairs)
if err != nil {
return fmt.Errorf("migrate channels: %w", err)
}
if err := om.writeSilencesFile(); err != nil {
return fmt.Errorf("write silence file for org %d: %w", om.orgID, err)
}
if len(pairs) > 0 {
om.log.Debug("Inserting migrated alert rules", "count", len(pairs))
rules := make([]models.AlertRule, 0, len(pairs))
for _, p := range pairs {
rules = append(rules, *p.AlertRule)
}
err := om.migrationStore.InsertAlertRules(ctx, rules...)
if err != nil {
return fmt.Errorf("insert alert rules: %w", err)
}
}
if amConfig != nil {
if err := om.migrationStore.SaveAlertmanagerConfiguration(ctx, om.orgID, amConfig); err != nil {
return err
}
}
return nil
}