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 }