2022-03-08 02:33:01 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								package  api  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								import  (  
						 
					
						
							
								
									
										
										
										
											2022-07-13 21:27:03 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									"bytes" 
							 
						 
					
						
							
								
									
										
										
										
											2022-03-08 02:33:01 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									"context" 
							 
						 
					
						
							
								
									
										
										
										
											2022-07-13 21:27:03 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									"encoding/json" 
							 
						 
					
						
							
								
									
										
										
										
											2022-09-15 00:19:57 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									"errors" 
							 
						 
					
						
							
								
									
										
										
										
											2022-03-08 02:33:01 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									"fmt" 
							 
						 
					
						
							
								
									
										
										
										
											2022-09-15 00:19:57 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									"io" 
							 
						 
					
						
							
								
									
										
										
										
											2022-03-08 02:33:01 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									"net/http" 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									"strings" 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									"testing" 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2022-05-18 02:52:22 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									"github.com/grafana/grafana-plugin-sdk-go/backend" 
							 
						 
					
						
							
								
									
										
										
										
											2022-06-28 00:23:15 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									"github.com/stretchr/testify/require" 
							 
						 
					
						
							
								
									
										
										
										
											2022-09-15 00:19:57 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									"golang.org/x/oauth2" 
							 
						 
					
						
							
								
									
										
										
										
											2022-06-28 00:23:15 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2022-09-15 00:19:57 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									"github.com/grafana/grafana/pkg/plugins" 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									"github.com/grafana/grafana/pkg/plugins/backendplugin" 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									pluginClient  "github.com/grafana/grafana/pkg/plugins/manager/client" 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									"github.com/grafana/grafana/pkg/plugins/manager/registry" 
							 
						 
					
						
							
								
									
										
										
										
											2022-06-28 00:23:15 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									"github.com/grafana/grafana/pkg/services/datasources" 
							 
						 
					
						
							
								
									
										
										
										
											2022-09-15 00:19:57 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									fakeDatasources  "github.com/grafana/grafana/pkg/services/datasources/fakes" 
							 
						 
					
						
							
								
									
										
										
										
											2022-06-14 07:23:56 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									"github.com/grafana/grafana/pkg/services/featuremgmt" 
							 
						 
					
						
							
								
									
										
										
										
											2022-08-10 17:56:48 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									"github.com/grafana/grafana/pkg/services/org" 
							 
						 
					
						
							
								
									
										
										
										
											2022-09-15 00:19:57 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									"github.com/grafana/grafana/pkg/services/query" 
							 
						 
					
						
							
								
									
										
										
										
											2022-07-16 00:06:44 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									"github.com/grafana/grafana/pkg/services/quota/quotatest" 
							 
						 
					
						
							
								
									
										
										
										
											2022-08-10 17:56:48 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									"github.com/grafana/grafana/pkg/services/user" 
							 
						 
					
						
							
								
									
										
										
										
											2022-09-15 00:19:57 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									"github.com/grafana/grafana/pkg/util/errutil" 
							 
						 
					
						
							
								
									
										
										
										
											2022-06-14 07:23:56 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									"github.com/grafana/grafana/pkg/web/webtest" 
							 
						 
					
						
							
								
									
										
										
										
											2022-03-08 02:33:01 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								)  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								type  fakePluginRequestValidator  struct  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									err  error 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2022-07-13 21:27:03 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								type  secretsErrorResponseBody  struct  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									Error    string  ` json:"error" ` 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									Message  string  ` json:"message" ` 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2022-03-08 02:33:01 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								func  ( rv  * fakePluginRequestValidator )  Validate ( dsURL  string ,  req  * http . Request )  error  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  rv . err 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								type  fakeOAuthTokenService  struct  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									passThruEnabled  bool 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									token            * oauth2 . Token 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2022-08-10 17:56:48 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								func  ( ts  * fakeOAuthTokenService )  GetCurrentOAuthToken ( context . Context ,  * user . SignedInUser )  * oauth2 . Token  {  
						 
					
						
							
								
									
										
										
										
											2022-03-08 02:33:01 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									return  ts . token 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2022-06-28 00:23:15 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								func  ( ts  * fakeOAuthTokenService )  IsOAuthPassThruEnabled ( * datasources . DataSource )  bool  {  
						 
					
						
							
								
									
										
										
										
											2022-03-08 02:33:01 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									return  ts . passThruEnabled 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2022-05-04 00:02:20 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								// `/ds/query` endpoint test
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								func  TestAPIEndpoint_Metrics_QueryMetricsV2 ( t  * testing . T )  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									qds  :=  query . ProvideService ( 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										nil , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										nil , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										nil , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										& fakePluginRequestValidator { } , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										& fakeDatasources . FakeDataSourceService { } , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										& fakePluginClient { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											QueryDataHandlerFunc :  func ( ctx  context . Context ,  req  * backend . QueryDataRequest )  ( * backend . QueryDataResponse ,  error )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												resp  :=  backend . Responses { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													"A" :  backend . DataResponse { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
														Error :  fmt . Errorf ( "query failed" ) , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													} , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												return  & backend . QueryDataResponse { Responses :  resp } ,  nil 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											} , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										& fakeOAuthTokenService { } , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									serverFeatureEnabled  :=  SetupAPITestServer ( t ,  func ( hs  * HTTPServer )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										hs . queryDataService  =  qds 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										hs . Features  =  featuremgmt . WithFeatures ( featuremgmt . FlagDatasourceQueryMultiStatus ,  true ) 
							 
						 
					
						
							
								
									
										
										
										
											2022-07-16 00:06:44 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										hs . QuotaService  =  quotatest . NewQuotaServiceFake ( ) 
							 
						 
					
						
							
								
									
										
										
										
											2022-05-04 00:02:20 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									} ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									serverFeatureDisabled  :=  SetupAPITestServer ( t ,  func ( hs  * HTTPServer )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										hs . queryDataService  =  qds 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										hs . Features  =  featuremgmt . WithFeatures ( featuremgmt . FlagDatasourceQueryMultiStatus ,  false ) 
							 
						 
					
						
							
								
									
										
										
										
											2022-07-16 00:06:44 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										hs . QuotaService  =  quotatest . NewQuotaServiceFake ( ) 
							 
						 
					
						
							
								
									
										
										
										
											2022-05-04 00:02:20 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									} ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									t . Run ( "Status code is 400 when data source response has an error and feature toggle is disabled" ,  func ( t  * testing . T )  { 
							 
						 
					
						
							
								
									
										
										
										
											2022-09-15 00:19:57 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										req  :=  serverFeatureDisabled . NewPostRequest ( "/api/ds/query" ,  strings . NewReader ( reqValid ) ) 
							 
						 
					
						
							
								
									
										
										
										
											2022-08-11 19:28:55 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										webtest . RequestWithSignedInUser ( req ,  & user . SignedInUser { UserID :  1 ,  OrgID :  1 ,  OrgRole :  org . RoleViewer } ) 
							 
						 
					
						
							
								
									
										
										
										
											2022-05-04 00:02:20 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										resp ,  err  :=  serverFeatureDisabled . SendJSON ( req ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										require . NoError ( t ,  err ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										require . NoError ( t ,  resp . Body . Close ( ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										require . Equal ( t ,  http . StatusBadRequest ,  resp . StatusCode ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									t . Run ( "Status code is 207 when data source response has an error and feature toggle is enabled" ,  func ( t  * testing . T )  { 
							 
						 
					
						
							
								
									
										
										
										
											2022-09-15 00:19:57 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										req  :=  serverFeatureEnabled . NewPostRequest ( "/api/ds/query" ,  strings . NewReader ( reqValid ) ) 
							 
						 
					
						
							
								
									
										
										
										
											2022-08-11 19:28:55 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										webtest . RequestWithSignedInUser ( req ,  & user . SignedInUser { UserID :  1 ,  OrgID :  1 ,  OrgRole :  org . RoleViewer } ) 
							 
						 
					
						
							
								
									
										
										
										
											2022-05-04 00:02:20 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										resp ,  err  :=  serverFeatureEnabled . SendJSON ( req ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										require . NoError ( t ,  err ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										require . NoError ( t ,  resp . Body . Close ( ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										require . Equal ( t ,  http . StatusMultiStatus ,  resp . StatusCode ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
									
										
										
										
											2022-07-13 21:27:03 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								func  TestAPIEndpoint_Metrics_PluginDecryptionFailure ( t  * testing . T )  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									qds  :=  query . ProvideService ( 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										nil , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										nil , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										nil , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										& fakePluginRequestValidator { } , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										& fakeDatasources . FakeDataSourceService { SimulatePluginFailure :  true } , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										& fakePluginClient { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											QueryDataHandlerFunc :  func ( ctx  context . Context ,  req  * backend . QueryDataRequest )  ( * backend . QueryDataResponse ,  error )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												resp  :=  backend . Responses { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													"A" :  backend . DataResponse { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
														Error :  fmt . Errorf ( "query failed" ) , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													} , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												return  & backend . QueryDataResponse { Responses :  resp } ,  nil 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											} , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										& fakeOAuthTokenService { } , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									httpServer  :=  SetupAPITestServer ( t ,  func ( hs  * HTTPServer )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										hs . queryDataService  =  qds 
							 
						 
					
						
							
								
									
										
										
										
											2022-07-16 00:06:44 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										hs . QuotaService  =  quotatest . NewQuotaServiceFake ( ) 
							 
						 
					
						
							
								
									
										
										
										
											2022-07-13 21:27:03 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									} ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									t . Run ( "Status code is 500 and a secrets plugin error is returned if there is a problem getting secrets from the remote plugin" ,  func ( t  * testing . T )  { 
							 
						 
					
						
							
								
									
										
										
										
											2022-09-15 00:19:57 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										req  :=  httpServer . NewPostRequest ( "/api/ds/query" ,  strings . NewReader ( reqValid ) ) 
							 
						 
					
						
							
								
									
										
										
										
											2022-08-11 19:28:55 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										webtest . RequestWithSignedInUser ( req ,  & user . SignedInUser { UserID :  1 ,  OrgID :  1 ,  OrgRole :  org . RoleViewer } ) 
							 
						 
					
						
							
								
									
										
										
										
											2022-07-13 21:27:03 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										resp ,  err  :=  httpServer . SendJSON ( req ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										require . NoError ( t ,  err ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										require . Equal ( t ,  http . StatusInternalServerError ,  resp . StatusCode ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										buf  :=  new ( bytes . Buffer ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										_ ,  err  =  buf . ReadFrom ( resp . Body ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										require . NoError ( t ,  err ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										require . NoError ( t ,  resp . Body . Close ( ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										var  resObj  secretsErrorResponseBody 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										err  =  json . Unmarshal ( buf . Bytes ( ) ,  & resObj ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										require . NoError ( t ,  err ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										require . Equal ( t ,  "unknown error" ,  resObj . Error ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										require . Contains ( t ,  resObj . Message ,  "Secrets Plugin error:" ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
									
										
										
										
											2022-09-15 00:19:57 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								var  reqValid  =  ` {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									"from" :  "" , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									"to" :  "" , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									"queries" :  [ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										{ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											"datasource" :  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												"type" :  "datasource" , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												"uid" :  "grafana" 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											} , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											"queryType" :  "randomWalk" , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											"refId" :  "A" 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									] 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								} `  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								var  reqNoQueries  =  ` {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									"from" :  "" , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									"to" :  "" , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									"queries" :  [ ] 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								} `  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								var  reqQueryWithInvalidDatasourceID  =  ` {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									"from" :  "" , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									"to" :  "" , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									"queries" :  [ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										{ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											"queryType" :  "randomWalk" , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											"refId" :  "A" 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									] 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								} `  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								var  reqDatasourceByUidNotFound  =  ` {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									"from" :  "" , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									"to" :  "" , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									"queries" :  [ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										{ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											"datasource" :  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												"type" :  "datasource" , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												"uid" :  "not-found" 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											} , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											"queryType" :  "randomWalk" , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											"refId" :  "A" 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									] 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								} `  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								var  reqDatasourceByIdNotFound  =  ` {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									"from" :  "" , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									"to" :  "" , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									"queries" :  [ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										{ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											"datasourceId" :  1 , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											"queryType" :  "randomWalk" , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											"refId" :  "A" 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									] 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								} `  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								func  TestDataSourceQueryError ( t  * testing . T )  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									tcs  :=  [ ] struct  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										request         string 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										clientErr       error 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										expectedStatus  int 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										expectedBody    string 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										{ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											request :         reqValid , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											clientErr :       backendplugin . ErrPluginUnavailable , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											expectedStatus :  http . StatusInternalServerError , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											expectedBody :    ` { "message":"Internal server error","messageId":"plugin.unavailable","statusCode":500,"traceID":""} ` , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										{ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											request :         reqValid , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											clientErr :       backendplugin . ErrMethodNotImplemented , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											expectedStatus :  http . StatusNotImplemented , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											expectedBody :    ` { "message":"Not implemented","messageId":"plugin.notImplemented","statusCode":501,"traceID":""} ` , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										{ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											request :         reqValid , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											clientErr :       errors . New ( "surprise surprise" ) , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											expectedStatus :  errutil . StatusInternal . HTTPStatus ( ) , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											expectedBody :    ` { "message":"An error occurred within the plugin","messageId":"plugin.downstreamError","statusCode":500,"traceID":""} ` , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										{ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											request :         reqNoQueries , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											expectedStatus :  http . StatusBadRequest , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											expectedBody :    ` { "message":"No queries found","messageId":"query.noQueries","statusCode":400,"traceID":""} ` , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										{ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											request :         reqQueryWithInvalidDatasourceID , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											expectedStatus :  http . StatusBadRequest , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											expectedBody :    ` { "message":"Query does not contain a valid data source identifier","messageId":"query.invalidDatasourceId","statusCode":400,"traceID":""} ` , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										{ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											request :         reqDatasourceByUidNotFound , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											expectedStatus :  http . StatusNotFound , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											expectedBody :    ` { "error":"data source not found","message":"Data source not found","traceID":""} ` , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										{ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											request :         reqDatasourceByIdNotFound , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											expectedStatus :  http . StatusNotFound , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											expectedBody :    ` { "error":"data source not found","message":"Data source not found","traceID":""} ` , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									for  _ ,  tc  :=  range  tcs  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										t . Run ( fmt . Sprintf ( "Plugin client error %q should propagate to API" ,  tc . clientErr ) ,  func ( t  * testing . T )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											p  :=  & plugins . Plugin { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												JSONData :  plugins . JSONData { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													ID :  "grafana" , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												} , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											p . RegisterClient ( & fakePluginBackend { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												qdr :  func ( ctx  context . Context ,  req  * backend . QueryDataRequest )  ( * backend . QueryDataResponse ,  error )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													return  nil ,  tc . clientErr 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												} , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											} ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											srv  :=  SetupAPITestServer ( t ,  func ( hs  * HTTPServer )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												r  :=  registry . NewInMemory ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												err  :=  r . Add ( context . Background ( ) ,  p ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												require . NoError ( t ,  err ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												hs . queryDataService  =  query . ProvideService ( 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													nil , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													& fakeDatasources . FakeCacheService { } , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													nil , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													& fakePluginRequestValidator { } , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													& fakeDatasources . FakeDataSourceService { } , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													pluginClient . ProvideService ( r ) , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													& fakeOAuthTokenService { } , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												hs . QuotaService  =  quotatest . NewQuotaServiceFake ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											} ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											req  :=  srv . NewPostRequest ( "/api/ds/query" ,  strings . NewReader ( tc . request ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											webtest . RequestWithSignedInUser ( req ,  & user . SignedInUser { UserID :  1 ,  OrgID :  1 ,  OrgRole :  org . RoleViewer } ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											resp ,  err  :=  srv . SendJSON ( req ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											require . NoError ( t ,  err ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											require . Equal ( t ,  tc . expectedStatus ,  resp . StatusCode ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											require . Equal ( t ,  tc . expectedStatus ,  resp . StatusCode ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											body ,  err  :=  io . ReadAll ( resp . Body ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											require . NoError ( t ,  err ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											require . Equal ( t ,  tc . expectedBody ,  string ( body ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											require . NoError ( t ,  resp . Body . Close ( ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								type  fakePluginBackend  struct  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									qdr  backend . QueryDataHandlerFunc 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									backendplugin . Plugin 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								func  ( f  * fakePluginBackend )  QueryData ( ctx  context . Context ,  req  * backend . QueryDataRequest )  ( * backend . QueryDataResponse ,  error )  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  f . qdr  !=  nil  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  f . qdr ( ctx ,  req ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  backend . NewQueryDataResponse ( ) ,  nil 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								func  ( f  * fakePluginBackend )  IsDecommissioned ( )  bool  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  false 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}