diff --git a/pkg/services/sqlstore/migrations/migrations_test.go b/pkg/services/sqlstore/migrations/migrations_test.go index 0bf54752876..23765632f0d 100644 --- a/pkg/services/sqlstore/migrations/migrations_test.go +++ b/pkg/services/sqlstore/migrations/migrations_test.go @@ -5,6 +5,7 @@ import ( . "github.com/grafana/grafana/pkg/services/sqlstore/migrator" "github.com/grafana/grafana/pkg/services/sqlstore/sqlutil" + "github.com/grafana/grafana/pkg/setting" "github.com/stretchr/testify/require" "xorm.io/xorm" ) @@ -23,7 +24,7 @@ func TestMigrations(t *testing.T) { _, err = x.SQL(query).Get(&result) require.Error(t, err) - mg := NewMigrator(x) + mg := NewMigrator(x, &setting.Cfg{}) AddMigrations(mg) expectedMigrations := mg.MigrationsCount() @@ -36,7 +37,7 @@ func TestMigrations(t *testing.T) { require.Equal(t, expectedMigrations, result.Count) - mg = NewMigrator(x) + mg = NewMigrator(x, &setting.Cfg{}) AddMigrations(mg) err = mg.Start() diff --git a/pkg/services/sqlstore/migrations/ualert/permissions.go b/pkg/services/sqlstore/migrations/ualert/permissions.go index 19ae39af805..0110c91a8f8 100644 --- a/pkg/services/sqlstore/migrations/ualert/permissions.go +++ b/pkg/services/sqlstore/migrations/ualert/permissions.go @@ -44,7 +44,6 @@ func (m *migration) createFolder(orgID int64, title string) (*dashboard, error) }), } dash := cmd.getDashboardModel() - var userId int64 = -1 uid, err := m.generateNewDashboardUid(dash.OrgId) if err != nil { @@ -55,9 +54,9 @@ func (m *migration) createFolder(orgID int64, title string) (*dashboard, error) parentVersion := dash.Version dash.setVersion(1) dash.Created = time.Now() - dash.CreatedBy = userId + dash.CreatedBy = FOLDER_CREATED_BY dash.Updated = time.Now() - dash.UpdatedBy = userId + dash.UpdatedBy = FOLDER_CREATED_BY metrics.MApiDashboardInsert.Inc() if _, err = m.sess.Insert(dash); err != nil { diff --git a/pkg/services/sqlstore/migrations/ualert/ualert.go b/pkg/services/sqlstore/migrations/ualert/ualert.go index cb267c4f773..c765ff2d28a 100644 --- a/pkg/services/sqlstore/migrations/ualert/ualert.go +++ b/pkg/services/sqlstore/migrations/ualert/ualert.go @@ -11,6 +11,14 @@ import ( const GENERAL_FOLDER = "General Alerting" const DASHBOARD_FOLDER = "Migrated %s" +// FOLDER_CREATED_BY us used to track folders created by this migration +// during alert migration cleanup. +const FOLDER_CREATED_BY = -8 + +var migTitle = "move dashboard alerts to unified alerting" + +var rmMigTitle = "remove unified alerting data" + type MigrationError struct { AlertId int64 Err error @@ -26,7 +34,31 @@ func AddMigration(mg *migrator.Migrator) { if os.Getenv("UALERT_MIG") == "iDidBackup" { // TODO: unified alerting DB needs to be extacted into ../migrations.go // so it runs and creates the tables before this migration runs. - mg.AddMigration("move dashboard alerts to unified alerting", &migration{}) + logs, err := mg.GetMigrationLog() + if err != nil { + mg.Logger.Crit("alert migration failure: could not get migration log", "error", err) + os.Exit(1) + } + + _, migrationRun := logs[migTitle] + + ngEnabled := mg.Cfg.IsNgAlertEnabled() + + switch { + case ngEnabled && !migrationRun: + // clear the entry of the migration that + err = mg.ClearMigrationEntry(rmMigTitle) + if err != nil { + mg.Logger.Error("alert migration error: could not clear alert migration for removing data", "error", err) + } + mg.AddMigration(migTitle, &migration{}) + case !ngEnabled && migrationRun: + err = mg.ClearMigrationEntry(migTitle) + if err != nil { + mg.Logger.Error("alert migration error: could not clear alert migration", "error", err) + } + mg.AddMigration(rmMigTitle, &rmMigration{}) + } } } @@ -184,3 +216,45 @@ func (m *migration) Exec(sess *xorm.Session, mg *migrator.Migrator) error { return nil } + +type rmMigration struct { + migrator.MigrationBase +} + +func (m *rmMigration) SQL(dialect migrator.Dialect) string { + return "code migration" +} + +func (m *rmMigration) Exec(sess *xorm.Session, mg *migrator.Migrator) error { + _, err := sess.Exec("delete from alert_rule") + if err != nil { + return err + } + + _, err = sess.Exec("delete from alert_rule_version") + if err != nil { + return err + } + + _, err = sess.Exec("delete from dashboard_acl where dashboard_id IN (select id from dashboard where created_by = ?)", FOLDER_CREATED_BY) + if err != nil { + return err + } + + _, err = sess.Exec("delete from dashboard where created_by = ?", FOLDER_CREATED_BY) + if err != nil { + return err + } + + _, err = sess.Exec("delete from alert_configuration") + if err != nil { + return err + } + + _, err = sess.Exec("delete from alert_instance") + if err != nil { + return err + } + + return nil +} diff --git a/pkg/services/sqlstore/migrator/migrator.go b/pkg/services/sqlstore/migrator/migrator.go index f05a87c2af8..b40d7e0468b 100644 --- a/pkg/services/sqlstore/migrator/migrator.go +++ b/pkg/services/sqlstore/migrator/migrator.go @@ -6,6 +6,7 @@ import ( _ "github.com/go-sql-driver/mysql" "github.com/grafana/grafana/pkg/infra/log" + "github.com/grafana/grafana/pkg/setting" "github.com/grafana/grafana/pkg/util/errutil" _ "github.com/lib/pq" _ "github.com/mattn/go-sqlite3" @@ -17,6 +18,7 @@ type Migrator struct { Dialect Dialect migrations []Migration Logger log.Logger + Cfg *setting.Cfg } type MigrationLog struct { @@ -28,12 +30,13 @@ type MigrationLog struct { Timestamp time.Time } -func NewMigrator(engine *xorm.Engine) *Migrator { +func NewMigrator(engine *xorm.Engine, cfg *setting.Cfg) *Migrator { mg := &Migrator{} mg.x = engine mg.Logger = log.New("migrator") mg.migrations = make([]Migration, 0) mg.Dialect = NewDialect(mg.x) + mg.Cfg = cfg return mg } @@ -168,6 +171,16 @@ func (mg *Migrator) exec(m Migration, sess *xorm.Session) error { return nil } +func (mg *Migrator) ClearMigrationEntry(id string) error { + sess := mg.x.NewSession() + defer sess.Close() + _, err := sess.SQL(`DELETE from migration_log where migration_id = ?`, id).Query() + if err != nil { + return fmt.Errorf("failed to clear migration entry %v: %w", id, err) + } + return nil +} + type dbTransactionFunc func(sess *xorm.Session) error func (mg *Migrator) inTransaction(callback dbTransactionFunc) error { diff --git a/pkg/services/sqlstore/sqlstore.go b/pkg/services/sqlstore/sqlstore.go index 05ec397bf27..457e83551f9 100644 --- a/pkg/services/sqlstore/sqlstore.go +++ b/pkg/services/sqlstore/sqlstore.go @@ -85,7 +85,7 @@ func (ss *SQLStore) Init() error { dialect = ss.Dialect if !ss.dbCfg.SkipMigrations { - migrator := migrator.NewMigrator(ss.engine) + migrator := migrator.NewMigrator(ss.engine, ss.Cfg) migrations.AddMigrations(migrator) for _, descriptor := range registry.GetServices() {