Elasticsearch: Fix resource calls for paths that include : (#82327)

* Elasticsearch: Fix resource calls for paths that include :

* Add tests

* Add test case and comment

* Remove redundant comment
This commit is contained in:
Ivana Huckova
2024-02-13 13:44:08 +01:00
committed by GitHub
parent baa46e6a46
commit 082f020b7d
2 changed files with 42 additions and 12 deletions
+12 -12
View File
@@ -205,21 +205,11 @@ func (s *Service) CallResource(ctx context.Context, req *backend.CallResourceReq
return err
}
esUrl, err := url.Parse(ds.URL)
esUrl, err := createElasticsearchURL(req, ds)
if err != nil {
logger.Error("Failed to parse data source URL", "error", err, "url", ds.URL)
return err
logger.Error("Failed to create request url", "error", err, "url", ds.URL, "path", req.Path)
}
resourcePath, err := url.Parse(req.Path)
if err != nil {
logger.Error("Failed to parse data source path", "error", err, "url", req.Path)
return err
}
// We take the path and the query-string only
esUrl.RawQuery = resourcePath.RawQuery
esUrl.Path = path.Join(esUrl.Path, resourcePath.Path)
request, err := http.NewRequestWithContext(ctx, req.Method, esUrl.String(), bytes.NewBuffer(req.Body))
if err != nil {
logger.Error("Failed to create request", "error", err, "url", esUrl.String())
@@ -269,3 +259,13 @@ func (s *Service) CallResource(ctx context.Context, req *backend.CallResourceReq
Body: body,
})
}
func createElasticsearchURL(req *backend.CallResourceRequest, ds *es.DatasourceInfo) (*url.URL, error) {
esUrl, err := url.Parse(ds.URL)
if err != nil {
return nil, fmt.Errorf("failed to parse data source URL: %s, error: %w", ds.URL, err)
}
esUrl.Path = path.Join(esUrl.Path, req.Path)
return esUrl, nil
}
@@ -9,6 +9,7 @@ import (
"github.com/stretchr/testify/require"
"github.com/grafana/grafana/pkg/infra/httpclient"
es "github.com/grafana/grafana/pkg/tsdb/elasticsearch/client"
)
type datasourceInfo struct {
@@ -71,3 +72,32 @@ func TestNewInstanceSettings(t *testing.T) {
})
})
}
func TestCreateElasticsearchURL(t *testing.T) {
tt := []struct {
name string
settings es.DatasourceInfo
req backend.CallResourceRequest
expected string
}{
{name: "with /_msearch path and valid url", settings: es.DatasourceInfo{URL: "http://localhost:9200"}, req: backend.CallResourceRequest{Path: "_msearch"}, expected: "http://localhost:9200/_msearch"},
{name: "with _msearch path and valid url", settings: es.DatasourceInfo{URL: "http://localhost:9200"}, req: backend.CallResourceRequest{Path: "_msearch"}, expected: "http://localhost:9200/_msearch"},
{name: "with _msearch path and valid url with /", settings: es.DatasourceInfo{URL: "http://localhost:9200/"}, req: backend.CallResourceRequest{Path: "_msearch"}, expected: "http://localhost:9200/_msearch"},
{name: "with _mapping path and valid url", settings: es.DatasourceInfo{URL: "http://localhost:9200"}, req: backend.CallResourceRequest{Path: "/_mapping"}, expected: "http://localhost:9200/_mapping"},
{name: "with /_mapping path and valid url", settings: es.DatasourceInfo{URL: "http://localhost:9200"}, req: backend.CallResourceRequest{Path: "/_mapping"}, expected: "http://localhost:9200/_mapping"},
{name: "with /_mapping path and valid url with /", settings: es.DatasourceInfo{URL: "http://localhost:9200/"}, req: backend.CallResourceRequest{Path: "/_mapping"}, expected: "http://localhost:9200/_mapping"},
{name: "with abc/_mapping path and valid url", settings: es.DatasourceInfo{URL: "http://localhost:9200"}, req: backend.CallResourceRequest{Path: "abc/_mapping"}, expected: "http://localhost:9200/abc/_mapping"},
{name: "with /abc/_mapping path and valid url", settings: es.DatasourceInfo{URL: "http://localhost:9200"}, req: backend.CallResourceRequest{Path: "abc/_mapping"}, expected: "http://localhost:9200/abc/_mapping"},
{name: "with /abc/_mapping path and valid url", settings: es.DatasourceInfo{URL: "http://localhost:9200/"}, req: backend.CallResourceRequest{Path: "abc/_mapping"}, expected: "http://localhost:9200/abc/_mapping"},
// This is to support mappings to cross cluster search that includes ":"
{name: "with path including :", settings: es.DatasourceInfo{URL: "http://localhost:9200/"}, req: backend.CallResourceRequest{Path: "ab:c/_mapping"}, expected: "http://localhost:9200/ab:c/_mapping"},
}
for _, test := range tt {
t.Run(test.name, func(t *testing.T) {
url, err := createElasticsearchURL(&test.req, &test.settings)
require.NoError(t, err)
require.Equal(t, test.expected, url.String())
})
}
}