mirror of https://github.com/grafana/grafana.git
				
				
				
			
		
			
				
	
	
		
			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
 | 
						|
}
 |