grafana/pkg/services/sqlstore/migrations/external_alertmanagers.go
Alex Moreno 45facbba11
Alerting: Remove url based external alertmanagers config (#57918)
* Remove URL-based alertmanagers from endpoint config

* WIP

* Add migration and alertmanagers from admin_configuration

* Empty comment removed

* set BasicAuth true when user is present in url

* Remove Alertmanagers from GET /admin_config payload

* Remove URL-based alertmanager configuration from UI

* Fix new uid generation in external alertmanagers migration

* Fix tests for URL-based external alertmanagers

* Fix API tests

* Add more tests, move migration code to separate file, and remove possible am duplicate urls

* Fix edge cases in migration

* Fix imports

* Remove useless fields and fix created_at/updated_at retrieval

Co-authored-by: George Robinson <george.robinson@grafana.com>
Co-authored-by: Konrad Lalik <konrad.lalik@grafana.com>
2022-11-10 16:34:13 +01:00

126 lines
3.0 KiB
Go

package migrations
import (
"fmt"
"net/url"
"time"
"github.com/grafana/grafana/pkg/components/simplejson"
"github.com/grafana/grafana/pkg/services/datasources"
"github.com/grafana/grafana/pkg/services/sqlstore/migrations/ualert"
"github.com/grafana/grafana/pkg/services/sqlstore/migrator"
"github.com/grafana/grafana/pkg/util"
"xorm.io/xorm"
)
func AddExternalAlertmanagerToDatasourceMigration(mg *migrator.Migrator) {
mg.AddMigration("migrate external alertmanagers to datsourcse", &externalAlertmanagerToDatasources{})
}
type externalAlertmanagerToDatasources struct {
migrator.MigrationBase
}
type AdminConfiguration struct {
OrgID int64 `xorm:"org_id"`
Alertmanagers []string
CreatedAt int64 `xorm:"created_at"`
UpdatedAt int64 `xorm:"updated_at"`
}
func (e externalAlertmanagerToDatasources) SQL(dialect migrator.Dialect) string {
return "migrate external alertmanagers to datasource"
}
func (e externalAlertmanagerToDatasources) Exec(sess *xorm.Session, mg *migrator.Migrator) error {
var results []AdminConfiguration
err := sess.SQL("SELECT org_id, alertmanagers, created_at, updated_at FROM ngalert_configuration").Find(&results)
if err != nil {
return err
}
for _, result := range results {
for _, am := range removeDuplicates(result.Alertmanagers) {
u, err := url.Parse(am)
if err != nil {
return err
}
uri := fmt.Sprintf("%s://%s%s", u.Scheme, u.Host, u.Path)
uid, err := generateNewDatasourceUid(sess, result.OrgID)
if err != nil {
return err
}
ds := &datasources.DataSource{
OrgId: result.OrgID,
Name: fmt.Sprintf("alertmanager-%s", uid),
Type: "alertmanager",
Access: "proxy",
Url: uri,
Created: time.Unix(result.CreatedAt, 0),
Updated: time.Unix(result.UpdatedAt, 0),
Uid: uid,
Version: 1,
JsonData: simplejson.NewFromAny(map[string]interface{}{
"handleGrafanaManagedAlerts": true,
"implementation": "prometheus",
}),
SecureJsonData: map[string][]byte{},
}
if u.User != nil {
ds.BasicAuth = true
ds.BasicAuthUser = u.User.Username()
if password, ok := u.User.Password(); ok {
ds.SecureJsonData = ualert.GetEncryptedJsonData(map[string]string{
"basicAuthPassword": password,
})
}
}
rowsAffected, err := sess.Table("data_source").Insert(ds)
if err != nil {
return err
}
if rowsAffected == 0 {
return fmt.Errorf("expected 1 row, got %d", rowsAffected)
}
}
}
return nil
}
func removeDuplicates(strs []string) []string {
var res []string
found := map[string]bool{}
for _, str := range strs {
if found[str] {
continue
}
found[str] = true
res = append(res, str)
}
return res
}
func generateNewDatasourceUid(sess *xorm.Session, orgId int64) (string, error) {
for i := 0; i < 3; i++ {
uid := util.GenerateShortUID()
exists, err := sess.Table("data_source").Where("uid = ? AND org_id = ?", uid, orgId).Exist()
if err != nil {
return "", err
}
if !exists {
return uid, nil
}
}
return "", datasources.ErrDataSourceFailedGenerateUniqueUid
}