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:
Ieva
2023-11-22 09:57:26 +00:00
committed by GitHub
parent 2acf153a26
commit 9a3b2937aa
7 changed files with 117 additions and 119 deletions

View File

@@ -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"`

View File

@@ -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 {

View File

@@ -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{}