Documentation
¶
Overview ¶
Package grpc provides gRPC-based plugin runtime using HashiCorp go-plugin.
This enables native Go plugins to run as separate processes, communicating with the host via gRPC. Useful for I/O-heavy plugins that benefit from native performance and direct system access.
Shared types (handshake, RPC structs, ServePlugin) live in pkg/plugin/grpcutil so external plugins can import them. This package adds the host-side loading, HostAPI bridging, and bidirectional calls.
Index ¶
- Variables
- func GenerateComposeFragment(pluginName string, sidecars []plugin.SidecarSpec) string
- func GeneratePodManifest(spec K8sPodSpec) string
- type CallRequest
- type CallResponse
- type GKPluginInterface
- type GKPluginPlugin
- type GKPluginPluginHost
- type GKPluginRPCClient
- type GKPluginRPCClientHost
- type GKPluginRPCServer
- type GRPCPlugin
- func (p *GRPCPlugin) Call(ctx context.Context, fn string, args json.RawMessage) (json.RawMessage, error)
- func (p *GRPCPlugin) GKRegister() plugin.GKRegistration
- func (p *GRPCPlugin) Init(ctx context.Context, host plugin.HostAPI) error
- func (p *GRPCPlugin) SetCallTimeout(d time.Duration)
- func (p *GRPCPlugin) Shutdown(ctx context.Context) error
- type HostAPIRPCServer
- type HostAPIRequest
- type HostAPIResponse
- type InitRequest
- type IsolationMode
- type K8sPodSpec
Constants ¶
This section is empty.
Variables ¶
var Handshake = grpcutil.Handshake
Handshake re-exports the shared handshake config.
var ServePlugin = grpcutil.ServePlugin
ServePlugin re-exports the public ServePlugin for internal use.
Functions ¶
func GenerateComposeFragment ¶
func GenerateComposeFragment(pluginName string, sidecars []plugin.SidecarSpec) string
GenerateComposeFragment returns a Docker Compose service fragment for plugin sidecars. This can be merged into the project's docker-compose.override.yml.
func GeneratePodManifest ¶
func GeneratePodManifest(spec K8sPodSpec) string
GeneratePodManifest returns a Kubernetes pod YAML for a plugin. If the plugin declares sidecars, they are injected into the same pod so they share the pod network (sidecars reach each other via localhost).
Types ¶
type CallRequest ¶
type CallRequest = grpcutil.CallRequest
type CallResponse ¶
type CallResponse = grpcutil.CallResponse
type GKPluginInterface ¶
type GKPluginInterface = grpcutil.GKPluginInterface
Re-export shared types so existing internal callers don't break.
type GKPluginPlugin ¶
type GKPluginPlugin = grpcutil.GKPluginPlugin
type GKPluginPluginHost ¶
type GKPluginPluginHost struct {
goplugin.Plugin
PluginName string // Plugin name for caller authentication
// contains filtered or unexported fields
}
GKPluginPluginHost is the host-side go-plugin.Plugin implementation. It extends the base plugin with HostAPI bidirectional call support.
type GKPluginRPCClient ¶
type GKPluginRPCClient = grpcutil.GKPluginRPCClient
type GKPluginRPCClientHost ¶
type GKPluginRPCClientHost struct {
// contains filtered or unexported fields
}
GKPluginRPCClientHost is the host-side RPC client with HostAPI bridging.
func (*GKPluginRPCClientHost) GKRegister ¶
func (c *GKPluginRPCClientHost) GKRegister() (*plugin.GKRegistration, error)
func (*GKPluginRPCClientHost) Init ¶
func (c *GKPluginRPCClientHost) Init(config map[string]string) error
func (*GKPluginRPCClientHost) Shutdown ¶
func (c *GKPluginRPCClientHost) Shutdown() error
type GKPluginRPCServer ¶
type GKPluginRPCServer = grpcutil.GKPluginRPCServer
type GRPCPlugin ¶
type GRPCPlugin struct {
// contains filtered or unexported fields
}
GRPCPlugin wraps a go-plugin client to implement plugin.Plugin.
func LoadGRPCPlugin ¶
func LoadGRPCPlugin(execPath, pluginName string, policy plugin.ResourcePolicy) (*GRPCPlugin, error)
LoadGRPCPlugin loads a gRPC plugin from an executable path with OS-level sandboxing. The plugin's host callbacks are refused until Init binds the host the Manager gives the plugin (its SandboxedHostAPI).
func (*GRPCPlugin) Call ¶
func (p *GRPCPlugin) Call(ctx context.Context, fn string, args json.RawMessage) (json.RawMessage, error)
Call implements plugin.Plugin. ctx stays registered under the call's token until Call returns, so the plugin's callbacks that carry the token run with it (acting user, language, call depth, deadline).
func (*GRPCPlugin) GKRegister ¶
func (p *GRPCPlugin) GKRegister() plugin.GKRegistration
GKRegister implements plugin.Plugin.
func (*GRPCPlugin) Init ¶
Init implements plugin.Plugin. host is the plugin's SandboxedHostAPI: from here on every host callback from the plugin process goes through it.
func (*GRPCPlugin) SetCallTimeout ¶
func (p *GRPCPlugin) SetCallTimeout(d time.Duration)
SetCallTimeout sets the per-call timeout for this plugin.
func (*GRPCPlugin) Shutdown ¶
func (p *GRPCPlugin) Shutdown(ctx context.Context) error
Shutdown implements plugin.Plugin.
Runs the plugin's Shutdown RPC with the caller's context deadline respected. The old implementation ignored ctx and blocked on the RPC indefinitely, so a plugin stuck mid-shutdown could wedge goatflow's whole process (ShutdownAll holds the manager lock serially across every plugin — one hang froze them all). Now we run the RPC in a goroutine and let the ctx deadline bail us out into Kill().
Kill() is always called at the end regardless of outcome: it's the hashicorp go-plugin supervisor's teardown path (SIGTERM → grace period → SIGKILL), and it's safe to call even if the plugin already exited cleanly via the Shutdown RPC. Treating it as unconditional cleanup avoids a class of leak where a half-responsive plugin returned OK from Shutdown but left the subprocess alive.
type HostAPIRPCServer ¶
type HostAPIRPCServer struct {
CallerName string // Authenticated plugin name (set by host, not trusted from plugin)
// contains filtered or unexported fields
}
HostAPIRPCServer exposes HostAPI to one plugin process via RPC. This runs on the host side and handles plugin callbacks.
func (*HostAPIRPCServer) Call ¶
func (s *HostAPIRPCServer) Call(req HostAPIRequest, resp *HostAPIResponse) error
Call handles all host API calls from the plugin.
type HostAPIRequest ¶
type HostAPIRequest struct {
Method string // Method name (e.g., "db_query", "cache_get")
Args json.RawMessage // JSON-encoded arguments
CallerPlugin string // Name the plugin claims; ignored, CallerName is used
CallToken string // Token of the host call this callback belongs to
}
HostAPIRequest is a generic host API request. Field names match grpcutil.HostAPIRPCRequest (net/rpc gob encoding matches by name).
type HostAPIResponse ¶
type HostAPIResponse struct {
Result json.RawMessage
Error string
}
HostAPIResponse is a generic host API response.
type InitRequest ¶
type InitRequest = grpcutil.InitRequest
type IsolationMode ¶
type IsolationMode string
IsolationMode determines how gRPC plugins are sandboxed.
const ( // IsolationLocal runs plugins as local processes with Linux namespace isolation. IsolationLocal IsolationMode = "local" // IsolationK8s runs plugins as Kubernetes pods. IsolationK8s IsolationMode = "k8s" )
func GetIsolationMode ¶
func GetIsolationMode() IsolationMode
GetIsolationMode returns the configured plugin isolation mode.
type K8sPodSpec ¶
type K8sPodSpec struct {
PluginName string
Image string // Container image for the plugin
Port int // gRPC port
MemoryMB int // Memory limit from ResourcePolicy
CPUMillis int // CPU limit (millicores)
Namespace string // K8s namespace (default: goatflow-plugins)
Sidecars []plugin.SidecarSpec // Sidecar containers declared in manifest
}
K8sPodSpec generates a Kubernetes pod spec for a gRPC plugin. This is used by the plugin loader when isolation mode is "k8s".