github.com/drellem2/pogo@v0.0.0-20240503070746-2c2b76da329a/pkg/plugin/plugin_interface.go (about)

     1  package plugin
     2  
     3  import (
     4  	"fmt"
     5  	"net/rpc"
     6  
     7  	"github.com/hashicorp/go-plugin"
     8  )
     9  
    10  type DataObject struct {
    11  	Plugin string `json:"plugin"`
    12  	Value  string `json:"value"`
    13  }
    14  
    15  type IProcessProjectReq interface {
    16  	Path() string
    17  }
    18  
    19  type ProcessProjectReq struct {
    20  	PathVar string
    21  }
    22  
    23  func (r ProcessProjectReq) Path() string {
    24  	return r.PathVar
    25  }
    26  
    27  type PluginInfoRes struct {
    28  	Version string `json:"version"`
    29  }
    30  
    31  // The interface that plugins should implement
    32  type IPogoPlugin interface {
    33  	// Returns info about the plugin. Most importantly API version.
    34  	Info() *PluginInfoRes
    35  
    36  	// Executes a url-encoded json string, and returns one.
    37  	Execute(req string) string
    38  
    39  	// Notifies the plugin that a project exists. It is the plugin's responsibility
    40  	// to decide when and to what extent action should be taken.
    41  	ProcessProject(req *IProcessProjectReq) error
    42  }
    43  
    44  // Here is an implementation that talks over RPC
    45  type PluginRPC struct{ client *rpc.Client }
    46  
    47  func (g *PluginRPC) Info() *PluginInfoRes {
    48  	var resp *PluginInfoRes
    49  	err := g.client.Call("Plugin.Info", new(interface{}), &resp)
    50  	if err != nil {
    51  		fmt.Printf("Error finding plugin info: %v", err)
    52  		return nil
    53  	}
    54  	return resp
    55  }
    56  
    57  func (g *PluginRPC) Execute(req string) string {
    58  	var resp string
    59  	err := g.client.Call("Plugin.Execute", req, &resp)
    60  	if err != nil {
    61  		fmt.Printf("Error executing plugin call: %v", err)
    62  		return ""
    63  	}
    64  	return resp
    65  }
    66  
    67  func (g *PluginRPC) ProcessProject(req *IProcessProjectReq) error {
    68  	var resp error
    69  	err := g.client.Call("Plugin.ProcessProject", req, &resp)
    70  	if err != nil {
    71  		return err
    72  	}
    73  
    74  	return resp
    75  }
    76  
    77  // Here is the RPC server that PluginRPC talks to, conforming to
    78  // the requirements of net/rpc
    79  type PluginRPCServer struct {
    80  	// This is the real implementation
    81  	Impl IPogoPlugin
    82  }
    83  
    84  func (s *PluginRPCServer) Info(args interface{}, resp **PluginInfoRes) error {
    85  	*resp = s.Impl.Info()
    86  	return nil
    87  }
    88  
    89  func (s *PluginRPCServer) Execute(req string, resp *string) error {
    90  	*resp = s.Impl.Execute(req)
    91  	return nil
    92  }
    93  
    94  func (s *PluginRPCServer) ProcessProject(args interface{}, resp *error) error {
    95  	var iargs = args.(IProcessProjectReq)
    96  	*resp = s.Impl.ProcessProject(&iargs)
    97  	return nil
    98  }
    99  
   100  // This is the implementation of plugin.Plugin so we can serve/consume this
   101  //
   102  // This has two methods: Server must return an RPC server for this plugin
   103  // type. We construct a PluginRPCServer for this.
   104  //
   105  // Client must return an implementation of our interface that communicates
   106  // over an RPC client. We return PluginRPC for this.
   107  //
   108  // Ignore MuxBroker. That is used to create more multiplexed streams on our
   109  // plugin connection and is a more advanced use case.
   110  type PogoPlugin struct {
   111  	// Impl Injection
   112  	Impl IPogoPlugin
   113  }
   114  
   115  func (p *PogoPlugin) Server(*plugin.MuxBroker) (interface{}, error) {
   116  	return &PluginRPCServer{Impl: p.Impl}, nil
   117  }
   118  
   119  func (PogoPlugin) Client(b *plugin.MuxBroker, c *rpc.Client) (interface{}, error) {
   120  	return &PluginRPC{client: c}, nil
   121  }