| 
									
										
										
										
											2023-11-03 21:01:08 +08:00
										 |  |  | package grpcplugin | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | import ( | 
					
						
							|  |  |  | 	"context" | 
					
						
							|  |  |  | 	"errors" | 
					
						
							| 
									
										
										
										
											2023-11-13 21:41:53 +08:00
										 |  |  | 	"sync" | 
					
						
							| 
									
										
										
										
											2023-11-03 21:01:08 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	"google.golang.org/grpc" | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	"github.com/grafana/grafana-plugin-sdk-go/genproto/pluginv2" | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-04-18 00:47:01 +08:00
										 |  |  | 	"github.com/grafana/grafana/pkg/plugins" | 
					
						
							|  |  |  | 	"github.com/grafana/grafana/pkg/plugins/backendplugin" | 
					
						
							| 
									
										
										
										
											2023-11-03 21:01:08 +08:00
										 |  |  | 	"github.com/grafana/grafana/pkg/plugins/log" | 
					
						
							|  |  |  | ) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | var ( | 
					
						
							|  |  |  | 	errClientNotStarted = errors.New("plugin client has not been started") | 
					
						
							|  |  |  | ) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | var _ ProtoClient = (*protoClient)(nil) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | type ProtoClient interface { | 
					
						
							|  |  |  | 	pluginv2.DataClient | 
					
						
							|  |  |  | 	pluginv2.ResourceClient | 
					
						
							|  |  |  | 	pluginv2.DiagnosticsClient | 
					
						
							|  |  |  | 	pluginv2.StreamClient | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-11-17 20:52:31 +08:00
										 |  |  | 	PID(context.Context) (string, error) | 
					
						
							| 
									
										
										
										
											2023-11-03 21:01:08 +08:00
										 |  |  | 	PluginID() string | 
					
						
							| 
									
										
										
										
											2023-11-15 23:53:30 +08:00
										 |  |  | 	PluginVersion() string | 
					
						
							| 
									
										
										
										
											2024-04-18 00:47:01 +08:00
										 |  |  | 	PluginJSON() plugins.JSONData | 
					
						
							|  |  |  | 	Backend() backendplugin.Plugin | 
					
						
							| 
									
										
										
										
											2023-11-03 21:01:08 +08:00
										 |  |  | 	Logger() log.Logger | 
					
						
							|  |  |  | 	Start(context.Context) error | 
					
						
							|  |  |  | 	Stop(context.Context) error | 
					
						
							| 
									
										
										
										
											2023-11-17 20:52:31 +08:00
										 |  |  | 	Running(context.Context) bool | 
					
						
							| 
									
										
										
										
											2023-11-03 21:01:08 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | type protoClient struct { | 
					
						
							| 
									
										
										
										
											2023-11-15 23:53:30 +08:00
										 |  |  | 	plugin        *grpcPlugin | 
					
						
							|  |  |  | 	pluginVersion string | 
					
						
							| 
									
										
										
										
											2024-04-18 00:47:01 +08:00
										 |  |  | 	pluginJSON    plugins.JSONData | 
					
						
							| 
									
										
										
										
											2023-11-13 21:41:53 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	mu sync.RWMutex | 
					
						
							| 
									
										
										
										
											2023-11-03 21:01:08 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | type ProtoClientOpts struct { | 
					
						
							| 
									
										
										
										
											2024-04-18 00:47:01 +08:00
										 |  |  | 	PluginJSON     plugins.JSONData | 
					
						
							| 
									
										
										
										
											2023-11-03 21:01:08 +08:00
										 |  |  | 	ExecutablePath string | 
					
						
							|  |  |  | 	ExecutableArgs []string | 
					
						
							|  |  |  | 	Env            []string | 
					
						
							|  |  |  | 	Logger         log.Logger | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func NewProtoClient(opts ProtoClientOpts) (ProtoClient, error) { | 
					
						
							|  |  |  | 	p := newGrpcPlugin( | 
					
						
							|  |  |  | 		PluginDescriptor{ | 
					
						
							| 
									
										
										
										
											2024-04-18 00:47:01 +08:00
										 |  |  | 			pluginID:         opts.PluginJSON.ID, | 
					
						
							| 
									
										
										
										
											2023-11-03 21:01:08 +08:00
										 |  |  | 			managed:          true, | 
					
						
							|  |  |  | 			executablePath:   opts.ExecutablePath, | 
					
						
							|  |  |  | 			executableArgs:   opts.ExecutableArgs, | 
					
						
							|  |  |  | 			versionedPlugins: pluginSet, | 
					
						
							|  |  |  | 		}, | 
					
						
							|  |  |  | 		opts.Logger, | 
					
						
							|  |  |  | 		func() []string { return opts.Env }, | 
					
						
							|  |  |  | 	) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-04-18 00:47:01 +08:00
										 |  |  | 	return &protoClient{plugin: p, pluginVersion: opts.PluginJSON.Info.Version, pluginJSON: opts.PluginJSON}, nil | 
					
						
							| 
									
										
										
										
											2023-11-03 21:01:08 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-11-17 20:52:31 +08:00
										 |  |  | func (r *protoClient) PID(ctx context.Context) (string, error) { | 
					
						
							|  |  |  | 	if _, exists := r.client(ctx); !exists { | 
					
						
							| 
									
										
										
										
											2023-11-13 21:41:53 +08:00
										 |  |  | 		return "", errClientNotStarted | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return r.plugin.client.ID(), nil | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-11-03 21:01:08 +08:00
										 |  |  | func (r *protoClient) PluginID() string { | 
					
						
							|  |  |  | 	return r.plugin.descriptor.pluginID | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-11-15 23:53:30 +08:00
										 |  |  | func (r *protoClient) PluginVersion() string { | 
					
						
							|  |  |  | 	return r.pluginVersion | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-04-18 00:47:01 +08:00
										 |  |  | func (r *protoClient) PluginJSON() plugins.JSONData { | 
					
						
							|  |  |  | 	return r.pluginJSON | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (r *protoClient) Backend() backendplugin.Plugin { | 
					
						
							|  |  |  | 	return r.plugin | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-11-03 21:01:08 +08:00
										 |  |  | func (r *protoClient) Logger() log.Logger { | 
					
						
							|  |  |  | 	return r.plugin.logger | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (r *protoClient) Start(ctx context.Context) error { | 
					
						
							| 
									
										
										
										
											2023-11-13 21:41:53 +08:00
										 |  |  | 	r.mu.Lock() | 
					
						
							|  |  |  | 	defer r.mu.Unlock() | 
					
						
							| 
									
										
										
										
											2023-11-03 21:01:08 +08:00
										 |  |  | 	return r.plugin.Start(ctx) | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (r *protoClient) Stop(ctx context.Context) error { | 
					
						
							| 
									
										
										
										
											2023-11-13 21:41:53 +08:00
										 |  |  | 	r.mu.Lock() | 
					
						
							|  |  |  | 	defer r.mu.Unlock() | 
					
						
							| 
									
										
										
										
											2023-11-03 21:01:08 +08:00
										 |  |  | 	return r.plugin.Stop(ctx) | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-11-17 20:52:31 +08:00
										 |  |  | func (r *protoClient) Running(_ context.Context) bool { | 
					
						
							|  |  |  | 	r.mu.RLock() | 
					
						
							|  |  |  | 	defer r.mu.RUnlock() | 
					
						
							|  |  |  | 	return !r.plugin.Exited() | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (r *protoClient) client(ctx context.Context) (*ClientV2, bool) { | 
					
						
							|  |  |  | 	if !r.Running(ctx) { | 
					
						
							|  |  |  | 		return nil, false | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-11-13 21:41:53 +08:00
										 |  |  | 	r.mu.RLock() | 
					
						
							| 
									
										
										
										
											2023-11-03 21:01:08 +08:00
										 |  |  | 	if r.plugin.pluginClient == nil { | 
					
						
							| 
									
										
										
										
											2023-11-13 21:41:53 +08:00
										 |  |  | 		r.mu.RUnlock() | 
					
						
							|  |  |  | 		return nil, false | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	pc := r.plugin.pluginClient | 
					
						
							|  |  |  | 	r.mu.RUnlock() | 
					
						
							|  |  |  | 	return pc, true | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (r *protoClient) QueryData(ctx context.Context, in *pluginv2.QueryDataRequest, opts ...grpc.CallOption) (*pluginv2.QueryDataResponse, error) { | 
					
						
							| 
									
										
										
										
											2023-11-17 20:52:31 +08:00
										 |  |  | 	c, exists := r.client(ctx) | 
					
						
							| 
									
										
										
										
											2023-11-13 21:41:53 +08:00
										 |  |  | 	if !exists { | 
					
						
							| 
									
										
										
										
											2023-11-03 21:01:08 +08:00
										 |  |  | 		return nil, errClientNotStarted | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2023-11-13 21:41:53 +08:00
										 |  |  | 	return c.DataClient.QueryData(ctx, in, opts...) | 
					
						
							| 
									
										
										
										
											2023-11-03 21:01:08 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (r *protoClient) CallResource(ctx context.Context, in *pluginv2.CallResourceRequest, opts ...grpc.CallOption) (pluginv2.Resource_CallResourceClient, error) { | 
					
						
							| 
									
										
										
										
											2023-11-17 20:52:31 +08:00
										 |  |  | 	c, exists := r.client(ctx) | 
					
						
							| 
									
										
										
										
											2023-11-13 21:41:53 +08:00
										 |  |  | 	if !exists { | 
					
						
							| 
									
										
										
										
											2023-11-03 21:01:08 +08:00
										 |  |  | 		return nil, errClientNotStarted | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2023-11-13 21:41:53 +08:00
										 |  |  | 	return c.ResourceClient.CallResource(ctx, in, opts...) | 
					
						
							| 
									
										
										
										
											2023-11-03 21:01:08 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (r *protoClient) CheckHealth(ctx context.Context, in *pluginv2.CheckHealthRequest, opts ...grpc.CallOption) (*pluginv2.CheckHealthResponse, error) { | 
					
						
							| 
									
										
										
										
											2023-11-17 20:52:31 +08:00
										 |  |  | 	c, exists := r.client(ctx) | 
					
						
							| 
									
										
										
										
											2023-11-13 21:41:53 +08:00
										 |  |  | 	if !exists { | 
					
						
							| 
									
										
										
										
											2023-11-03 21:01:08 +08:00
										 |  |  | 		return nil, errClientNotStarted | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2023-11-13 21:41:53 +08:00
										 |  |  | 	return c.DiagnosticsClient.CheckHealth(ctx, in, opts...) | 
					
						
							| 
									
										
										
										
											2023-11-03 21:01:08 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (r *protoClient) CollectMetrics(ctx context.Context, in *pluginv2.CollectMetricsRequest, opts ...grpc.CallOption) (*pluginv2.CollectMetricsResponse, error) { | 
					
						
							| 
									
										
										
										
											2023-11-17 20:52:31 +08:00
										 |  |  | 	c, exists := r.client(ctx) | 
					
						
							| 
									
										
										
										
											2023-11-13 21:41:53 +08:00
										 |  |  | 	if !exists { | 
					
						
							| 
									
										
										
										
											2023-11-03 21:01:08 +08:00
										 |  |  | 		return nil, errClientNotStarted | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2023-11-13 21:41:53 +08:00
										 |  |  | 	return c.DiagnosticsClient.CollectMetrics(ctx, in, opts...) | 
					
						
							| 
									
										
										
										
											2023-11-03 21:01:08 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (r *protoClient) SubscribeStream(ctx context.Context, in *pluginv2.SubscribeStreamRequest, opts ...grpc.CallOption) (*pluginv2.SubscribeStreamResponse, error) { | 
					
						
							| 
									
										
										
										
											2023-11-17 20:52:31 +08:00
										 |  |  | 	c, exists := r.client(ctx) | 
					
						
							| 
									
										
										
										
											2023-11-13 21:41:53 +08:00
										 |  |  | 	if !exists { | 
					
						
							| 
									
										
										
										
											2023-11-03 21:01:08 +08:00
										 |  |  | 		return nil, errClientNotStarted | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2023-11-13 21:41:53 +08:00
										 |  |  | 	return c.StreamClient.SubscribeStream(ctx, in, opts...) | 
					
						
							| 
									
										
										
										
											2023-11-03 21:01:08 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (r *protoClient) RunStream(ctx context.Context, in *pluginv2.RunStreamRequest, opts ...grpc.CallOption) (pluginv2.Stream_RunStreamClient, error) { | 
					
						
							| 
									
										
										
										
											2023-11-17 20:52:31 +08:00
										 |  |  | 	c, exists := r.client(ctx) | 
					
						
							| 
									
										
										
										
											2023-11-13 21:41:53 +08:00
										 |  |  | 	if !exists { | 
					
						
							| 
									
										
										
										
											2023-11-03 21:01:08 +08:00
										 |  |  | 		return nil, errClientNotStarted | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2023-11-13 21:41:53 +08:00
										 |  |  | 	return c.StreamClient.RunStream(ctx, in, opts...) | 
					
						
							| 
									
										
										
										
											2023-11-03 21:01:08 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (r *protoClient) PublishStream(ctx context.Context, in *pluginv2.PublishStreamRequest, opts ...grpc.CallOption) (*pluginv2.PublishStreamResponse, error) { | 
					
						
							| 
									
										
										
										
											2023-11-17 20:52:31 +08:00
										 |  |  | 	c, exists := r.client(ctx) | 
					
						
							| 
									
										
										
										
											2023-11-13 21:41:53 +08:00
										 |  |  | 	if !exists { | 
					
						
							| 
									
										
										
										
											2023-11-03 21:01:08 +08:00
										 |  |  | 		return nil, errClientNotStarted | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2023-11-13 21:41:53 +08:00
										 |  |  | 	return c.StreamClient.PublishStream(ctx, in, opts...) | 
					
						
							| 
									
										
										
										
											2023-11-03 21:01:08 +08:00
										 |  |  | } |