Documentation ¶
Overview ¶
Package pluginrpc implements an RPC framework for plugins.
Index ¶
- Constants
- Variables
- func Main(newServer func() (Server, error), _ ...MainOption)
- func NewProtoProcedure(procedure Procedure) *pluginrpcv1.Procedure
- func NewProtoSpec(spec Spec) *pluginrpcv1.Spec
- type CallOption
- type Client
- type ClientOption
- type Code
- type Env
- type Error
- type ExecRunnerOption
- type ExitError
- type Format
- type HandleEnv
- type HandleOption
- type Handler
- type HandlerOption
- type MainOption
- type Procedure
- type ProcedureOption
- type Runner
- type Server
- type ServerOption
- type ServerRegistrar
- type ServerRunnerOption
- type Spec
Constants ¶
const ( // ProtocolFlagName is the name of the protocol bool flag. ProtocolFlagName = "protocol" // SpecFlagName is the name of the spec bool flag. SpecFlagName = "spec" // FormatFlagName is the name of the format string flag. FormatFlagName = "format" )
const ( // Version is the semantic version of the pluginrpc module. Version = "0.5.0" // IsAtLeastVersion0_1_0 is used in compile-time handshake's with pluginrpc's generated code. IsAtLeastVersion0_1_0 = true // IsAtLeastVersion0_4_0 is used in compile-time handshake's with pluginrpc's generated code. IsAtLeastVersion0_4_0 = true )
Variables ¶
var ( // AllFormats are all Formsts. AllFormats = []Format{ FormatJSON, FormatBinary, } )
var OSEnv = Env{ Args: os.Args[1:], Stdin: os.Stdin, Stdout: os.Stdout, Stderr: os.Stderr, }
OSEnv is an Env using os.Args, os.Stdin, os.Stdout, and os.Stderr.
Functions ¶
func Main ¶
func Main(newServer func() (Server, error), _ ...MainOption)
Main is a convenience function that will run the server within a main function with the proper semantics.
All registration should already be complete before passing the Server to this function.
func main() { pluginrpc.Main(newServer) } func newServer() (pluginrpc.Server, error) { spec, err := examplev1pluginrpc.EchoServiceSpecBuilder{ EchoRequest: []pluginrpc.ProcedureOption{pluginrpc.ProcedureWithArgs("echo", "request")}, EchoError: []pluginrpc.ProcedureOption{pluginrpc.ProcedureWithArgs("echo", "error")}, }.Build() if err != nil { return nil, err } serverRegistrar := pluginrpc.NewServerRegistrar() echoServiceServer := examplev1pluginrpc.NewEchoServiceServer(pluginrpc.NewHandler(spec), echoServiceHandler{}) examplev1pluginrpc.RegisterEchoServiceServer(serverRegistrar, echoServiceServer) return pluginrpc.NewServer(spec, serverRegistrar) }
func NewProtoProcedure ¶
func NewProtoProcedure(procedure Procedure) *pluginrpcv1.Procedure
NewProtoProcedure returns a new pluginrpcv1.Procedure for the given Procedure.
func NewProtoSpec ¶
func NewProtoSpec(spec Spec) *pluginrpcv1.Spec
NewProtoSpec returns a new pluginrpcv1.Spec for the given Spec.
Types ¶
type CallOption ¶
type CallOption func(*callOptions)
CallOption is an option for an individual client call.
type Client ¶
type Client interface { // Spec returns the Spec that the client receives. // // Clients will cache retrieved protocols and Specs. If it is possible that a plugin will // change during the lifetime of a Client, it is the responsibility of the caller to // create a new Client. We may change this requirement in the future. Spec(ctx context.Context) (Spec, error) // Call calls the given Procedure. // // The request will be sent over stdin, with a response being sent on stdout. // The response given will then be populated. Call( ctx context.Context, procedurePath string, request any, response any, options ...CallOption, ) error // contains filtered or unexported methods }
Client is a client that calls plugins.
Typically, Clients are not directly invoked. Instead, the generated code for a given service will use a Client to call the Procedures that the service specifies.
func NewClient ¶
func NewClient(runner Runner, options ...ClientOption) Client
NewClient returns a new Client for the given Runner.
type ClientOption ¶
type ClientOption func(*clientOptions)
ClientOption is an option for a new Client.
func ClientWithFormat ¶
func ClientWithFormat(format Format) ClientOption
ClientWithFormat will result in the given Format being used for requests and responses.
The default is FormatBinary.
func ClientWithStderr ¶
func ClientWithStderr(stderr io.Writer) ClientOption
ClientWithStderr will result in the stderr of the plugin being propagated to the given writer.
The default is to drop stderr.
type Code ¶
type Code uint32
Code is an error code. There are no user-defined codes, so only the codes enumerated below are valid. In both name and semantics, these codes match the gRPC status codes.
const ( // CodeCanceled indicates that the operation was canceled, typically by the // caller. CodeCanceled Code = 1 // CodeUnknown indicates that the operation failed for an unknown reason. CodeUnknown Code = 2 // CodeInvalidArgument indicates that client supplied an invalid argument. CodeInvalidArgument Code = 3 // CodeDeadlineExceeded indicates that deadline expired before the operation // could complete. CodeDeadlineExceeded Code = 4 // CodeNotFound indicates that some requested entity (for example, a file or // directory) was not found. CodeNotFound Code = 5 // CodeAlreadyExists indicates that client attempted to create an entity (for // example, a file or directory) that already exists. CodeAlreadyExists Code = 6 // CodePermissionDenied indicates that the caller doesn't have permission to // execute the specified operation. CodePermissionDenied Code = 7 // CodeResourceExhausted indicates that some resource has been exhausted. For // example, a per-user quota may be exhausted or the entire file system may // be full. CodeResourceExhausted Code = 8 // CodeFailedPrecondition indicates that the system is not in a state // required for the operation's execution. CodeFailedPrecondition Code = 9 // CodeAborted indicates that operation was aborted by the system, usually // because of a concurrency issue such as a sequencer check failure or // transaction abort. CodeAborted Code = 10 // CodeOutOfRange indicates that the operation was attempted past the valid // range (for example, seeking past end-of-file). CodeOutOfRange Code = 11 // CodeUnimplemented indicates that the operation isn't implemented, // supported, or enabled in this service. CodeUnimplemented Code = 12 // CodeInternal indicates that some invariants expected by the underlying // system have been broken. This code is reserved for serious errors. CodeInternal Code = 13 // is usually temporary, so clients can back off and retry idempotent // operations. CodeUnavailable Code = 14 // CodeDataLoss indicates that the operation has resulted in unrecoverable // data loss or corruption. CodeDataLoss Code = 15 // CodeUnauthenticated indicates that the request does not have valid // authentication credentials for the operation. CodeUnauthenticated Code = 16 )
func CodeForProto ¶
func CodeForProto(protoCode pluginrpcv1.Code) (Code, error)
CodeForProto returns the Code for the pluginrpcv1.Code.
Returns error the pluginrpcv1.Code is not valid.
type Env ¶
Env specifies an environment used to invoke a plugin.
This abstracts away args, stdin, stdout, and stderr. Envs are used by Runners and Servers.
type Error ¶
type Error struct {
// contains filtered or unexported fields
}
Error is an error with a Code.
func NewError ¶
NewError returns a new Error.
Code and underlying with a non-empty message are required.
An Error will never have an invalid Code or nil underlying error when returned from this function.
func NewErrorForProto ¶
func NewErrorForProto(protoError *pluginrpcv1.Error) *Error
NewErrorForProto returns a new Error for the given pluginrpcv1.Error.
If protoError is nil, this returns nil.
func NewErrorf ¶
Code and a non-empty message are required.
An Error will never have an invalid Code or nil underlying error when returned from this function.
func WrapError ¶
WrapError wraps the given error as a Error.
If the given error is nil, this returns nil. If the given error is already a Error, this is returned. Otherwise, an error with code CodeUnknown is returned.
An Error will never have an invalid Code when returned from this function.
func (*Error) ToProto ¶
func (e *Error) ToProto() *pluginrpcv1.Error
ToProto converts the Error to a pluginrpcv1.Error.
If e is nil, this returns nil.
type ExecRunnerOption ¶
type ExecRunnerOption func(*execRunnerOptions)
ExecRunnerOption is an option for a new os/exec Runner.
func ExecRunnerWithArgs ¶
func ExecRunnerWithArgs(args ...string) ExecRunnerOption
ExecRunnerWithArgs returns a new ExecRunnerOption that specifies a sub-command to invoke on the program.
For example, if the plugin is implemented under the sub-command `foo bar` on the program `plug`, specifying ExecRunnerWithArgs("foo", "bar") will result in the command `plug foo bar` being invoked as the plugin. In this scenario, all procedures and flag will be implemented under this sub-command. In this example, `plug foo bar --plugin-spec` should produce the spec.
type ExitError ¶
type ExitError struct {
// contains filtered or unexported fields
}
ExitError is an process exit error with an exit code.
Runners return ExitErrors to indicate the exit code of the process.
func NewExitError ¶
NewExitError returns a new ExitError.
An ExitError will never have an exit code of 0 when returned from this function.
func WrapExitError ¶
WrapExitError wraps the given error as a *ExitError.
If the given error is nil, this returns nil. If the given error is already a *ExitError, this is returned.
An ExitError will never have a exit code of 0 when returned from this function.
type Format ¶
type Format uint32
Format is the serialization mechanism of the body of Requests, Responses and Specs.
func FormatForString ¶
FormatForString returns the Format for the given string.
Returns 0 if the Format is unknown or s is empty.
type HandleOption ¶
type HandleOption func(*handleOptions)
HandleOption is an option for handler.Handle.
func HandleWithFormat ¶
func HandleWithFormat(format Format) HandleOption
HandleWithFormat returns a new HandleOption that says to marshal and unmarshal requests, responses, and errors in the given format.
The default is FormatBinary.
type Handler ¶
type Handler interface { Handle( ctx context.Context, handleEnv HandleEnv, request any, handle func(context.Context, any) (any, error), options ...HandleOption, ) error // contains filtered or unexported methods }
Handler handles requests on the server side.
This is used within generated code when registering an implementation of a service.
Currently, Handlers do not have any customization, however this type is exposes so that customization can be provided in the future.
func NewHandler ¶
func NewHandler(spec Spec, _ ...HandlerOption) Handler
NewHandler returns a new Handler.
type HandlerOption ¶
type HandlerOption func(*handlerOptions)
HandlerOption is an option for a new Handler.
type Procedure ¶
type Procedure interface { // Path returns the path of the Procedure. // // Paths are always valid URIs. Path() string // Args returns optional custom args which can be used to invoke the Procedure. // // If there are no args, the Procedure can be invoked with the single arg equal to the path. // Arg values may only use the characters [a-zA-Z0-9-_], and never start or end with a dash // or underscore. Args() []string // contains filtered or unexported methods }
Procedure defines a single procedure that a plugin exposes.
func NewProcedure ¶
func NewProcedure(path string, options ...ProcedureOption) (Procedure, error)
NewProcedure returns a new validated Procedure for the given path.
func NewProcedureForProto ¶
func NewProcedureForProto(protoProcedure *pluginrpcv1.Procedure) (Procedure, error)
NewProcedureForProto returns a new validated Procedure for the given pluginrpcv1.Procedure.
type ProcedureOption ¶
type ProcedureOption func(*procedureOptions)
ProcedureOption is an option for a new Procedure.
func ProcedureWithArgs ¶
func ProcedureWithArgs(args ...string) ProcedureOption
ProcedureWithArgs specifies optional custom args which can be used to invoke the Procedure.
If there are no args, the Procedure can be invoked with the single arg equal to the path. Arg values may only use the characters [a-zA-Z0-9-_], and never start with a dash or underscore.
type Runner ¶
type Runner interface { // Run runs the external command with the given environment. // // The environment variables are always cleared before running the command. // If no stdin, stdout, or stderr are provided, the equivalent of /dev/null are given to the command. // The command is run in the context of the current working directory. // // If there is an exit error, it is returned as a *ExitError. Run(ctx context.Context, env Env) error }
Runner runs external commands.
Runners should not proxy any environment variables to the commands they run.
func NewExecRunner ¶
func NewExecRunner(programName string, options ...ExecRunnerOption) Runner
NewExecRunner returns a new Runner that uses os/exec to call the given external command given by the program name.
func NewServerRunner ¶
func NewServerRunner(server Server, _ ...ServerRunnerOption) Runner
NewServerRunner returns a new Runner that directly calls the server.
This is primarily used for testing.
type Server ¶
type Server interface { // Serve serves the plugin. Serve(ctx context.Context, env Env) error // contains filtered or unexported methods }
Server is the server for plugin implementations.
The easiest way to run a server for a plugin is to call ServerMain.
func NewServer ¶
func NewServer(spec Spec, serverRegistrar ServerRegistrar, options ...ServerOption) (Server, error)
NewServer returns a new Server for a given Spec and ServerRegistrar.
The Spec will be validated against the ServerRegistar to make sure there is a 1-1 mapping between Procedures and registered paths.
Once passed to this constructor, the ServerRegistrar can no longer have new paths registered to it.
type ServerOption ¶
type ServerOption func(*serverOptions)
ServerOption is an option for a new Server.
func ServerWithDoc ¶ added in v0.5.0
func ServerWithDoc(doc string) ServerOption
ServerWithDoc will attach the given documentation to the server.
This will add ths given docs as a prefix when the flag -h/--help is used.
type ServerRegistrar ¶
type ServerRegistrar interface { // Register registers the given handle function for the given path. // // Paths must be unique. Register(path string, handleFunc func(context.Context, HandleEnv, ...HandleOption) error) // contains filtered or unexported methods }
ServerRegistrar is used to registered paths when constructing a server.
By splitting out registration from the Server interface, we allow the Server to be immutable.
Generally, ServerRegistrars are called by `Register.*Server` functions from generated code.
func NewServerRegistrar ¶
func NewServerRegistrar() ServerRegistrar
NewServerRegistrar returns a new ServerRegistrar.
type ServerRunnerOption ¶
type ServerRunnerOption func(*serverRunnerOptions)
ServerRunnerOption is an option for a new ServerRunner.
type Spec ¶
type Spec interface { // ProcedureForPath returns the Procedure for the given path. // // If no such procedure exists, this returns nil. ProcedureForPath(path string) Procedure // Procedures returns all Procedures. Procedures() []Procedure // contains filtered or unexported methods }
Spec specifies a set of Procedures that a plugin implements. This describes the shape of the plugin to clients.
Specs are returned on stdout when `--spec` is called.
A given Spec will have no duplicate Procedures either by path or args.
func MergeSpecs ¶ added in v0.4.0
MergeSpecs merges the given Specs.
Returns error if any Procedures overlap by Path or Args.
func NewSpecForProto ¶
func NewSpecForProto(protoSpec *pluginrpcv1.Spec) (Spec, error)
NewSpecForProto returns a new validated Spec for the given pluginrpcv1.Spec.
Source Files ¶
Directories ¶
Path | Synopsis |
---|---|
cmd
|
|
internal
|
|
example/cmd/echo-error-client
Package main implements a client that calls the EchoError RPC on the echo-plugin plugin.
|
Package main implements a client that calls the EchoError RPC on the echo-plugin plugin. |
example/cmd/echo-list-client
Package main implements a client that calls the EchoList RPC on the echo-plugin plugin.
|
Package main implements a client that calls the EchoList RPC on the echo-plugin plugin. |
example/cmd/echo-plugin
Package main implements an example plugin.
|
Package main implements an example plugin. |
example/cmd/echo-request-client
Package main implements a client that calls the EchoRequest RPC on the echo-plugin plugin.
|
Package main implements a client that calls the EchoRequest RPC on the echo-plugin plugin. |