/usr/share/gocode/src/github.com/hashicorp/go-plugin/examples/basic/main.go is in golang-github-hashicorp-go-plugin-dev 0.0~git20160212.0.cccb4a1-1.
This file is owned by root:root, with mode 0o644.
The actual contents of the file can be viewed below.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 | package main
import (
"fmt"
"io/ioutil"
"log"
"net/rpc"
"os"
"os/exec"
"github.com/hashicorp/go-plugin"
)
func main() {
// Normal a plugin will be a separate binary. We put both in one
// here so that it is easy to build and use this example.
if len(os.Args) >= 2 && os.Args[1] != "" {
mainPlugin()
return
}
// We don't want to see the plugin logs.
log.SetOutput(ioutil.Discard)
// We're a host! Start by launching the plugin process.
client := plugin.NewClient(&plugin.ClientConfig{
HandshakeConfig: handshakeConfig,
Plugins: pluginMap,
Cmd: exec.Command(os.Args[0], "plugin"),
})
defer client.Kill()
// Connect via RPC
rpcClient, err := client.Client()
if err != nil {
log.Fatal(err)
}
// Request the plugin
raw, err := rpcClient.Dispense("greeter")
if err != nil {
log.Fatal(err)
}
// We should have a Greeter now! This feels like a normal interface
// implementation but is in fact over an RPC connection.
greeter := raw.(Greeter)
fmt.Println(greeter.Greet())
}
func mainPlugin() {
// We're a plugin! Serve the plugin. We set the handshake config
// so that the host and our plugin can verify they can talk to each other.
// Then we set the plugin map to say what plugins we're serving.
plugin.Serve(&plugin.ServeConfig{
HandshakeConfig: handshakeConfig,
Plugins: pluginMap,
})
}
// handshakeConfigs are used to just do a basic handshake between
// a plugin and host. If the handshake fails, a user friendly error is shown.
// This prevents users from executing bad plugins or executing a plugin
// directory. It is a UX feature, not a security feature.
var handshakeConfig = plugin.HandshakeConfig{
ProtocolVersion: 1,
MagicCookieKey: "BASIC_PLUGIN",
MagicCookieValue: "hello",
}
// pluginMap is the map of plugins we can dispense.
var pluginMap = map[string]plugin.Plugin{
"greeter": new(GreeterPlugin),
}
// Greeter is the interface that we're exposing as a plugin.
type Greeter interface {
Greet() string
}
// Here is a real implementation of Greeter
type GreeterHello struct{}
func (GreeterHello) Greet() string { return "Hello!" }
// Here is an implementation that talks over RPC
type GreeterRPC struct{ client *rpc.Client }
func (g *GreeterRPC) Greet() string {
var resp string
err := g.client.Call("Plugin.Greet", new(interface{}), &resp)
if err != nil {
// You usually want your interfaces to return errors. If they don't,
// there isn't much other choice here.
panic(err)
}
return resp
}
// Here is the RPC server that GreeterRPC talks to, conforming to
// the requirements of net/rpc
type GreeterRPCServer struct {
// This is the real implementation
Impl Greeter
}
func (s *GreeterRPCServer) Greet(args interface{}, resp *string) error {
*resp = s.Impl.Greet()
return nil
}
// This is the implementation of plugin.Plugin so we can serve/consume this
//
// This has two methods: Server must return an RPC server for this plugin
// type. We construct a GreeterRPCServer for this.
//
// Client must return an implementation of our interface that communicates
// over an RPC client. We return GreeterRPC for this.
//
// Ignore MuxBroker. That is used to create more multiplexed streams on our
// plugin connection and is a more advanced use case.
type GreeterPlugin struct{}
func (GreeterPlugin) Server(*plugin.MuxBroker) (interface{}, error) {
return &GreeterRPCServer{Impl: new(GreeterHello)}, nil
}
func (GreeterPlugin) Client(b *plugin.MuxBroker, c *rpc.Client) (interface{}, error) {
return &GreeterRPC{client: c}, nil
}
|