mirror of
https://github.com/grafana/grafana.git
synced 2024-11-29 20:24:18 -06:00
e4d1fdc3d0
When running in dev mode, error messages would contain an additional "error" property alongside "message". Since this causes confusion, that has been removed and now error messages are the same both modes (using "message").
133 lines
3.2 KiB
Go
133 lines
3.2 KiB
Go
package datasourceproxy
|
|
|
|
import (
|
|
"encoding/json"
|
|
"fmt"
|
|
"io"
|
|
"net/http"
|
|
"net/http/httptest"
|
|
"net/url"
|
|
"testing"
|
|
|
|
"github.com/grafana/grafana/pkg/infra/log"
|
|
"github.com/grafana/grafana/pkg/plugins"
|
|
contextmodel "github.com/grafana/grafana/pkg/services/contexthandler/model"
|
|
"github.com/grafana/grafana/pkg/services/datasources"
|
|
"github.com/grafana/grafana/pkg/services/pluginsintegration/pluginstore"
|
|
"github.com/grafana/grafana/pkg/web"
|
|
"github.com/stretchr/testify/assert"
|
|
"github.com/stretchr/testify/require"
|
|
)
|
|
|
|
func TestDataProxy(t *testing.T) {
|
|
t.Run("extractProxyPath", func(t *testing.T) {
|
|
testCases := []struct {
|
|
originalRawPath string
|
|
exp string
|
|
}{
|
|
{
|
|
"/api/datasources/proxy/1",
|
|
"",
|
|
},
|
|
{
|
|
"/api/datasources/proxy/1/some/thing",
|
|
"some/thing",
|
|
},
|
|
{
|
|
"/api/datasources/proxy/54/api/services/afsd%2Fafsd/operations",
|
|
"api/services/afsd%2Fafsd/operations",
|
|
},
|
|
{
|
|
"/api/datasources/proxy/uid/26MI0wZ7k",
|
|
"",
|
|
},
|
|
{
|
|
"/api/datasources/proxy/uid/26MI0wZ7k/some/thing",
|
|
"some/thing",
|
|
},
|
|
{
|
|
"/api/datasources/proxy/uid/pUWo-no4k/search",
|
|
"search",
|
|
},
|
|
{
|
|
"/api/datasources/proxy/uid/pUWo_no4k/search",
|
|
"search",
|
|
},
|
|
{
|
|
"/api/datasources/proxy/uid/26MI0wZ7k/api/services/afsd%2Fafsd/operations",
|
|
"api/services/afsd%2Fafsd/operations",
|
|
},
|
|
}
|
|
for _, tc := range testCases {
|
|
t.Run("Given raw path, should extract expected proxy path", func(t *testing.T) {
|
|
assert.Equal(t, tc.exp, extractProxyPath(tc.originalRawPath))
|
|
})
|
|
}
|
|
})
|
|
}
|
|
|
|
// Tests request to datasource proxy service
|
|
func TestDatasourceProxy_proxyDatasourceRequest(t *testing.T) {
|
|
tcs := []struct {
|
|
name string
|
|
dsURL string
|
|
}{
|
|
{
|
|
name: "Empty datasource URL will return a 400 HTTP status code",
|
|
dsURL: "",
|
|
},
|
|
{
|
|
name: "Invalid datasource URL will return a 400 HTTP status code",
|
|
dsURL: "://host/path",
|
|
},
|
|
}
|
|
for _, tc := range tcs {
|
|
t.Run(tc.name, func(t *testing.T) {
|
|
pluginID := datasources.DS_PROMETHEUS
|
|
|
|
pluginStore := &pluginstore.FakePluginStore{PluginList: []pluginstore.Plugin{
|
|
{JSONData: plugins.JSONData{ID: pluginID}},
|
|
}}
|
|
|
|
p := DataSourceProxyService{
|
|
PluginRequestValidator: &fakePluginRequestValidator{},
|
|
pluginStore: pluginStore,
|
|
}
|
|
|
|
responseRecorder := httptest.NewRecorder()
|
|
c := &contextmodel.ReqContext{
|
|
Context: &web.Context{
|
|
Req: &http.Request{URL: &url.URL{}},
|
|
Resp: web.NewResponseWriter("GET", responseRecorder),
|
|
},
|
|
Logger: log.NewNopLogger(),
|
|
}
|
|
|
|
p.proxyDatasourceRequest(c, &datasources.DataSource{
|
|
Type: pluginID,
|
|
URL: tc.dsURL,
|
|
})
|
|
|
|
resp := responseRecorder.Result()
|
|
body := resp.Body
|
|
|
|
b, err := io.ReadAll(body)
|
|
require.NoError(t, err)
|
|
require.NoError(t, body.Close())
|
|
|
|
jsonBody := make(map[string]string)
|
|
err = json.Unmarshal(b, &jsonBody)
|
|
require.NoError(t, err)
|
|
|
|
require.Equal(t, http.StatusBadRequest, resp.StatusCode)
|
|
require.Equal(t, fmt.Sprintf("Invalid data source URL: %q", tc.dsURL), jsonBody["message"])
|
|
})
|
|
}
|
|
}
|
|
|
|
type fakePluginRequestValidator struct{}
|
|
|
|
func (rv *fakePluginRequestValidator) Validate(_ string, _ *http.Request) error {
|
|
return nil
|
|
}
|