2023-10-12 07:43:10 -05:00
|
|
|
package migration
|
|
|
|
|
|
|
|
import (
|
|
|
|
"context"
|
2024-01-05 04:37:13 -06:00
|
|
|
"errors"
|
2023-10-12 07:43:10 -05:00
|
|
|
"fmt"
|
|
|
|
|
2024-01-05 04:37:13 -06:00
|
|
|
"github.com/grafana/grafana/pkg/infra/log"
|
2024-01-25 04:10:35 -06:00
|
|
|
"github.com/grafana/grafana/pkg/infra/metrics"
|
2023-12-19 12:25:13 -06:00
|
|
|
legacymodels "github.com/grafana/grafana/pkg/services/alerting/models"
|
2024-01-05 04:37:13 -06:00
|
|
|
"github.com/grafana/grafana/pkg/services/dashboards"
|
2023-10-12 17:12:40 -05:00
|
|
|
migmodels "github.com/grafana/grafana/pkg/services/ngalert/migration/models"
|
2023-10-12 07:43:10 -05:00
|
|
|
)
|
|
|
|
|
2024-01-05 04:37:13 -06:00
|
|
|
// ErrOrphanedAlert is used for legacy alerts that are missing their dashboard.
|
|
|
|
var ErrOrphanedAlert = errors.New("orphaned")
|
2023-10-12 07:43:10 -05:00
|
|
|
|
2024-01-05 04:37:13 -06:00
|
|
|
func (om *OrgMigration) migrateAlerts(ctx context.Context, l log.Logger, alerts []*legacymodels.Alert, dashboard *dashboards.Dashboard) []*migmodels.AlertPair {
|
|
|
|
pairs := make([]*migmodels.AlertPair, 0, len(alerts))
|
2023-10-12 07:43:10 -05:00
|
|
|
for _, da := range alerts {
|
2024-01-05 04:37:13 -06:00
|
|
|
al := l.New("ruleId", da.ID, "ruleName", da.Name)
|
|
|
|
|
|
|
|
alertRule, err := om.migrateAlert(ctx, al, da, dashboard)
|
2023-10-12 07:43:10 -05:00
|
|
|
if err != nil {
|
2024-01-05 04:37:13 -06:00
|
|
|
al.Warn("Failed to migrate alert", "error", err)
|
|
|
|
pairs = append(pairs, migmodels.NewAlertPair(da, err))
|
|
|
|
continue
|
2023-10-12 07:43:10 -05:00
|
|
|
}
|
2024-01-05 04:37:13 -06:00
|
|
|
|
|
|
|
pair := migmodels.NewAlertPair(da, nil)
|
|
|
|
pair.Rule = alertRule
|
|
|
|
pairs = append(pairs, pair)
|
2023-10-12 07:43:10 -05:00
|
|
|
}
|
|
|
|
|
2024-01-05 04:37:13 -06:00
|
|
|
return pairs
|
2023-10-12 07:43:10 -05:00
|
|
|
}
|
|
|
|
|
2024-01-05 04:37:13 -06:00
|
|
|
func (om *OrgMigration) migrateDashboard(ctx context.Context, dashID int64, alerts []*legacymodels.Alert) *migmodels.DashboardUpgrade {
|
|
|
|
dashboard, err := om.migrationStore.GetDashboard(ctx, om.orgID, dashID)
|
2023-10-12 07:43:10 -05:00
|
|
|
if err != nil {
|
2024-01-05 04:37:13 -06:00
|
|
|
if errors.Is(err, dashboards.ErrDashboardNotFound) {
|
|
|
|
err = fmt.Errorf("%w: missing dashboard", ErrOrphanedAlert)
|
|
|
|
}
|
|
|
|
du := migmodels.NewDashboardUpgrade(dashID)
|
|
|
|
du.AddAlertErrors(err, alerts...)
|
|
|
|
return du
|
2023-10-12 07:43:10 -05:00
|
|
|
}
|
2024-01-05 04:37:13 -06:00
|
|
|
l := om.log.New(
|
|
|
|
"dashboardTitle", dashboard.Title,
|
|
|
|
"dashboardUid", dashboard.UID,
|
|
|
|
)
|
|
|
|
l.Info("Migrating alerts for dashboard", "alertCount", len(alerts))
|
|
|
|
|
|
|
|
du := migmodels.NewDashboardUpgrade(dashID)
|
|
|
|
du.UID = dashboard.UID
|
|
|
|
du.Title = dashboard.Title
|
2024-01-25 04:10:35 -06:00
|
|
|
metrics.MFolderIDsServiceCount.WithLabelValues(metrics.NGAlerts).Inc()
|
2024-01-05 04:37:13 -06:00
|
|
|
// nolint:staticcheck
|
|
|
|
du.FolderID = dashboard.FolderID
|
2023-10-12 07:43:10 -05:00
|
|
|
|
2024-01-05 04:37:13 -06:00
|
|
|
pairs := om.migrateAlerts(ctx, l, alerts, dashboard)
|
|
|
|
for _, pair := range pairs {
|
|
|
|
du.MigratedAlerts[pair.LegacyRule.PanelID] = pair
|
|
|
|
}
|
|
|
|
return du
|
2023-10-12 07:43:10 -05:00
|
|
|
}
|
|
|
|
|
2024-01-05 04:37:13 -06:00
|
|
|
func (om *OrgMigration) migrateOrgAlerts(ctx context.Context) ([]*migmodels.DashboardUpgrade, error) {
|
2023-10-12 07:43:10 -05:00
|
|
|
mappedAlerts, cnt, err := om.migrationStore.GetOrgDashboardAlerts(ctx, om.orgID)
|
|
|
|
if err != nil {
|
2024-01-05 04:37:13 -06:00
|
|
|
return nil, fmt.Errorf("load alerts: %w", err)
|
2023-10-12 07:43:10 -05:00
|
|
|
}
|
|
|
|
om.log.Info("Alerts found to migrate", "alerts", cnt)
|
|
|
|
|
2024-01-05 04:37:13 -06:00
|
|
|
dashboardUpgrades := make([]*migmodels.DashboardUpgrade, 0, len(mappedAlerts))
|
2023-10-12 07:43:10 -05:00
|
|
|
for dashID, alerts := range mappedAlerts {
|
2024-01-05 04:37:13 -06:00
|
|
|
du := om.migrateDashboard(ctx, dashID, alerts)
|
|
|
|
dashboardUpgrades = append(dashboardUpgrades, du)
|
2023-10-12 07:43:10 -05:00
|
|
|
}
|
2024-01-05 04:37:13 -06:00
|
|
|
return dashboardUpgrades, nil
|
2023-10-12 07:43:10 -05:00
|
|
|
}
|
|
|
|
|
2024-01-05 04:37:13 -06:00
|
|
|
func (om *OrgMigration) migrateOrgChannels(ctx context.Context) ([]*migmodels.ContactPair, error) {
|
2023-10-12 07:43:10 -05:00
|
|
|
channels, err := om.migrationStore.GetNotificationChannels(ctx, om.orgID)
|
|
|
|
if err != nil {
|
|
|
|
return nil, fmt.Errorf("load notification channels: %w", err)
|
|
|
|
}
|
|
|
|
|
2024-01-05 04:37:13 -06:00
|
|
|
pairs, err := om.migrateChannels(channels)
|
2023-10-12 07:43:10 -05:00
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
2024-01-05 04:37:13 -06:00
|
|
|
return pairs, nil
|
2023-10-12 07:43:10 -05:00
|
|
|
}
|
|
|
|
|
2024-01-05 04:37:13 -06:00
|
|
|
func (om *OrgMigration) migrateOrg(ctx context.Context) ([]*migmodels.DashboardUpgrade, []*migmodels.ContactPair, error) {
|
2023-10-12 07:43:10 -05:00
|
|
|
om.log.Info("Migrating alerts for organisation")
|
2024-01-05 04:37:13 -06:00
|
|
|
pairs, err := om.migrateOrgChannels(ctx)
|
2023-10-12 07:43:10 -05:00
|
|
|
if err != nil {
|
2024-01-05 04:37:13 -06:00
|
|
|
return nil, nil, fmt.Errorf("migrate channels: %w", err)
|
2023-10-12 07:43:10 -05:00
|
|
|
}
|
|
|
|
|
2024-01-05 04:37:13 -06:00
|
|
|
dashboardUpgrades, err := om.migrateOrgAlerts(ctx)
|
2023-10-12 07:43:10 -05:00
|
|
|
if err != nil {
|
2024-01-05 04:37:13 -06:00
|
|
|
return nil, nil, fmt.Errorf("migrate alerts: %w", err)
|
2023-10-12 07:43:10 -05:00
|
|
|
}
|
|
|
|
|
2024-01-05 04:37:13 -06:00
|
|
|
return dashboardUpgrades, pairs, nil
|
2023-10-12 07:43:10 -05:00
|
|
|
}
|