From ea0555215555f536dbdb2f3db507b6e968140dcd Mon Sep 17 00:00:00 2001 From: Srinivasa Kartheek Date: Fri, 16 Jan 2026 03:55:06 +0530 Subject: [PATCH 1/5] chore: add plugin selection and fix encoding in gRPC example --- examples/grpc/README.md | 16 ++++++++++------ examples/grpc/main.go | 9 ++++++++- examples/grpc/plugin-python/plugin.py | 2 +- 3 files changed, 19 insertions(+), 8 deletions(-) diff --git a/examples/grpc/README.md b/examples/grpc/README.md index 63c4af5e..5a71c90b 100644 --- a/examples/grpc/README.md +++ b/examples/grpc/README.md @@ -10,7 +10,8 @@ $ go build -o kv # This builds the plugin written in Go $ go build -o kv-go-grpc ./plugin-go-grpc -# This tells the KV binary to use the "kv-go-grpc" binary +# This tells the KV binary to use the "kv-go-grpc" binary over gRPC +$ export KV_PLUGIN_NAME=kv_grpc $ export KV_PLUGIN="./kv-go-grpc" # Read and write @@ -24,11 +25,12 @@ world This plugin uses gRPC to serve a plugin that is written in Go: -``` +```sh # This builds the plugin written in Go $ go build -o kv-go-grpc ./plugin-go-grpc -# This tells the KV binary to use the "kv-go-grpc" binary +# This tells the KV binary to use the "kv-go-grpc" binary over gRPC +$ export KV_PLUGIN_NAME=kv_grpc $ export KV_PLUGIN="./kv-go-grpc" ``` @@ -36,11 +38,12 @@ $ export KV_PLUGIN="./kv-go-grpc" This plugin uses the builtin Go net/rpc mechanism to serve the plugin: -``` +```sh # This builds the plugin written in Go $ go build -o kv-go-netrpc ./plugin-go-netrpc -# This tells the KV binary to use the "kv-go-netrpc" binary +# This tells the KV binary to use the "kv-go-netrpc" binary over net/rpc +$ export KV_PLUGIN_NAME=kv $ export KV_PLUGIN="./kv-go-netrpc" ``` @@ -48,10 +51,11 @@ $ export KV_PLUGIN="./kv-go-netrpc" This plugin is written in Python: -``` +```sh $ python -m venv plugin-python/.venv $ source plugin-python/.venv/bin/activate $ pip install -r plugin-python/requirements.txt +$ export KV_PLUGIN_NAME=kv_grpc $ export KV_PLUGIN="python plugin-python/plugin.py" ``` diff --git a/examples/grpc/main.go b/examples/grpc/main.go index bb9ab42c..ec108cc4 100644 --- a/examples/grpc/main.go +++ b/examples/grpc/main.go @@ -7,14 +7,21 @@ import ( "fmt" "io" "log" + "maps" "os" "os/exec" + "slices" "github.com/hashicorp/go-plugin" "github.com/hashicorp/go-plugin/examples/grpc/shared" ) func run() error { + pluginName := os.Getenv("KV_PLUGIN_NAME") + if _, ok := shared.PluginMap[pluginName]; !ok { + return fmt.Errorf("please set KV_PLUGIN_NAME to one of %q", slices.Collect(maps.Keys(shared.PluginMap))) + } + // We're a host. Start by launching the plugin process. client := plugin.NewClient(&plugin.ClientConfig{ HandshakeConfig: shared.Handshake, @@ -32,7 +39,7 @@ func run() error { } // Request the plugin - raw, err := rpcClient.Dispense("kv_grpc") + raw, err := rpcClient.Dispense(pluginName) if err != nil { return err } diff --git a/examples/grpc/plugin-python/plugin.py b/examples/grpc/plugin-python/plugin.py index 0bc57db2..a1a88497 100644 --- a/examples/grpc/plugin-python/plugin.py +++ b/examples/grpc/plugin-python/plugin.py @@ -25,7 +25,7 @@ def Get(self, request, context): def Put(self, request, context): filename = "kv_"+request.key - value = "{0}\n\nWritten from plugin-python".format(request.value) + value = "{0}\n\nWritten from plugin-python".format(request.value.decode('utf-8')) with open(filename, 'w') as f: f.write(value) From 693aa06b1bd695f3491c2c3c8a170543c50912c1 Mon Sep 17 00:00:00 2001 From: Srinivasa Kartheek Date: Fri, 16 Jan 2026 04:30:18 +0530 Subject: [PATCH 2/5] Fix doc comment --- examples/bidirectional/shared/interface.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/bidirectional/shared/interface.go b/examples/bidirectional/shared/interface.go index a12c3295..23594b4c 100644 --- a/examples/bidirectional/shared/interface.go +++ b/examples/bidirectional/shared/interface.go @@ -29,7 +29,7 @@ type AddHelper interface { Sum(int64, int64) (int64, error) } -// KV is the interface that we're exposing as a plugin. +// Counter is the interface that we're exposing as a plugin. type Counter interface { Put(key string, value int64, a AddHelper) error Get(key string) (int64, error) From fca49012fb41a67fb9c591f29b74899dd59ad70b Mon Sep 17 00:00:00 2001 From: Srinivasa Kartheek Date: Fri, 16 Jan 2026 04:50:43 +0530 Subject: [PATCH 3/5] More updates to doc comments --- examples/bidirectional/shared/grpc.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/bidirectional/shared/grpc.go b/examples/bidirectional/shared/grpc.go index 85edbd8f..74d6dd87 100644 --- a/examples/bidirectional/shared/grpc.go +++ b/examples/bidirectional/shared/grpc.go @@ -77,7 +77,7 @@ func (m *GRPCServer) Get(ctx context.Context, req *proto.GetRequest) (*proto.Get return &proto.GetResponse{Value: v}, err } -// GRPCClient is an implementation of KV that talks over RPC. +// GRPCAddHelperClient is an implementation of AddHelper that talks over RPC. type GRPCAddHelperClient struct{ client proto.AddHelperClient } func (m *GRPCAddHelperClient) Sum(a, b int64) (int64, error) { @@ -92,7 +92,7 @@ func (m *GRPCAddHelperClient) Sum(a, b int64) (int64, error) { return resp.R, err } -// Here is the gRPC server that GRPCClient talks to. +// Here is the gRPC server that GRPCAddHelperClient talks to. type GRPCAddHelperServer struct { // This is the real implementation Impl AddHelper From 831813e8fac0f4dbac9338d1c27854691f63b696 Mon Sep 17 00:00:00 2001 From: Srinivasa Kartheek Date: Fri, 16 Jan 2026 04:53:28 +0530 Subject: [PATCH 4/5] Add .gitignore to bidirectional example --- examples/bidirectional/.gitignore | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 examples/bidirectional/.gitignore diff --git a/examples/bidirectional/.gitignore b/examples/bidirectional/.gitignore new file mode 100644 index 00000000..69f8fee4 --- /dev/null +++ b/examples/bidirectional/.gitignore @@ -0,0 +1,3 @@ +/counter +/counter-* +/kv_* From 82248d8d57f49780c6840b6b96036154a65d5002 Mon Sep 17 00:00:00 2001 From: Srinivasa Kartheek Date: Fri, 16 Jan 2026 05:02:31 +0530 Subject: [PATCH 5/5] Use KV_PROTO environment variable to be consistent --- examples/grpc/main.go | 18 +++++++++++------- examples/grpc/shared/interface.go | 9 +++++++-- 2 files changed, 18 insertions(+), 9 deletions(-) diff --git a/examples/grpc/main.go b/examples/grpc/main.go index ec108cc4..d150d74d 100644 --- a/examples/grpc/main.go +++ b/examples/grpc/main.go @@ -7,21 +7,14 @@ import ( "fmt" "io" "log" - "maps" "os" "os/exec" - "slices" "github.com/hashicorp/go-plugin" "github.com/hashicorp/go-plugin/examples/grpc/shared" ) func run() error { - pluginName := os.Getenv("KV_PLUGIN_NAME") - if _, ok := shared.PluginMap[pluginName]; !ok { - return fmt.Errorf("please set KV_PLUGIN_NAME to one of %q", slices.Collect(maps.Keys(shared.PluginMap))) - } - // We're a host. Start by launching the plugin process. client := plugin.NewClient(&plugin.ClientConfig{ HandshakeConfig: shared.Handshake, @@ -38,6 +31,17 @@ func run() error { return err } + var pluginName string + switch os.Getenv("KV_PROTO") { + case "netrpc": + pluginName = shared.PluginNetRPC + case "grpc": + pluginName = shared.PluginGRPC + default: + fmt.Println("must set KV_PROTO to netrpc or grpc") + os.Exit(1) + } + // Request the plugin raw, err := rpcClient.Dispense(pluginName) if err != nil { diff --git a/examples/grpc/shared/interface.go b/examples/grpc/shared/interface.go index 2fad93f2..140af046 100644 --- a/examples/grpc/shared/interface.go +++ b/examples/grpc/shared/interface.go @@ -14,6 +14,11 @@ import ( "github.com/hashicorp/go-plugin/examples/grpc/proto" ) +const ( + PluginNetRPC = "kv" + PluginGRPC = "kv_grpc" +) + // Handshake is a common handshake that is shared by plugin and host. var Handshake = plugin.HandshakeConfig{ // This isn't required when using VersionedPlugins @@ -24,8 +29,8 @@ var Handshake = plugin.HandshakeConfig{ // PluginMap is the map of plugins we can dispense. var PluginMap = map[string]plugin.Plugin{ - "kv_grpc": &KVGRPCPlugin{}, - "kv": &KVPlugin{}, + PluginGRPC: &KVGRPCPlugin{}, + PluginNetRPC: &KVPlugin{}, } // KV is the interface that we're exposing as a plugin.