mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
Data sources: Refactor logic for naming new data sources (#78479)
* move the name finding logic for new data sources from frontend to backend * cleanup and fix test * linting * change the way the number after the ds type is incremented - keep incrementing it without adding more hyphens * enterprise spec updates (unrelated to the PR)
This commit is contained in:
@@ -140,7 +140,7 @@ func (e ErrDatasourceSecretsPluginUserFriendly) Error() string {
|
||||
|
||||
// Also acts as api DTO
|
||||
type AddDataSourceCommand struct {
|
||||
Name string `json:"name" binding:"Required"`
|
||||
Name string `json:"name"`
|
||||
Type string `json:"type" binding:"Required"`
|
||||
Access DsAccess `json:"access" binding:"Required"`
|
||||
URL string `json:"url"`
|
||||
|
||||
@@ -188,12 +188,25 @@ func (s *Service) GetDataSourcesByType(ctx context.Context, query *datasources.G
|
||||
}
|
||||
|
||||
func (s *Service) AddDataSource(ctx context.Context, cmd *datasources.AddDataSourceCommand) (*datasources.DataSource, error) {
|
||||
var dataSource *datasources.DataSource
|
||||
|
||||
if err := validateFields(cmd.Name, cmd.URL); err != nil {
|
||||
return dataSource, err
|
||||
dataSources, err := s.SQLStore.GetDataSources(ctx, &datasources.GetDataSourcesQuery{OrgID: cmd.OrgID})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Set the first created data source as default
|
||||
if len(dataSources) == 0 {
|
||||
cmd.IsDefault = true
|
||||
}
|
||||
|
||||
if cmd.Name == "" {
|
||||
cmd.Name = getAvailableName(cmd.Type, dataSources)
|
||||
}
|
||||
|
||||
if err := validateFields(cmd.Name, cmd.URL); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var dataSource *datasources.DataSource
|
||||
return dataSource, s.db.InTransaction(ctx, func(ctx context.Context) error {
|
||||
var err error
|
||||
|
||||
@@ -236,6 +249,24 @@ func (s *Service) AddDataSource(ctx context.Context, cmd *datasources.AddDataSou
|
||||
})
|
||||
}
|
||||
|
||||
// getAvailableName finds the first available name for a datasource of the given type.
|
||||
func getAvailableName(dsType string, dataSources []*datasources.DataSource) string {
|
||||
dsNames := make(map[string]bool)
|
||||
for _, ds := range dataSources {
|
||||
dsNames[strings.ToLower(ds.Name)] = true
|
||||
}
|
||||
|
||||
name := dsType
|
||||
currentDigit := 0
|
||||
|
||||
for dsNames[strings.ToLower(name)] {
|
||||
currentDigit++
|
||||
name = fmt.Sprintf("%s-%d", dsType, currentDigit)
|
||||
}
|
||||
|
||||
return name
|
||||
}
|
||||
|
||||
func (s *Service) DeleteDataSource(ctx context.Context, cmd *datasources.DeleteDataSourceCommand) error {
|
||||
return s.db.InTransaction(ctx, func(ctx context.Context) error {
|
||||
cmd.UpdateSecretFn = func() error {
|
||||
|
||||
@@ -79,6 +79,85 @@ func TestService_AddDataSource(t *testing.T) {
|
||||
})
|
||||
}
|
||||
|
||||
func TestService_getAvailableName(t *testing.T) {
|
||||
type testCase struct {
|
||||
desc string
|
||||
dsType string
|
||||
existingDs []*datasources.DataSource
|
||||
expected string
|
||||
}
|
||||
|
||||
testCases := []testCase{
|
||||
{
|
||||
desc: "should return type as the name if no DS are passed in",
|
||||
dsType: "prometheus",
|
||||
expected: "prometheus",
|
||||
},
|
||||
{
|
||||
desc: "should return type as the name if no DS with that name exists",
|
||||
dsType: "prometheus",
|
||||
existingDs: []*datasources.DataSource{
|
||||
{Name: "graphite"},
|
||||
{Name: "loki"},
|
||||
},
|
||||
expected: "prometheus",
|
||||
},
|
||||
{
|
||||
desc: "should return type-1 as the name if one data source with that name exists",
|
||||
dsType: "prometheus",
|
||||
existingDs: []*datasources.DataSource{
|
||||
{Name: "graphite"},
|
||||
{Name: "prometheus"},
|
||||
},
|
||||
expected: "prometheus-1",
|
||||
},
|
||||
{
|
||||
desc: "should correctly increment the number suffix of the name",
|
||||
dsType: "prometheus",
|
||||
existingDs: []*datasources.DataSource{
|
||||
{Name: "prometheus"},
|
||||
{Name: "prometheus-1"},
|
||||
{Name: "prometheus-3"},
|
||||
},
|
||||
expected: "prometheus-2",
|
||||
},
|
||||
{
|
||||
desc: "should correctly increment the number suffix for multidigit numbers",
|
||||
dsType: "prometheus",
|
||||
existingDs: []*datasources.DataSource{
|
||||
{Name: "prometheus"},
|
||||
{Name: "prometheus-1"},
|
||||
{Name: "prometheus-2"},
|
||||
{Name: "prometheus-3"},
|
||||
{Name: "prometheus-4"},
|
||||
{Name: "prometheus-5"},
|
||||
{Name: "prometheus-6"},
|
||||
{Name: "prometheus-7"},
|
||||
{Name: "prometheus-8"},
|
||||
{Name: "prometheus-9"},
|
||||
{Name: "prometheus-10"},
|
||||
},
|
||||
expected: "prometheus-11",
|
||||
},
|
||||
{
|
||||
desc: "name comparison should be case insensitive",
|
||||
dsType: "prometheus",
|
||||
existingDs: []*datasources.DataSource{
|
||||
{Name: "Prometheus"},
|
||||
{Name: "PROMETHEUS"},
|
||||
},
|
||||
expected: "prometheus-1",
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range testCases {
|
||||
t.Run(tc.desc, func(t *testing.T) {
|
||||
name := getAvailableName(tc.dsType, tc.existingDs)
|
||||
assert.Equal(t, tc.expected, name)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestService_UpdateDataSource(t *testing.T) {
|
||||
cfg := &setting.Cfg{}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user