github.com/hashicorp/go-plugin@v1.6.0/docs/guide-plugin-write-non-go.md (about)

     1  # Writing Plugins Without Go
     2  
     3  This guide explains how to write a go-plugin compatible plugin using
     4  a programming language other than Go. go-plugin supports plugins using
     5  [gRPC](http://www.grpc.io). This makes it relatively simple to write plugins
     6  using other languages!
     7  
     8  Minimal knowledge about gRPC is assumed. We recommend reading the
     9  [gRPC Go Tutorial](http://www.grpc.io/docs/tutorials/basic/go.html). This
    10  alone is enough gRPC knowledge to continue.
    11  
    12  This guide will implement the kv example in Python.
    13  Full source code for the examples present in this guide
    14  [is available in the examples/grpc folder](https://github.com/hashicorp/go-plugin/tree/master/examples/grpc).
    15  
    16  ## 1. Implement the Service
    17  
    18  The first step is to implement the gRPC server for the protocol buffers
    19  service that your plugin defines. This is a standard gRPC server.
    20  For the KV service, the service looks like this:
    21  
    22  ```proto
    23  service KV {
    24      rpc Get(GetRequest) returns (GetResponse);
    25      rpc Put(PutRequest) returns (Empty);
    26  }
    27  ```
    28  
    29  We can implement that using Python as easily as:
    30  
    31  ```python
    32  class KVServicer(kv_pb2_grpc.KVServicer):
    33      """Implementation of KV service."""
    34  
    35      def Get(self, request, context):
    36          filename = "kv_"+request.key
    37          with open(filename, 'r') as f:
    38              result = kv_pb2.GetResponse()
    39              result.value = f.read()
    40              return result
    41  
    42      def Put(self, request, context):
    43          filename = "kv_"+request.key
    44          value = "{0}\n\nWritten from plugin-python".format(request.value)
    45          with open(filename, 'w') as f:
    46              f.write(value)
    47  
    48          return kv_pb2.Empty()
    49  
    50  ```
    51  
    52  Great! With that, we have a fully functioning implementation of the service.
    53  You can test this using standard gRPC testing mechanisms.
    54  
    55  ## 2. Serve the Service
    56  
    57  Next, we need to create a gRPC server and serve the service we just made.
    58  
    59  In Python:
    60  
    61  ```python
    62  # Make the server
    63  server = grpc.server(futures.ThreadPoolExecutor(max_workers=10))
    64  
    65  # Add our service
    66  kv_pb2_grpc.add_KVServicer_to_server(KVServicer(), server)
    67  
    68  # Listen on a port
    69  server.add_insecure_port(':1234')
    70  
    71  # Start
    72  server.start()
    73  ```
    74  
    75  You can listen on any TCP address or Unix domain socket. go-plugin does
    76  assume that connections are reliable (local), so you should not serve
    77  your plugin across the network.
    78  
    79  ## 3. Add the gRPC Health Checking Service
    80  
    81  go-plugin requires the
    82  [gRPC Health Checking Service](https://github.com/grpc/grpc/blob/master/doc/health-checking.md)
    83  to be registered on your server. You must register the status of "plugin" to be SERVING.
    84  
    85  The health checking service is used by go-plugin to determine if everything
    86  is healthy with the connection. If you don't implement this service, your
    87  process may be abruptly restarted and your plugins are likely to be unreliable.
    88  
    89  ```
    90  health = HealthServicer()
    91  health.set("plugin", health_pb2.HealthCheckResponse.ServingStatus.Value('SERVING'))
    92  health_pb2_grpc.add_HealthServicer_to_server(health, server)
    93  ```
    94  
    95  ## 4. Output Handshake Information
    96  
    97  The final step is to output the handshake information to stdout. go-plugin
    98  reads a single line from stdout to determine how to connect to your plugin,
    99  what protocol it is using, etc.
   100  
   101  
   102  The structure is:
   103  
   104  ```
   105  CORE-PROTOCOL-VERSION | APP-PROTOCOL-VERSION | NETWORK-TYPE | NETWORK-ADDR | PROTOCOL
   106  ```
   107  
   108  Where:
   109  
   110    * `CORE-PROTOCOL-VERSION` is the protocol version for go-plugin itself.
   111      The current value is `1`. Please use this value. Any other value will
   112      cause your plugin to not load.
   113  
   114    * `APP-PROTOCOL-VERSION` is the protocol version for the application data.
   115      This is determined by the application. You must reference the documentation
   116      for your application to determine the desired value.
   117  
   118    * `NETWORK-TYPE` and `NETWORK-ADDR` are the networking information for
   119      connecting to this plugin. The type must be "unix" or "tcp". The address
   120      is a path to the Unix socket for "unix" and an IP address for "tcp".
   121  
   122    * `PROTOCOL` is the named protocol that the connection will use. If this
   123      is omitted (older versions), this is "netrpc" for Go net/rpc. This can
   124      also be "grpc". This is the protocol that the plugin wants to speak to
   125      the host process with.
   126  
   127  For our example that is:
   128  
   129  ```
   130  1|1|tcp|127.0.0.1:1234|grpc
   131  ```
   132  
   133  The only element you'll have to be careful about is the second one (the
   134  `APP-PROTOCOL-VERISON`). This will depend on the application you're
   135  building a plugin for. Please reference their documentation for more
   136  information.
   137  
   138  ## 5. Done!
   139  
   140  And we're done!
   141  
   142  Configure the host application (the application you're writing a plugin
   143  for) to execute your Python application. Configuring plugins is specific
   144  to the host application.
   145  
   146  For our example, we used an environmental variable, and it looks like this:
   147  
   148  ```sh
   149  $ export KV_PLUGIN="python plugin.py"
   150  ```