Migrate wrong datasource UIDs (#86598)
This commit is contained in:
@@ -64,7 +64,7 @@ func ProvideService(
|
||||
quotaService quota.Service, pluginStore pluginstore.Store,
|
||||
) (*Service, error) {
|
||||
dslogger := log.New("datasources")
|
||||
store := &SqlStore{db: db, logger: dslogger}
|
||||
store := &SqlStore{db: db, logger: dslogger, features: features}
|
||||
s := &Service{
|
||||
SQLStore: store,
|
||||
SecretsStore: secretsStore,
|
||||
|
||||
@@ -16,6 +16,7 @@ import (
|
||||
"github.com/grafana/grafana/pkg/infra/metrics"
|
||||
ac "github.com/grafana/grafana/pkg/services/accesscontrol"
|
||||
"github.com/grafana/grafana/pkg/services/datasources"
|
||||
"github.com/grafana/grafana/pkg/services/featuremgmt"
|
||||
"github.com/grafana/grafana/pkg/services/quota"
|
||||
"github.com/grafana/grafana/pkg/services/sqlstore"
|
||||
"github.com/grafana/grafana/pkg/util"
|
||||
@@ -36,8 +37,9 @@ type Store interface {
|
||||
}
|
||||
|
||||
type SqlStore struct {
|
||||
db db.DB
|
||||
logger log.Logger
|
||||
db db.DB
|
||||
logger log.Logger
|
||||
features featuremgmt.FeatureToggles
|
||||
}
|
||||
|
||||
func CreateStore(db db.DB, logger log.Logger) *SqlStore {
|
||||
@@ -59,11 +61,17 @@ func (ss *SqlStore) GetDataSource(ctx context.Context, query *datasources.GetDat
|
||||
})
|
||||
}
|
||||
|
||||
func (ss *SqlStore) getDataSource(ctx context.Context, query *datasources.GetDataSourceQuery, sess *db.Session) (*datasources.DataSource, error) {
|
||||
func (ss *SqlStore) getDataSource(_ context.Context, query *datasources.GetDataSourceQuery, sess *db.Session) (*datasources.DataSource, error) {
|
||||
if query.OrgID == 0 || (query.ID == 0 && len(query.Name) == 0 && len(query.UID) == 0) {
|
||||
return nil, datasources.ErrDataSourceIdentifierNotSet
|
||||
}
|
||||
|
||||
if len(query.UID) > 0 {
|
||||
if err := util.ValidateUID(query.UID); err != nil {
|
||||
logDeprecatedInvalidDsUid(ss.logger, query.UID, query.Name, "read", fmt.Errorf("invalid UID"))
|
||||
}
|
||||
}
|
||||
|
||||
datasource := &datasources.DataSource{Name: query.Name, OrgID: query.OrgID, ID: query.ID, UID: query.UID}
|
||||
has, err := sess.Get(datasource)
|
||||
|
||||
@@ -250,7 +258,10 @@ func (ss *SqlStore) AddDataSource(ctx context.Context, cmd *datasources.AddDataS
|
||||
}
|
||||
cmd.UID = uid
|
||||
} else if err := util.ValidateUID(cmd.UID); err != nil {
|
||||
logDeprecatedInvalidDsUid(ss.logger, cmd.UID, cmd.Name, err)
|
||||
logDeprecatedInvalidDsUid(ss.logger, cmd.UID, cmd.Name, "create", err)
|
||||
if ss.features != nil && ss.features.IsEnabled(ctx, featuremgmt.FlagAutofixDSUID) {
|
||||
return fmt.Errorf("invalid UID for datasource %s: %w", cmd.Name, err)
|
||||
}
|
||||
}
|
||||
|
||||
ds = &datasources.DataSource{
|
||||
@@ -321,6 +332,15 @@ func (ss *SqlStore) UpdateDataSource(ctx context.Context, cmd *datasources.Updat
|
||||
cmd.JsonData = simplejson.New()
|
||||
}
|
||||
|
||||
if cmd.UID != "" {
|
||||
if err := util.ValidateUID(cmd.UID); err != nil {
|
||||
logDeprecatedInvalidDsUid(ss.logger, cmd.UID, cmd.Name, "update", err)
|
||||
if ss.features != nil && ss.features.IsEnabled(ctx, featuremgmt.FlagAutofixDSUID) {
|
||||
cmd.UID = util.AutofixUID(cmd.UID)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ds = &datasources.DataSource{
|
||||
ID: cmd.ID,
|
||||
OrgID: cmd.OrgID,
|
||||
@@ -387,12 +407,6 @@ func (ss *SqlStore) UpdateDataSource(ctx context.Context, cmd *datasources.Updat
|
||||
}
|
||||
}
|
||||
|
||||
if cmd.UID != "" {
|
||||
if err := util.ValidateUID(cmd.UID); err != nil {
|
||||
logDeprecatedInvalidDsUid(ss.logger, cmd.UID, cmd.Name, err)
|
||||
}
|
||||
}
|
||||
|
||||
return err
|
||||
})
|
||||
}
|
||||
@@ -416,11 +430,10 @@ func generateNewDatasourceUid(sess *db.Session, orgId int64) (string, error) {
|
||||
|
||||
var generateNewUid func() string = util.GenerateShortUID
|
||||
|
||||
func logDeprecatedInvalidDsUid(logger log.Logger, uid string, name string, err error) {
|
||||
func logDeprecatedInvalidDsUid(logger log.Logger, uid string, name string, action string, err error) {
|
||||
logger.Warn(
|
||||
"Invalid datasource uid. The use of invalid uids is deprecated and this operation will fail in a future "+
|
||||
"version of Grafana. A valid uid is a combination of a-z, A-Z, 0-9 (alphanumeric), - (dash) and _ "+
|
||||
"(underscore) characters, maximum length 40",
|
||||
"uid", uid, "name", name, "error", err,
|
||||
"Invalid datasource uid. A valid uid is a combination of a-z, A-Z, 0-9 (alphanumeric), - (dash) and _ "+
|
||||
"(underscore) characters, maximum length 40. Invalid characters will be replaced by dashes.",
|
||||
"uid", uid, "action", action, "name", name, "error", err,
|
||||
)
|
||||
}
|
||||
|
||||
@@ -11,8 +11,10 @@ import (
|
||||
|
||||
"github.com/grafana/grafana/pkg/events"
|
||||
"github.com/grafana/grafana/pkg/infra/db"
|
||||
"github.com/grafana/grafana/pkg/infra/log"
|
||||
ac "github.com/grafana/grafana/pkg/services/accesscontrol"
|
||||
"github.com/grafana/grafana/pkg/services/datasources"
|
||||
"github.com/grafana/grafana/pkg/services/featuremgmt"
|
||||
)
|
||||
|
||||
func TestIntegrationDataAccess(t *testing.T) {
|
||||
@@ -96,6 +98,19 @@ func TestIntegrationDataAccess(t *testing.T) {
|
||||
require.IsType(t, datasources.ErrDataSourceUidExists, err)
|
||||
})
|
||||
|
||||
t.Run("fails to create a datasource with an invalid uid", func(t *testing.T) {
|
||||
db := db.InitTestDB(t)
|
||||
ss := SqlStore{
|
||||
db: db,
|
||||
logger: log.NewNopLogger(),
|
||||
features: featuremgmt.WithFeatures(featuremgmt.FlagAutofixDSUID),
|
||||
}
|
||||
cmd := defaultAddDatasourceCommand
|
||||
cmd.UID = "test/uid"
|
||||
_, err := ss.AddDataSource(context.Background(), &cmd)
|
||||
require.ErrorContains(t, err, "invalid format of UID")
|
||||
})
|
||||
|
||||
t.Run("fires an event when the datasource is added", func(t *testing.T) {
|
||||
db := db.InitTestDB(t)
|
||||
sqlStore := SqlStore{db: db}
|
||||
@@ -213,6 +228,30 @@ func TestIntegrationDataAccess(t *testing.T) {
|
||||
_, err := ss.UpdateDataSource(context.Background(), cmd)
|
||||
require.NoError(t, err)
|
||||
})
|
||||
|
||||
t.Run("updates UID with a valid one", func(t *testing.T) {
|
||||
db := db.InitTestDB(t)
|
||||
ds := initDatasource(db)
|
||||
ss := SqlStore{
|
||||
db: db,
|
||||
logger: log.NewNopLogger(),
|
||||
features: featuremgmt.WithFeatures(featuremgmt.FlagAutofixDSUID),
|
||||
}
|
||||
require.NotEmpty(t, ds.UID)
|
||||
|
||||
cmd := defaultUpdateDatasourceCommand
|
||||
cmd.ID = ds.ID
|
||||
cmd.UID = "new/uid"
|
||||
res, err := ss.UpdateDataSource(context.Background(), &cmd)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, "new-uid", res.UID)
|
||||
|
||||
// Return the datasource with the valid UID
|
||||
query := datasources.GetDataSourceQuery{UID: "new-uid", OrgID: 10}
|
||||
dataSource, err := ss.GetDataSource(context.Background(), &query)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, "new-uid", dataSource.UID)
|
||||
})
|
||||
})
|
||||
|
||||
t.Run("DeleteDataSourceById", func(t *testing.T) {
|
||||
|
||||
Reference in New Issue
Block a user