Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up

A Protobuf RPC framework for plugins.

License

NotificationsYou must be signed in to change notification settings

pluginrpc/pluginrpc

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

6 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

BuildBSRLicenseSlack

PluginRPC is an Protobuf RPC framework for plugins. It enables writing plugins defined by Protobufservices while only relying on CLI primitives such as args, stdin, and stdout. PluginRPC has noreliance on network calls. Individual RPCs are invoked via arguments passed to the CLI plugin,requests are sent on stdin, and responses are sent on stdout. It's everything you need to useProtobuf services to represent your plugin API without any of the cruft.

PluginRPC has the following goals:

  • Make it possible to evolve both the PluginRPC protocol and the APIs for individual plugins inbackward-compatible ways over time.
  • Make it possible to invoke multiple methods as part of a plugin. Many plugin frameworks onlyprovide for a single entrypoint. In contrast, PluginRPC provides the full power of Protobufservices: multiple services, and multiple RPCs per service, can be exposed.
  • Expose the plugin interface in CLI-idiomatic ways. PluginRPC exposes individual RPCs assub-commands with flags for control, optionally allowing the specific sub-commands to becustomizable. PluginRPC attempts to consume and produce requests and responses in a manner thatwill be readable by humans invoking the sub-commands.
  • Make it easy to call plugins even in the absence of an official language-specific library.

PluginRPC currently has one official language library:

Go is a natural language to write plugins in, and we have a direct use case for an RPC library in Gofor our custom lint and breaking change plugins inbuf. However,PluginRPC is purposefully designed to be simple to implement in any language. If there is sufficientdemand, we may provide official implementations for other languages in the future.

If using Protobuf to write plugins, there's traditionally been two mechanisms:

  1. Have a single request message type sent over stdin, and return a single response message typeover stdout. This is howprotocoperates, for example, taking in aCodeGeneratorRequest and sending back aCodeGeneratorResponse over stdout. This is very simple, however it makes doing anything elseextremely difficult. All plugin API evolution needs to remain within these single messages forall time, and providing functionality for multiple methods is awkward at best (for example, viause ofoneofs). Multiple content types cannot be supported.
  2. Bring a full-powered network RPC framework into the mix. This is howgo-plugin operates, for example, making a plugin exposea gRPC service, and then doing an exec/kill dance to bring the plugin up temporarily and exposeit on a port, call the required method, and then kill the plugin entirely. While effective inallowing lots of flexibility, it's bringing in a very complicated framework to solve a simpleengineering problem, adding brittleness, requiring network calls, and not allowing plugins toremain idiomatic CLI tools

PluginRPC provides the best of both worlds: simple CLI constructs with all the power you require. Ifyou want to use Protobuf services across the network, useConnectRPC. Ifyou want to use Protobuf services to write plugins, use PluginRPC.

Protocol

A plugin is implemented as an executable binary. Plugins may be implemented on sub-commands of thebinary. For example, given the binaryacme, a plugin author may choose to implement the pluginunder the sub-commandacme plug. PluginRPC frameworks will provide clients the ability to specifythis sub-command (inpluginrpc-go, this is done viaExecRunnerWithArgs).

We'll refer to the executable and subsequent base args as$PLUGIN below. In our example here,acme plug is what we refer to as$PLUGIN. We'll also assume that the plugin wants to implementthe following Protobuf service:

packageacme.foo.v1;serviceFooService {rpcBar(BarRequest)returns (BarResponse);rpcBaz(BazRequest)returns (BazResponse);}messageBarRequest {stringid=1;}messageBarResponse {stringbar=1;}messageBazRequest {}messageBazResponse {stringbaz=1;}

All plugins must respond to three flags:

  • $PLUGIN --protocol. This must print the PluginRPC protocol version to stdout with any number ofsubsequent newlines and exit with code0. The only protocol version right now is1, so pluginsmust print1 to stdout (or1\n,1\n\n, etc).

Plugin callers can use--protocol to understand which PluginRPC protocol version the pluginsupports. In the future, if there are newer backwards-incompatible versions of the PluginRPCprotocol, these will be exposed as versions2,3, etc.

  • $PLUGIN --spec. This must print a serializedpluginrpc.v1.Specto stdout and exit with code0.

  • $PLUGIN --format. This controls the serialization format of requests, responses, errors, and theresult of the--spec flag. The current valid values are--format binary and--format json.All plugins must respond to--format binary and--format json.

Here's an example response to--spec --format json on stdout:

{"procedures": [    {"path":"/acme.foo.v1.FooService/Bar","args": ["bar"]    },    {"path":"/acme.foo.v1.FooService/Baz","args": ["baz"]    }  ]}

This specifies that:

  • TheBar RPC is invoked by calling$PLUGIN bar.
  • TheBaz RPC is invoked by calling$PLUGIN baz.

Theprocedure.args field is optional. Ifargs are not specified, a procedure can be invoked with$PLUGIN <path>. For example, ifargs were not specified forBaz, then$PLUGIN /acme.foo.v1.FooService/Baz would invoke theBaz RPC.

An RPC is invoked by sending a serializedpluginrpc.v1.Requestto stdin.

Plugins must support nothing being written to stdin, which will be interpreted as a request with anempty value.

An RPC will respond on stdout a serializedpluginrpc.v1.Response.

The plugin will exit with code0 unless there is a system error.

A response value may be present even if there is apluginrpc.v1.Erroron theResponse.

If a plugin exits with any code other than0, this is considered a system error, and stdout isundefined and will not be processed.

A plugin may always write to stderr as it wishes.

Status: Beta

This framework is in active development, and should not be considered stable.

Legal

Offered under theApache 2 license


[8]ページ先頭

©2009-2025 Movatter.jp