@ -12,23 +12,24 @@ import (
"time"
"time"
"github.com/grafana/grafana/pkg/api/datasource"
"github.com/grafana/grafana/pkg/api/datasource"
"github.com/grafana/grafana/pkg/bus"
"github.com/grafana/grafana/pkg/components/securejsondata"
"github.com/grafana/grafana/pkg/components/securejsondata"
"github.com/grafana/grafana/pkg/components/simplejson"
"github.com/grafana/grafana/pkg/infra/httpclient"
"github.com/grafana/grafana/pkg/login/social"
"github.com/grafana/grafana/pkg/models"
"github.com/grafana/grafana/pkg/models"
"github.com/grafana/grafana/pkg/plugins"
"github.com/grafana/grafana/pkg/plugins"
"github.com/grafana/grafana/pkg/setting"
"github.com/grafana/grafana/pkg/util"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"github.com/stretchr/testify/require"
"golang.org/x/oauth2"
"golang.org/x/oauth2"
macaron "gopkg.in/macaron.v1"
macaron "gopkg.in/macaron.v1"
"github.com/grafana/grafana/pkg/bus"
"github.com/grafana/grafana/pkg/components/simplejson"
"github.com/grafana/grafana/pkg/login/social"
"github.com/grafana/grafana/pkg/setting"
"github.com/grafana/grafana/pkg/util"
)
)
func TestDataSourceProxy_routeRule ( t * testing . T ) {
func TestDataSourceProxy_routeRule ( t * testing . T ) {
httpClientProvider := httpclient . NewProvider ( )
t . Run ( "Plugin with routes" , func ( t * testing . T ) {
t . Run ( "Plugin with routes" , func ( t * testing . T ) {
plugin := & plugins . DataSourcePlugin {
plugin := & plugins . DataSourcePlugin {
Routes : [ ] * plugins . AppPluginRoute {
Routes : [ ] * plugins . AppPluginRoute {
@ -113,7 +114,7 @@ func TestDataSourceProxy_routeRule(t *testing.T) {
t . Run ( "When matching route path" , func ( t * testing . T ) {
t . Run ( "When matching route path" , func ( t * testing . T ) {
ctx , req := setUp ( )
ctx , req := setUp ( )
proxy , err := NewDataSourceProxy ( ds , plugin , ctx , "api/v4/some/method" , cfg )
proxy , err := NewDataSourceProxy ( ds , plugin , ctx , "api/v4/some/method" , cfg , httpClientProvider )
require . NoError ( t , err )
require . NoError ( t , err )
proxy . route = plugin . Routes [ 0 ]
proxy . route = plugin . Routes [ 0 ]
ApplyRoute ( proxy . ctx . Req . Context ( ) , req , proxy . proxyPath , proxy . route , proxy . ds , cfg )
ApplyRoute ( proxy . ctx . Req . Context ( ) , req , proxy . proxyPath , proxy . route , proxy . ds , cfg )
@ -124,7 +125,7 @@ func TestDataSourceProxy_routeRule(t *testing.T) {
t . Run ( "When matching route path and has dynamic url" , func ( t * testing . T ) {
t . Run ( "When matching route path and has dynamic url" , func ( t * testing . T ) {
ctx , req := setUp ( )
ctx , req := setUp ( )
proxy , err := NewDataSourceProxy ( ds , plugin , ctx , "api/common/some/method" , cfg )
proxy , err := NewDataSourceProxy ( ds , plugin , ctx , "api/common/some/method" , cfg , httpClientProvider )
require . NoError ( t , err )
require . NoError ( t , err )
proxy . route = plugin . Routes [ 3 ]
proxy . route = plugin . Routes [ 3 ]
ApplyRoute ( proxy . ctx . Req . Context ( ) , req , proxy . proxyPath , proxy . route , proxy . ds , cfg )
ApplyRoute ( proxy . ctx . Req . Context ( ) , req , proxy . proxyPath , proxy . route , proxy . ds , cfg )
@ -135,7 +136,7 @@ func TestDataSourceProxy_routeRule(t *testing.T) {
t . Run ( "When matching route path with no url" , func ( t * testing . T ) {
t . Run ( "When matching route path with no url" , func ( t * testing . T ) {
ctx , req := setUp ( )
ctx , req := setUp ( )
proxy , err := NewDataSourceProxy ( ds , plugin , ctx , "" , cfg )
proxy , err := NewDataSourceProxy ( ds , plugin , ctx , "" , cfg , httpClientProvider )
require . NoError ( t , err )
require . NoError ( t , err )
proxy . route = plugin . Routes [ 4 ]
proxy . route = plugin . Routes [ 4 ]
ApplyRoute ( proxy . ctx . Req . Context ( ) , req , proxy . proxyPath , proxy . route , proxy . ds , cfg )
ApplyRoute ( proxy . ctx . Req . Context ( ) , req , proxy . proxyPath , proxy . route , proxy . ds , cfg )
@ -145,7 +146,7 @@ func TestDataSourceProxy_routeRule(t *testing.T) {
t . Run ( "When matching route path and has dynamic body" , func ( t * testing . T ) {
t . Run ( "When matching route path and has dynamic body" , func ( t * testing . T ) {
ctx , req := setUp ( )
ctx , req := setUp ( )
proxy , err := NewDataSourceProxy ( ds , plugin , ctx , "api/body" , cfg )
proxy , err := NewDataSourceProxy ( ds , plugin , ctx , "api/body" , cfg , httpClientProvider )
require . NoError ( t , err )
require . NoError ( t , err )
proxy . route = plugin . Routes [ 5 ]
proxy . route = plugin . Routes [ 5 ]
ApplyRoute ( proxy . ctx . Req . Context ( ) , req , proxy . proxyPath , proxy . route , proxy . ds , cfg )
ApplyRoute ( proxy . ctx . Req . Context ( ) , req , proxy . proxyPath , proxy . route , proxy . ds , cfg )
@ -158,7 +159,7 @@ func TestDataSourceProxy_routeRule(t *testing.T) {
t . Run ( "Validating request" , func ( t * testing . T ) {
t . Run ( "Validating request" , func ( t * testing . T ) {
t . Run ( "plugin route with valid role" , func ( t * testing . T ) {
t . Run ( "plugin route with valid role" , func ( t * testing . T ) {
ctx , _ := setUp ( )
ctx , _ := setUp ( )
proxy , err := NewDataSourceProxy ( ds , plugin , ctx , "api/v4/some/method" , cfg )
proxy , err := NewDataSourceProxy ( ds , plugin , ctx , "api/v4/some/method" , cfg , httpClientProvider )
require . NoError ( t , err )
require . NoError ( t , err )
err = proxy . validateRequest ( )
err = proxy . validateRequest ( )
require . NoError ( t , err )
require . NoError ( t , err )
@ -166,7 +167,7 @@ func TestDataSourceProxy_routeRule(t *testing.T) {
t . Run ( "plugin route with admin role and user is editor" , func ( t * testing . T ) {
t . Run ( "plugin route with admin role and user is editor" , func ( t * testing . T ) {
ctx , _ := setUp ( )
ctx , _ := setUp ( )
proxy , err := NewDataSourceProxy ( ds , plugin , ctx , "api/admin" , cfg )
proxy , err := NewDataSourceProxy ( ds , plugin , ctx , "api/admin" , cfg , httpClientProvider )
require . NoError ( t , err )
require . NoError ( t , err )
err = proxy . validateRequest ( )
err = proxy . validateRequest ( )
require . Error ( t , err )
require . Error ( t , err )
@ -175,7 +176,7 @@ func TestDataSourceProxy_routeRule(t *testing.T) {
t . Run ( "plugin route with admin role and user is admin" , func ( t * testing . T ) {
t . Run ( "plugin route with admin role and user is admin" , func ( t * testing . T ) {
ctx , _ := setUp ( )
ctx , _ := setUp ( )
ctx . SignedInUser . OrgRole = models . ROLE_ADMIN
ctx . SignedInUser . OrgRole = models . ROLE_ADMIN
proxy , err := NewDataSourceProxy ( ds , plugin , ctx , "api/admin" , cfg )
proxy , err := NewDataSourceProxy ( ds , plugin , ctx , "api/admin" , cfg , httpClientProvider )
require . NoError ( t , err )
require . NoError ( t , err )
err = proxy . validateRequest ( )
err = proxy . validateRequest ( )
require . NoError ( t , err )
require . NoError ( t , err )
@ -257,7 +258,7 @@ func TestDataSourceProxy_routeRule(t *testing.T) {
cfg := & setting . Cfg { }
cfg := & setting . Cfg { }
proxy , err := NewDataSourceProxy ( ds , plugin , ctx , "pathwithtoken1" , cfg )
proxy , err := NewDataSourceProxy ( ds , plugin , ctx , "pathwithtoken1" , cfg , httpClientProvider )
require . NoError ( t , err )
require . NoError ( t , err )
ApplyRoute ( proxy . ctx . Req . Context ( ) , req , proxy . proxyPath , plugin . Routes [ 0 ] , proxy . ds , cfg )
ApplyRoute ( proxy . ctx . Req . Context ( ) , req , proxy . proxyPath , plugin . Routes [ 0 ] , proxy . ds , cfg )
@ -272,7 +273,7 @@ func TestDataSourceProxy_routeRule(t *testing.T) {
req , err := http . NewRequest ( "GET" , "http://localhost/asd" , nil )
req , err := http . NewRequest ( "GET" , "http://localhost/asd" , nil )
require . NoError ( t , err )
require . NoError ( t , err )
client = newFakeHTTPClient ( t , json2 )
client = newFakeHTTPClient ( t , json2 )
proxy , err := NewDataSourceProxy ( ds , plugin , ctx , "pathwithtoken2" , cfg )
proxy , err := NewDataSourceProxy ( ds , plugin , ctx , "pathwithtoken2" , cfg , httpClientProvider )
require . NoError ( t , err )
require . NoError ( t , err )
ApplyRoute ( proxy . ctx . Req . Context ( ) , req , proxy . proxyPath , plugin . Routes [ 1 ] , proxy . ds , cfg )
ApplyRoute ( proxy . ctx . Req . Context ( ) , req , proxy . proxyPath , plugin . Routes [ 1 ] , proxy . ds , cfg )
@ -288,7 +289,7 @@ func TestDataSourceProxy_routeRule(t *testing.T) {
require . NoError ( t , err )
require . NoError ( t , err )
client = newFakeHTTPClient ( t , [ ] byte { } )
client = newFakeHTTPClient ( t , [ ] byte { } )
proxy , err := NewDataSourceProxy ( ds , plugin , ctx , "pathwithtoken1" , cfg )
proxy , err := NewDataSourceProxy ( ds , plugin , ctx , "pathwithtoken1" , cfg , httpClientProvider )
require . NoError ( t , err )
require . NoError ( t , err )
ApplyRoute ( proxy . ctx . Req . Context ( ) , req , proxy . proxyPath , plugin . Routes [ 0 ] , proxy . ds , cfg )
ApplyRoute ( proxy . ctx . Req . Context ( ) , req , proxy . proxyPath , plugin . Routes [ 0 ] , proxy . ds , cfg )
@ -304,17 +305,11 @@ func TestDataSourceProxy_routeRule(t *testing.T) {
} )
} )
t . Run ( "When proxying graphite" , func ( t * testing . T ) {
t . Run ( "When proxying graphite" , func ( t * testing . T ) {
origBuildVer := setting . BuildVersion
t . Cleanup ( func ( ) {
setting . BuildVersion = origBuildVer
} )
setting . BuildVersion = "5.3.0"
plugin := & plugins . DataSourcePlugin { }
plugin := & plugins . DataSourcePlugin { }
ds := & models . DataSource { Url : "htttp://graphite:8080" , Type : models . DS_GRAPHITE }
ds := & models . DataSource { Url : "htttp://graphite:8080" , Type : models . DS_GRAPHITE }
ctx := & models . ReqContext { }
ctx := & models . ReqContext { }
proxy , err := NewDataSourceProxy ( ds , plugin , ctx , "/render" , & setting . Cfg { } )
proxy , err := NewDataSourceProxy ( ds , plugin , ctx , "/render" , & setting . Cfg { BuildVersion : "5.3.0" } , httpClientProvider )
require . NoError ( t , err )
require . NoError ( t , err )
req , err := http . NewRequest ( http . MethodGet , "http://grafana.com/sub" , nil )
req , err := http . NewRequest ( http . MethodGet , "http://grafana.com/sub" , nil )
require . NoError ( t , err )
require . NoError ( t , err )
@ -324,7 +319,6 @@ func TestDataSourceProxy_routeRule(t *testing.T) {
t . Run ( "Can translate request URL and path" , func ( t * testing . T ) {
t . Run ( "Can translate request URL and path" , func ( t * testing . T ) {
assert . Equal ( t , "graphite:8080" , req . URL . Host )
assert . Equal ( t , "graphite:8080" , req . URL . Host )
assert . Equal ( t , "/render" , req . URL . Path )
assert . Equal ( t , "/render" , req . URL . Path )
assert . Equal ( t , "Grafana/5.3.0" , req . Header . Get ( "User-Agent" ) )
} )
} )
} )
} )
@ -340,7 +334,7 @@ func TestDataSourceProxy_routeRule(t *testing.T) {
}
}
ctx := & models . ReqContext { }
ctx := & models . ReqContext { }
proxy , err := NewDataSourceProxy ( ds , plugin , ctx , "" , & setting . Cfg { } )
proxy , err := NewDataSourceProxy ( ds , plugin , ctx , "" , & setting . Cfg { } , httpClientProvider )
require . NoError ( t , err )
require . NoError ( t , err )
req , err := http . NewRequest ( http . MethodGet , "http://grafana.com/sub" , nil )
req , err := http . NewRequest ( http . MethodGet , "http://grafana.com/sub" , nil )
@ -363,7 +357,7 @@ func TestDataSourceProxy_routeRule(t *testing.T) {
}
}
ctx := & models . ReqContext { }
ctx := & models . ReqContext { }
proxy , err := NewDataSourceProxy ( ds , plugin , ctx , "" , & setting . Cfg { } )
proxy , err := NewDataSourceProxy ( ds , plugin , ctx , "" , & setting . Cfg { } , httpClientProvider )
require . NoError ( t , err )
require . NoError ( t , err )
requestURL , err := url . Parse ( "http://grafana.com/sub" )
requestURL , err := url . Parse ( "http://grafana.com/sub" )
@ -390,7 +384,7 @@ func TestDataSourceProxy_routeRule(t *testing.T) {
}
}
ctx := & models . ReqContext { }
ctx := & models . ReqContext { }
proxy , err := NewDataSourceProxy ( ds , plugin , ctx , "" , & setting . Cfg { } )
proxy , err := NewDataSourceProxy ( ds , plugin , ctx , "" , & setting . Cfg { } , httpClientProvider )
require . NoError ( t , err )
require . NoError ( t , err )
requestURL , err := url . Parse ( "http://grafana.com/sub" )
requestURL , err := url . Parse ( "http://grafana.com/sub" )
@ -411,7 +405,7 @@ func TestDataSourceProxy_routeRule(t *testing.T) {
Url : "http://host/root/" ,
Url : "http://host/root/" ,
}
}
ctx := & models . ReqContext { }
ctx := & models . ReqContext { }
proxy , err := NewDataSourceProxy ( ds , plugin , ctx , "/path/to/folder/" , & setting . Cfg { } )
proxy , err := NewDataSourceProxy ( ds , plugin , ctx , "/path/to/folder/" , & setting . Cfg { } , httpClientProvider )
require . NoError ( t , err )
require . NoError ( t , err )
req , err := http . NewRequest ( http . MethodGet , "http://grafana.com/sub" , nil )
req , err := http . NewRequest ( http . MethodGet , "http://grafana.com/sub" , nil )
req . Header . Set ( "Origin" , "grafana.com" )
req . Header . Set ( "Origin" , "grafana.com" )
@ -472,7 +466,7 @@ func TestDataSourceProxy_routeRule(t *testing.T) {
Req : macaron . Request { Request : req } ,
Req : macaron . Request { Request : req } ,
} ,
} ,
}
}
proxy , err := NewDataSourceProxy ( ds , plugin , ctx , "/path/to/folder/" , & setting . Cfg { } )
proxy , err := NewDataSourceProxy ( ds , plugin , ctx , "/path/to/folder/" , & setting . Cfg { } , httpClientProvider )
require . NoError ( t , err )
require . NoError ( t , err )
req , err = http . NewRequest ( http . MethodGet , "http://grafana.com/sub" , nil )
req , err = http . NewRequest ( http . MethodGet , "http://grafana.com/sub" , nil )
require . NoError ( t , err )
require . NoError ( t , err )
@ -545,6 +539,7 @@ func TestDataSourceProxy_routeRule(t *testing.T) {
// test DataSourceProxy request handling.
// test DataSourceProxy request handling.
func TestDataSourceProxy_requestHandling ( t * testing . T ) {
func TestDataSourceProxy_requestHandling ( t * testing . T ) {
httpClientProvider := httpclient . NewProvider ( )
var writeErr error
var writeErr error
plugin := & plugins . DataSourcePlugin { }
plugin := & plugins . DataSourcePlugin { }
@ -605,7 +600,7 @@ func TestDataSourceProxy_requestHandling(t *testing.T) {
t . Run ( "When response header Set-Cookie is not set should remove proxied Set-Cookie header" , func ( t * testing . T ) {
t . Run ( "When response header Set-Cookie is not set should remove proxied Set-Cookie header" , func ( t * testing . T ) {
ctx , ds := setUp ( t )
ctx , ds := setUp ( t )
proxy , err := NewDataSourceProxy ( ds , plugin , ctx , "/render" , & setting . Cfg { } )
proxy , err := NewDataSourceProxy ( ds , plugin , ctx , "/render" , & setting . Cfg { } , httpClientProvider )
require . NoError ( t , err )
require . NoError ( t , err )
proxy . HandleRequest ( )
proxy . HandleRequest ( )
@ -620,7 +615,7 @@ func TestDataSourceProxy_requestHandling(t *testing.T) {
"Set-Cookie" : "important_cookie=important_value" ,
"Set-Cookie" : "important_cookie=important_value" ,
} ,
} ,
} )
} )
proxy , err := NewDataSourceProxy ( ds , plugin , ctx , "/render" , & setting . Cfg { } )
proxy , err := NewDataSourceProxy ( ds , plugin , ctx , "/render" , & setting . Cfg { } , httpClientProvider )
require . NoError ( t , err )
require . NoError ( t , err )
proxy . HandleRequest ( )
proxy . HandleRequest ( )
@ -639,7 +634,7 @@ func TestDataSourceProxy_requestHandling(t *testing.T) {
t . Log ( "Wrote 401 response" )
t . Log ( "Wrote 401 response" )
} ,
} ,
} )
} )
proxy , err := NewDataSourceProxy ( ds , plugin , ctx , "/render" , & setting . Cfg { } )
proxy , err := NewDataSourceProxy ( ds , plugin , ctx , "/render" , & setting . Cfg { } , httpClientProvider )
require . NoError ( t , err )
require . NoError ( t , err )
proxy . HandleRequest ( )
proxy . HandleRequest ( )
@ -661,7 +656,7 @@ func TestDataSourceProxy_requestHandling(t *testing.T) {
} )
} )
ctx . Req . Request = httptest . NewRequest ( "GET" , "/api/datasources/proxy/1/path/%2Ftest%2Ftest%2F?query=%2Ftest%2Ftest%2F" , nil )
ctx . Req . Request = httptest . NewRequest ( "GET" , "/api/datasources/proxy/1/path/%2Ftest%2Ftest%2F?query=%2Ftest%2Ftest%2F" , nil )
proxy , err := NewDataSourceProxy ( ds , plugin , ctx , "/path/%2Ftest%2Ftest%2F" , & setting . Cfg { } )
proxy , err := NewDataSourceProxy ( ds , plugin , ctx , "/path/%2Ftest%2Ftest%2F" , & setting . Cfg { } , httpClientProvider )
require . NoError ( t , err )
require . NoError ( t , err )
proxy . HandleRequest ( )
proxy . HandleRequest ( )
@ -685,7 +680,7 @@ func TestNewDataSourceProxy_InvalidURL(t *testing.T) {
}
}
cfg := setting . Cfg { }
cfg := setting . Cfg { }
plugin := plugins . DataSourcePlugin { }
plugin := plugins . DataSourcePlugin { }
_ , err := NewDataSourceProxy ( & ds , & plugin , & ctx , "api/method" , & cfg )
_ , err := NewDataSourceProxy ( & ds , & plugin , & ctx , "api/method" , & cfg , httpclient . NewProvider ( ) )
require . Error ( t , err )
require . Error ( t , err )
assert . True ( t , strings . HasPrefix ( err . Error ( ) , ` validation of data source URL "://host/root" failed ` ) )
assert . True ( t , strings . HasPrefix ( err . Error ( ) , ` validation of data source URL "://host/root" failed ` ) )
}
}
@ -704,7 +699,7 @@ func TestNewDataSourceProxy_ProtocolLessURL(t *testing.T) {
cfg := setting . Cfg { }
cfg := setting . Cfg { }
plugin := plugins . DataSourcePlugin { }
plugin := plugins . DataSourcePlugin { }
_ , err := NewDataSourceProxy ( & ds , & plugin , & ctx , "api/method" , & cfg )
_ , err := NewDataSourceProxy ( & ds , & plugin , & ctx , "api/method" , & cfg , httpclient . NewProvider ( ) )
require . NoError ( t , err )
require . NoError ( t , err )
}
}
@ -744,7 +739,7 @@ func TestNewDataSourceProxy_MSSQL(t *testing.T) {
Url : tc . url ,
Url : tc . url ,
}
}
p , err := NewDataSourceProxy ( & ds , & plugin , & ctx , "api/method" , & cfg )
p , err := NewDataSourceProxy ( & ds , & plugin , & ctx , "api/method" , & cfg , httpclient . NewProvider ( ) )
if tc . err == nil {
if tc . err == nil {
require . NoError ( t , err )
require . NoError ( t , err )
assert . Equal ( t , & url . URL {
assert . Equal ( t , & url . URL {
@ -782,7 +777,7 @@ func getDatasourceProxiedRequest(t *testing.T, ctx *models.ReqContext, cfg *sett
Url : "http://host/root/" ,
Url : "http://host/root/" ,
}
}
proxy , err := NewDataSourceProxy ( ds , plugin , ctx , "" , cfg )
proxy , err := NewDataSourceProxy ( ds , plugin , ctx , "" , cfg , httpclient . NewProvider ( ) )
require . NoError ( t , err )
require . NoError ( t , err )
req , err := http . NewRequest ( http . MethodGet , "http://grafana.com/sub" , nil )
req , err := http . NewRequest ( http . MethodGet , "http://grafana.com/sub" , nil )
require . NoError ( t , err )
require . NoError ( t , err )
@ -840,6 +835,7 @@ func createAuthTest(t *testing.T, dsType string, authType string, authCheck stri
test := & testCase {
test := & testCase {
datasource : & models . DataSource {
datasource : & models . DataSource {
Id : 1 ,
Type : dsType ,
Type : dsType ,
JsonData : simplejson . New ( ) ,
JsonData : simplejson . New ( ) ,
} ,
} ,
@ -892,7 +888,7 @@ func createAuthTest(t *testing.T, dsType string, authType string, authCheck stri
func runDatasourceAuthTest ( t * testing . T , test * testCase ) {
func runDatasourceAuthTest ( t * testing . T , test * testCase ) {
plugin := & plugins . DataSourcePlugin { }
plugin := & plugins . DataSourcePlugin { }
ctx := & models . ReqContext { }
ctx := & models . ReqContext { }
proxy , err := NewDataSourceProxy ( test . datasource , plugin , ctx , "" , & setting . Cfg { } )
proxy , err := NewDataSourceProxy ( test . datasource , plugin , ctx , "" , & setting . Cfg { } , httpclient . NewProvider ( ) )
require . NoError ( t , err )
require . NoError ( t , err )
req , err := http . NewRequest ( http . MethodGet , "http://grafana.com/sub" , nil )
req , err := http . NewRequest ( http . MethodGet , "http://grafana.com/sub" , nil )
@ -933,7 +929,7 @@ func Test_PathCheck(t *testing.T) {
return ctx , req
return ctx , req
}
}
ctx , _ := setUp ( )
ctx , _ := setUp ( )
proxy , err := NewDataSourceProxy ( & models . DataSource { } , plugin , ctx , "b" , & setting . Cfg { } )
proxy , err := NewDataSourceProxy ( & models . DataSource { } , plugin , ctx , "b" , & setting . Cfg { } , httpclient . NewProvider ( ) )
require . NoError ( t , err )
require . NoError ( t , err )
require . Nil ( t , proxy . validateRequest ( ) )
require . Nil ( t , proxy . validateRequest ( ) )