| 
									
										
										
										
											2024-02-02 06:27:30 +08:00
										 |  |  | package datasource | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | import ( | 
					
						
							|  |  |  | 	"context" | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	"github.com/grafana/grafana-plugin-sdk-go/backend" | 
					
						
							| 
									
										
										
										
											2025-08-29 20:49:57 +08:00
										 |  |  | 	"github.com/grafana/grafana/pkg/apimachinery/identity" | 
					
						
							| 
									
										
										
										
											2024-09-04 19:53:14 +08:00
										 |  |  | 	"github.com/grafana/grafana/pkg/apimachinery/utils" | 
					
						
							| 
									
										
										
										
											2025-08-29 20:49:57 +08:00
										 |  |  | 	"github.com/grafana/grafana/pkg/apis/datasource/v0alpha1" | 
					
						
							| 
									
										
										
										
											2024-02-02 06:27:30 +08:00
										 |  |  | 	"github.com/grafana/grafana/pkg/plugins" | 
					
						
							|  |  |  | 	"github.com/grafana/grafana/pkg/services/apiserver/endpoints/request" | 
					
						
							|  |  |  | 	"github.com/grafana/grafana/pkg/services/datasources" | 
					
						
							| 
									
										
										
										
											2025-08-29 20:49:57 +08:00
										 |  |  | 	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" | 
					
						
							| 
									
										
										
										
											2024-02-02 06:27:30 +08:00
										 |  |  | ) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-09-04 19:53:14 +08:00
										 |  |  | type QuerierFactoryFunc func(ctx context.Context, ri utils.ResourceInfo, pj plugins.JSONData) (Querier, error) | 
					
						
							| 
									
										
										
										
											2024-02-02 06:27:30 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | type QuerierProvider interface { | 
					
						
							| 
									
										
										
										
											2024-09-04 19:53:14 +08:00
										 |  |  | 	Querier(ctx context.Context, ri utils.ResourceInfo, pj plugins.JSONData) (Querier, error) | 
					
						
							| 
									
										
										
										
											2024-02-02 06:27:30 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | type DefaultQuerierProvider struct { | 
					
						
							|  |  |  | 	factory QuerierFactoryFunc | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func ProvideDefaultQuerierProvider(pluginClient plugins.Client, dsService datasources.DataSourceService, | 
					
						
							|  |  |  | 	dsCache datasources.CacheService) *DefaultQuerierProvider { | 
					
						
							| 
									
										
										
										
											2024-09-04 19:53:14 +08:00
										 |  |  | 	return NewQuerierProvider(func(ctx context.Context, ri utils.ResourceInfo, pj plugins.JSONData) (Querier, error) { | 
					
						
							| 
									
										
										
										
											2024-02-02 06:27:30 +08:00
										 |  |  | 		return NewDefaultQuerier(ri, pj, pluginClient, dsService, dsCache), nil | 
					
						
							|  |  |  | 	}) | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func NewQuerierProvider(factory QuerierFactoryFunc) *DefaultQuerierProvider { | 
					
						
							|  |  |  | 	return &DefaultQuerierProvider{ | 
					
						
							|  |  |  | 		factory: factory, | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-09-04 19:53:14 +08:00
										 |  |  | func (p *DefaultQuerierProvider) Querier(ctx context.Context, ri utils.ResourceInfo, pj plugins.JSONData) (Querier, error) { | 
					
						
							| 
									
										
										
										
											2024-02-02 06:27:30 +08:00
										 |  |  | 	return p.factory(ctx, ri, pj) | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // Querier is the interface that wraps the Query method.
 | 
					
						
							|  |  |  | type Querier interface { | 
					
						
							|  |  |  | 	// Query runs the query on behalf of the user in context.
 | 
					
						
							|  |  |  | 	Query(ctx context.Context, query *backend.QueryDataRequest) (*backend.QueryDataResponse, error) | 
					
						
							|  |  |  | 	// Health checks the health of the plugin.
 | 
					
						
							|  |  |  | 	Health(ctx context.Context, req *backend.CheckHealthRequest) (*backend.CheckHealthResult, error) | 
					
						
							|  |  |  | 	// Resource gets a resource plugin.
 | 
					
						
							|  |  |  | 	Resource(ctx context.Context, req *backend.CallResourceRequest, sender backend.CallResourceResponseSender) error | 
					
						
							| 
									
										
										
										
											2025-08-29 20:49:57 +08:00
										 |  |  | 	// Datasource gets all data source plugins (with elevated permissions).
 | 
					
						
							|  |  |  | 	Datasource(ctx context.Context, name string) (*v0alpha1.DataSourceConnection, error) | 
					
						
							|  |  |  | 	// Datasources lists all data sources (with elevated permissions).
 | 
					
						
							|  |  |  | 	Datasources(ctx context.Context) (*v0alpha1.DataSourceConnectionList, error) | 
					
						
							| 
									
										
										
										
											2024-02-02 06:27:30 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | type DefaultQuerier struct { | 
					
						
							| 
									
										
										
										
											2024-09-04 19:53:14 +08:00
										 |  |  | 	connectionResourceInfo utils.ResourceInfo | 
					
						
							| 
									
										
										
										
											2024-02-02 06:27:30 +08:00
										 |  |  | 	pluginJSON             plugins.JSONData | 
					
						
							|  |  |  | 	pluginClient           plugins.Client | 
					
						
							|  |  |  | 	dsService              datasources.DataSourceService | 
					
						
							|  |  |  | 	dsCache                datasources.CacheService | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func NewDefaultQuerier( | 
					
						
							| 
									
										
										
										
											2024-09-04 19:53:14 +08:00
										 |  |  | 	connectionResourceInfo utils.ResourceInfo, | 
					
						
							| 
									
										
										
										
											2024-02-02 06:27:30 +08:00
										 |  |  | 	pluginJSON plugins.JSONData, | 
					
						
							|  |  |  | 	pluginClient plugins.Client, | 
					
						
							|  |  |  | 	dsService datasources.DataSourceService, | 
					
						
							|  |  |  | 	dsCache datasources.CacheService, | 
					
						
							|  |  |  | ) *DefaultQuerier { | 
					
						
							|  |  |  | 	return &DefaultQuerier{ | 
					
						
							|  |  |  | 		connectionResourceInfo: connectionResourceInfo, | 
					
						
							|  |  |  | 		pluginJSON:             pluginJSON, | 
					
						
							|  |  |  | 		pluginClient:           pluginClient, | 
					
						
							|  |  |  | 		dsService:              dsService, | 
					
						
							|  |  |  | 		dsCache:                dsCache, | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (q *DefaultQuerier) Query(ctx context.Context, query *backend.QueryDataRequest) (*backend.QueryDataResponse, error) { | 
					
						
							|  |  |  | 	_, err := request.NamespaceInfoFrom(ctx, true) | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		return nil, err | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return q.pluginClient.QueryData(ctx, query) | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (q *DefaultQuerier) Resource(ctx context.Context, req *backend.CallResourceRequest, sender backend.CallResourceResponseSender) error { | 
					
						
							|  |  |  | 	_, err := request.NamespaceInfoFrom(ctx, true) | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		return err | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return q.pluginClient.CallResource(ctx, req, sender) | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (q *DefaultQuerier) Health(ctx context.Context, query *backend.CheckHealthRequest) (*backend.CheckHealthResult, error) { | 
					
						
							|  |  |  | 	_, err := request.NamespaceInfoFrom(ctx, true) | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		return nil, err | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return q.pluginClient.CheckHealth(ctx, query) | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2025-08-29 20:49:57 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | func (q *DefaultQuerier) Datasource(ctx context.Context, name string) (*v0alpha1.DataSourceConnection, error) { | 
					
						
							|  |  |  | 	info, err := request.NamespaceInfoFrom(ctx, true) | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		return nil, err | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	user, err := identity.GetRequester(ctx) | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		return nil, err | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	ds, err := q.dsCache.GetDatasourceByUID(ctx, name, user, false) | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		return nil, err | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return asConnection(ds, info.Value) | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (q *DefaultQuerier) Datasources(ctx context.Context) (*v0alpha1.DataSourceConnectionList, error) { | 
					
						
							|  |  |  | 	info, err := request.NamespaceInfoFrom(ctx, true) | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		return nil, err | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	ds, err := q.dsService.GetDataSourcesByType(ctx, &datasources.GetDataSourcesByTypeQuery{ | 
					
						
							|  |  |  | 		OrgID: info.OrgID, | 
					
						
							|  |  |  | 		Type:  q.pluginJSON.ID, | 
					
						
							|  |  |  | 	}) | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		return nil, err | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return asConnectionList(q.connectionResourceInfo.TypeMeta(), ds, info.Value) | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func asConnectionList(typeMeta metav1.TypeMeta, dss []*datasources.DataSource, ns string) (*v0alpha1.DataSourceConnectionList, error) { | 
					
						
							|  |  |  | 	result := &v0alpha1.DataSourceConnectionList{ | 
					
						
							|  |  |  | 		Items: []v0alpha1.DataSourceConnection{}, | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	for _, ds := range dss { | 
					
						
							|  |  |  | 		v, _ := asConnection(ds, ns) | 
					
						
							|  |  |  | 		result.Items = append(result.Items, *v) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return result, nil | 
					
						
							|  |  |  | } |