rpcplugin

package module
v0.3.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Mar 3, 2024 License: MPL-2.0 Imports: 33 Imported by: 5

Documentation

Overview

Package rpcplugin is an implementation of the "rpcplugin" mechanism for Go, allowing both plugin clients and plugin servers to be implemented in Go.

Index

Constants

This section is empty.

Variables

View Source
var ForceServerWithoutTLS = func() (*tls.Config, error) {
	return nil, errForceNoTLS
}

ForceServerWithoutTLS is a predefined function for use with ServerConfig.TLSConfig which makes a server not use TLS at all. This makes the server non-compliant with the rpcplugin specification, but can be useful for debugging or for implementing servers for HashiCorp's go-plugin library when the client is not configured to use TLS. (That go-plugin mode isn't included in the rpcplugin specification.)

View Source
var NotChildProcessError error

NotChildProcessError is the error value returned from Serve if it does not detect the "cookie" environment variable that is a heuristic for detecting whether or not the server is being launched from the expected parent process.

Use this to detect that error case and potentially show a more application-specific error message, e.g. explaining how to install a plugin for that application.

Functions

func Serve

func Serve(ctx context.Context, config *ServerConfig) error

Serve starts up a plugin server and blocks while serving requests. It returns an error if initialization failed or if the given context becomes "done". It returns nil once all in-flight requests are complete if the client asks the server to exit.

Usually an application with rpcplugin-based plugins will have its own SDK library that provides a higher-level Serve function which takes some application-specific arguments. That allows the SDK to handle application-specific decisions about how the plugin RPC channel is configured, so that individual plugin implementers don't need to worry about it.

Serve assumes ownership of the standard I/O handles and consumes several environment variables in order to implement the client/server negotiation protocol. If you need to override its use of the real process environment for testing purposes, use package github.com/apparentlymart/go-envctx/envctx to override the environment variable values via the context.

Serve will also, by default, install a handler for the Interrupt signal (SIGINT on Unix-style systems) and ignore it, under the expectation that the plugin client process will handle interruptions and signal the plugins to shutdown via a different channel. This behavior can be overridden in ServerOpts if you need different signal-handling behavior.

Types

type ClientConfig

type ClientConfig struct {
	// Handshake configures the handshake settings that must agree with those
	// configured in the server.
	Handshake HandshakeConfig

	// ProtoVersions gives a Client implementation for each major protocol
	// version. The server will select the greatest version number that the
	// client and the server have in common, and then report its choice
	// as part of the handshake.
	ProtoVersions map[int]ClientVersion

	// Cmd is a not-yet-started exec.Cmd that is configured to launch a
	// specific plugin server executable. The given object must not be
	// used by the caller after it's been passed as part of a ClientConfig,
	// and will be modified in undefined ways by the rpcplugin package.
	Cmd *exec.Cmd

	// TLSConfig is used to set an explicit TLS configuration on the RPC client.
	// If this is nil, the client and server will negotiate temporary mutual
	// TLS automatically as part of their handshake.
	TLSConfig *tls.Config

	// StartTimeout is a time limit on how long the plugin is allowed to wait
	// before signalling that it is ready.
	//
	// If this is given as zero, it will default to one minute.
	StartTimeout time.Duration

	// Stderr, if non-nil, will recieve any data written by the child process
	// to its stderr stream.
	//
	// If Stderr is nil, any data written to the child's stderr is discarded.
	//
	// Stdout is not available because it's used exclusively by the plugin
	// handshake protocol.
	Stderr io.Writer
}

ClientConfig is used to configure the behavior of a plugin client.

type ClientVersion

type ClientVersion interface {
	// ClientProxy instantiates an instance of the plugin service's client
	// struct bound to the given connection, and returns that client proxy
	// object ready to use.
	//
	// There must be a single specific interface type that all returned client
	// proxies implement, so that the caller can know what to type-assert the
	// returned empty interface value to in order to get a useful client object.
	ClientProxy(ctx context.Context, conn *grpc.ClientConn) (interface{}, error)
}

ClientVersion is the interface to implement to launch a client for a particular protocol version. The client is the calling program that hosts one or more plugins.

type ClientVersionFunc

type ClientVersionFunc func(ctx context.Context, conn *grpc.ClientConn) (interface{}, error)

