Skip to content

Commit

Permalink
Add experimental test manage func (#704)
Browse files Browse the repository at this point in the history
* add test manage func

* flesh out

* fix linter

* adjust test to use experimental package

* regenerate

* delete dir

* Experimental: OAuth Token Retriever (#702)

Co-authored-by: Mihaly Gyongyosi <[email protected]>

* fix golden file

* update package name

* fix test

* fix golden file

* undo commit

* fix comment

* shutdown for plugin

---------

Co-authored-by: Andres Martinez Gotor <[email protected]>
Co-authored-by: Mihaly Gyongyosi <[email protected]>
  • Loading branch information
3 people authored Jun 29, 2023
1 parent 6be9232 commit 792f8fd
Show file tree
Hide file tree
Showing 12 changed files with 258 additions and 435 deletions.
57 changes: 57 additions & 0 deletions backend/serve.go
Original file line number Diff line number Diff line change
Expand Up @@ -251,3 +251,60 @@ func Manage(pluginID string, serveOpts ServeOpts) error {
// The default/normal hashicorp path.
return Serve(serveOpts)
}

// TestStandaloneServe starts a gRPC server that is not managed by hashicorp.
// The function returns the gRPC server which should be closed by the consumer.
func TestStandaloneServe(opts ServeOpts, address string) (*grpc.Server, error) {
pluginOpts := asGRPCServeOpts(opts)
if pluginOpts.GRPCServer == nil {
pluginOpts.GRPCServer = func(grpcOptions []grpc.ServerOption) *grpc.Server {
return grpc.NewServer(append(defaultGRPCMiddlewares(opts), grpcOptions...)...)
}
}

server := pluginOpts.GRPCServer(nil)

var plugKeys []string
if pluginOpts.DiagnosticsServer != nil {
pluginv2.RegisterDiagnosticsServer(server, pluginOpts.DiagnosticsServer)
plugKeys = append(plugKeys, "diagnostics")
}

if pluginOpts.ResourceServer != nil {
pluginv2.RegisterResourceServer(server, pluginOpts.ResourceServer)
plugKeys = append(plugKeys, "resources")
}

if pluginOpts.DataServer != nil {
pluginv2.RegisterDataServer(server, pluginOpts.DataServer)
plugKeys = append(plugKeys, "data")
}

if pluginOpts.StreamServer != nil {
pluginv2.RegisterStreamServer(server, pluginOpts.StreamServer)
plugKeys = append(plugKeys, "stream")
}

// Start the GRPC server and handle graceful shutdown to ensure we execute deferred functions correctly
log.DefaultLogger.Info("Standalone plugin server", "capabilities", plugKeys)
listener, err := net.Listen("tcp", address)
if err != nil {
return nil, err
}

serverErrChan := make(chan error, 1)
// Start GRPC server in a separate goroutine
go func() {
serverErrChan <- server.Serve(listener)
}()

// Wait until signal or GRPC server termination in a separate goroutine
go func() {
err := <-serverErrChan
if err != nil {
log.DefaultLogger.Error("Server experienced an error", "error", err)
}
}()

return server, nil
}
96 changes: 96 additions & 0 deletions experimental/datasourcetest/client.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
package datasourcetest

import (
"context"
"errors"
"io"

"google.golang.org/grpc"
"google.golang.org/grpc/codes"
"google.golang.org/grpc/credentials/insecure"
"google.golang.org/grpc/status"

"github.com/grafana/grafana-plugin-sdk-go/backend"
"github.com/grafana/grafana-plugin-sdk-go/genproto/pluginv2"
)

type TestPluginClient struct {
DataClient pluginv2.DataClient
DiagnosticsClient pluginv2.DiagnosticsClient
ResourceClient pluginv2.ResourceClient

conn *grpc.ClientConn
}

func newTestPluginClient(addr string) (*TestPluginClient, error) {
c, err := grpc.Dial(addr, grpc.WithTransportCredentials(insecure.NewCredentials()), grpc.WithBlock())
if err != nil {
return nil, err
}

return &TestPluginClient{
conn: c,
DiagnosticsClient: pluginv2.NewDiagnosticsClient(c),
DataClient: pluginv2.NewDataClient(c),
ResourceClient: pluginv2.NewResourceClient(c),
}, nil
}

func (p *TestPluginClient) QueryData(ctx context.Context, r *backend.QueryDataRequest) (*backend.QueryDataResponse, error) {
req := backend.ToProto().QueryDataRequest(r)

resp, err := p.DataClient.QueryData(ctx, req)
if err != nil {
return nil, err
}

return backend.FromProto().QueryDataResponse(resp)
}

func (p *TestPluginClient) CheckHealth(ctx context.Context, r *backend.CheckHealthRequest) (*backend.CheckHealthResult, error) {
req := &pluginv2.CheckHealthRequest{
PluginContext: backend.ToProto().PluginContext(r.PluginContext),
}

resp, err := p.DiagnosticsClient.CheckHealth(ctx, req)
if err != nil {
return nil, err
}

return backend.FromProto().CheckHealthResponse(resp), nil
}

func (p *TestPluginClient) CallResource(ctx context.Context, r *backend.CallResourceRequest, sender backend.CallResourceResponseSender) error {
protoReq := backend.ToProto().CallResourceRequest(r)
protoStream, err := p.ResourceClient.CallResource(ctx, protoReq)
if err != nil {
if status.Code(err) == codes.Unimplemented {
return errors.New("method not implemented")
}

return err
}

for {
protoResp, err := protoStream.Recv()
if err != nil {
if status.Code(err) == codes.Unimplemented {
return errors.New("method not implemented")
}

if errors.Is(err, io.EOF) {
return nil
}

return err
}

if err = sender.Send(backend.FromProto().CallResourceResponse(protoResp)); err != nil {
return err
}
}
}

func (p *TestPluginClient) shutdown() error {
return p.conn.Close()
}
51 changes: 51 additions & 0 deletions experimental/datasourcetest/manage.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
package datasourcetest

import (
"github.com/grafana/grafana-plugin-sdk-go/backend"
"github.com/grafana/grafana-plugin-sdk-go/backend/datasource"
"github.com/grafana/grafana-plugin-sdk-go/internal/automanagement"
)

type ManageOpts struct {
Address string
}

type TestPlugin struct {
Client *TestPluginClient
Server *TestPluginServer
}

func (p *TestPlugin) Shutdown() error {
if p.Server != nil {
p.Server.shutdown()
}

if p.Client != nil {
return p.Client.shutdown()
}
return nil
}

func Manage(instanceFactory datasource.InstanceFactoryFunc, opts ManageOpts) (TestPlugin, error) {
handler := automanagement.NewManager(datasource.NewInstanceManager(instanceFactory))
s, err := backend.TestStandaloneServe(backend.ServeOpts{
CheckHealthHandler: handler,
CallResourceHandler: handler,
QueryDataHandler: handler,
StreamHandler: handler,
}, opts.Address)

if err != nil {
return TestPlugin{}, err
}

c, err := newTestPluginClient(opts.Address)
if err != nil {
return TestPlugin{}, err
}

return TestPlugin{
Client: c,
Server: newTestPluginServer(s),
}, nil
}
16 changes: 16 additions & 0 deletions experimental/datasourcetest/server.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package datasourcetest

import "google.golang.org/grpc"

type TestPluginServer struct {
srv *grpc.Server
}

func newTestPluginServer(s *grpc.Server) *TestPluginServer {
return &TestPluginServer{
srv: s,
}
}
func (s *TestPluginServer) shutdown() {
s.srv.Stop()
}
57 changes: 0 additions & 57 deletions experimental/oauthtokenretriever/sign.go

This file was deleted.

51 changes: 0 additions & 51 deletions experimental/oauthtokenretriever/sign_test.go

This file was deleted.

Loading

0 comments on commit 792f8fd

Please sign in to comment.