[v9.4.x] Alerting: Update migration to put alerts to the default folder if dashboard folder is missing (#66593)
Alerting: Update migration to put alerts to the default folder if dashboard folder is missing (#65577)
* extract function
* use context logger
* put alert to general folder if folder is missing
* move folderHelper init
* add test
* Update pkg/services/sqlstore/migrations/ualert/ualert.go
Co-authored-by: Matthew Jacobson <matthew.jacobson@grafana.com>
---------
Co-authored-by: Matthew Jacobson <matthew.jacobson@grafana.com>
(cherry picked from commit 7b2f44762e)
Co-authored-by: Yuri Tseretyan <yuriy.tseretyan@grafana.com>
This commit is contained in:
co-authored by
Yuri Tseretyan
parent
8f761197a4
commit
b4d141ed1c
@@ -573,6 +573,43 @@ func TestDashAlertMigration(t *testing.T) {
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("when folder is missing put alert in General folder", func(t *testing.T) {
|
||||
o := createOrg(t, 1)
|
||||
folder1 := createDashboard(t, 1, o.ID, "folder-1")
|
||||
folder1.IsFolder = true
|
||||
dash1 := createDashboard(t, 3, o.ID, "dash1")
|
||||
dash1.FolderID = folder1.ID
|
||||
dash2 := createDashboard(t, 4, o.ID, "dash2")
|
||||
dash2.FolderID = 22 // missing folder
|
||||
|
||||
a1 := createAlert(t, o.ID, dash1.ID, int64(1), "alert-1", []string{})
|
||||
a2 := createAlert(t, o.ID, dash2.ID, int64(1), "alert-2", []string{})
|
||||
|
||||
_, err := x.Insert(o, folder1, dash1, dash2, a1, a2)
|
||||
require.NoError(t, err)
|
||||
|
||||
runDashAlertMigrationTestRun(t, x)
|
||||
|
||||
rules := getAlertRules(t, x, o.ID)
|
||||
require.Len(t, rules, 2)
|
||||
|
||||
var generalFolder dashboards.Dashboard
|
||||
_, err = x.Table(&dashboards.Dashboard{}).Where("title = ? AND org_id = ?", ualert.GENERAL_FOLDER, o.ID).Get(&generalFolder)
|
||||
require.NoError(t, err)
|
||||
|
||||
require.NotNil(t, generalFolder)
|
||||
|
||||
for _, rule := range rules {
|
||||
var expectedFolder dashboards.Dashboard
|
||||
if rule.Title == a1.Name {
|
||||
expectedFolder = *folder1
|
||||
} else {
|
||||
expectedFolder = generalFolder
|
||||
}
|
||||
require.Equal(t, expectedFolder.UID, rule.NamespaceUID)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
const (
|
||||
|
||||
@@ -263,10 +263,35 @@ func (m *migration) Exec(sess *xorm.Session, mg *migrator.Migrator) error {
|
||||
// cache for the general folders
|
||||
generalFolderCache := make(map[int64]*dashboard)
|
||||
|
||||
folderHelper := folderHelper{
|
||||
sess: sess,
|
||||
mg: mg,
|
||||
}
|
||||
|
||||
gf := func(dash dashboard, da dashAlert) (*dashboard, error) {
|
||||
f, ok := generalFolderCache[dash.OrgId]
|
||||
if !ok {
|
||||
// get or create general folder
|
||||
f, err = folderHelper.getOrCreateGeneralFolder(dash.OrgId)
|
||||
if err != nil {
|
||||
return nil, MigrationError{
|
||||
Err: fmt.Errorf("failed to get or create general folder under organisation %d: %w", dash.OrgId, err),
|
||||
AlertId: da.Id,
|
||||
}
|
||||
}
|
||||
generalFolderCache[dash.OrgId] = f
|
||||
}
|
||||
// No need to assign default permissions to general folder
|
||||
// because they are included to the query result if it's a folder with no permissions
|
||||
// https://github.com/grafana/grafana/blob/076e2ce06a6ecf15804423fcc8dca1b620a321e5/pkg/services/sqlstore/dashboard_acl.go#L109
|
||||
return f, nil
|
||||
}
|
||||
|
||||
// Per org map of newly created rules to which notification channels it should send to.
|
||||
rulesPerOrg := make(map[int64]map[*alertRule][]uidOrID)
|
||||
|
||||
for _, da := range dashAlerts {
|
||||
l := mg.Logger.New("ruleID", da.Id, "ruleName", da.Name, "dashboardUID", da.DashboardUID, "orgID", da.OrgId)
|
||||
newCond, err := transConditions(*da.ParsedSettings, da.OrgId, dsIDMap)
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -290,18 +315,13 @@ func (m *migration) Exec(sess *xorm.Session, mg *migrator.Migrator) error {
|
||||
}
|
||||
}
|
||||
|
||||
folderHelper := folderHelper{
|
||||
sess: sess,
|
||||
mg: mg,
|
||||
}
|
||||
|
||||
var folder *dashboard
|
||||
switch {
|
||||
case dash.HasACL:
|
||||
folderName := getAlertFolderNameFromDashboard(&dash)
|
||||
f, ok := folderCache[folderName]
|
||||
if !ok {
|
||||
mg.Logger.Info("create a new folder for alerts that belongs to dashboard because it has custom permissions", "org", dash.OrgId, "dashboard_uid", dash.Uid, "folder", folderName)
|
||||
l.Info("create a new folder for alerts that belongs to dashboard because it has custom permissions", "folder", folderName)
|
||||
// create folder and assign the permissions of the dashboard (included default and inherited)
|
||||
f, err = folderHelper.createFolder(dash.OrgId, folderName)
|
||||
if err != nil {
|
||||
@@ -331,29 +351,20 @@ func (m *migration) Exec(sess *xorm.Session, mg *migrator.Migrator) error {
|
||||
// get folder if exists
|
||||
f, err := folderHelper.getFolder(dash, da)
|
||||
if err != nil {
|
||||
return MigrationError{
|
||||
Err: err,
|
||||
AlertId: da.Id,
|
||||
}
|
||||
}
|
||||
folder = &f
|
||||
default:
|
||||
f, ok := generalFolderCache[dash.OrgId]
|
||||
if !ok {
|
||||
// get or create general folder
|
||||
f, err = folderHelper.getOrCreateGeneralFolder(dash.OrgId)
|
||||
// If folder does not exist then the dashboard is an orphan and we migrate the alert to the general folder.
|
||||
l.Warn("Failed to find folder for dashboard. Migrate rule to the default folder", "rule_name", da.Name, "dashboard_uid", da.DashboardUID, "missing_folder_id", dash.FolderId)
|
||||
folder, err = gf(dash, da)
|
||||
if err != nil {
|
||||
return MigrationError{
|
||||
Err: fmt.Errorf("failed to get or create general folder under organisation %d: %w", dash.OrgId, err),
|
||||
AlertId: da.Id,
|
||||
}
|
||||
return err
|
||||
}
|
||||
generalFolderCache[dash.OrgId] = f
|
||||
} else {
|
||||
folder = &f
|
||||
}
|
||||
default:
|
||||
folder, err = gf(dash, da)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
// No need to assign default permissions to general folder
|
||||
// because they are included to the query result if it's a folder with no permissions
|
||||
// https://github.com/grafana/grafana/blob/076e2ce06a6ecf15804423fcc8dca1b620a321e5/pkg/services/sqlstore/dashboard_acl.go#L109
|
||||
folder = f
|
||||
}
|
||||
|
||||
if folder.Uid == "" {
|
||||
|
||||
Reference in New Issue
Block a user