ClientVersionFunc is a function type that implements interface ClientVersion.

func (ClientVersionFunc) ClientProxy

func (fn ClientVersionFunc) ClientProxy(ctx context.Context, conn *grpc.ClientConn) (interface{}, error)

ClientProxy implements interface ClientVersion.

type HandshakeConfig

type HandshakeConfig struct {
	// CookieKey and CookieValue are used together to return an error if
	// a server program is run directly from the command line, rather than as
	// a child process of a plugin client.
	//
	// CookieKey is used as an environment variable name and CookieValue as
	// its value. The client sets this variable when it launches plugin server
	// child processes, and the server programs check for the variable and
	// corresponding value and will return an error immediately in case of
	// a mismatch.
	//
	// CookieKey will usually be something users can identify as being related
	// to the calling application. CookieValue should be something unlikely to
	// be set manually for some other reason, such as a specific (hard-coded)
	// uuid.
	//
	// This is not a security feature. It is just a heuristic to allow plugin
	// server programs to give good user feedback if a user tries to launch
	// them directly, rather than showing the user the plugin handshake line.
	CookieKey, CookieValue string
}

HandshakeConfig contains settings that the client and server must both agree on in order for a plugin connection to be established.

type Plugin

type Plugin struct {
	// contains filtered or unexported fields
}

Plugin represents a currently-active plugin instance, with an associated child process that is running an RPC server.

func New

func New(ctx context.Context, config *ClientConfig) (plugin *Plugin, err error)

New launches a plugin server in a child process and returns an object representing that ret.

Once a ClientConfig has been passed to this function, the caller must no longer access it or modify it.

If this function returns without error, the caller must retain the plugin object in order to eventually call Close on it, which will shut down the child process.

The child process inherits the environment variables of the current process. To customize the child process environment for testing, use package package github.com/apparentlymart/go-envctx/envctx to set a different environment on the given context.

func (*Plugin) Client

func (p *Plugin) Client(ctx context.Context) (protoVersion int, client interface{}, err error)

Client returns a client object that can be used to call plugin functions.

The protoVersion return value is the protocol version negotiated with the plugin server. The client return value must be type-asserted by the caller to the appropriate GRPC client interface type for the negotiated protocol version.

func (*Plugin) Close

func (p *Plugin) Close() error

Close terminates the plugin child process.

After this function returns, the recieving plugin object is no longer valid and calling any methods on it will lead to undefined behavior, possibly including panics.

type ServerConfig

type ServerConfig struct {
	// Handshake configures the handshake settings that must agree with those
	// configured in the client.
	Handshake HandshakeConfig

	// ProtoVersions gives a Server implementation for each major protocol
	// version. The server will select the greatest version number that the
	// client and the server have in common, and then call that version's
	// Server implementation to activate it.
	ProtoVersions map[int]ServerVersion

	// TLSConfig can be assigned a custom function for preparing the TLS
	// configuration used to authenticate and encrypt the RPC channel. If
	// no function is assigned, the ad-hoc TLS negotation protocol is used
	// to automatically establish a single-use key and certificate for each
	// plugin process.
	TLSConfig func() (*tls.Config, error)

	// Set NoSignalHandlers to prevent Serve from configuring the handling
	// of signals for the process. If you do this, you must find some other
	// way to prevent an interrupt signal to the client process group from also
	// being recieved by the plugin server processes.
	NoSignalHandlers bool
}

ServerConfig is used to configure the behavior of a plugin server started by the Serve function.

type ServerVersion

type ServerVersion interface {
	RegisterServer(*grpc.Server) error
}

ServerVersion is the interface to implement to write a server for a particular plugin version.

type ServerVersionFunc

type ServerVersionFunc func(*grpc.Server) error

ServerVersionFunc is a function type that implements interface ServerVersion

func (ServerVersionFunc) RegisterServer

func (fn ServerVersionFunc) RegisterServer(srv *grpc.Server) error

RegisterServer implements ServerVersion.

Directories

Path Synopsis
example
internal
Package plugintrace provides mechanisms to trace events in rpcplugin clients and servers, so that calling applications can record those events in their own application-specific logs or other trace mechanisms.
Package plugintrace provides mechanisms to trace events in rpcplugin clients and servers, so that calling applications can record those events in their own application-specific logs or other trace mechanisms.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL