Documentation
¶
Overview ¶
Package plugin provides a client for invoking extractor plugins.
Deputy supports three types of inventory extractors:
- OSV-SCALIBR extractors (built-in)
- Deputy custom extractors (built-in, Go)
- Plugin extractors (external, any language via pluginrpc)
This package handles type 3 - invoking external plugins that implement the ExtractorService defined in api/deputy/plugin/v1/extractor.proto.
Architecture ¶
┌────────────────────────────────────────────────────────────────┐
│ Deputy (this package) │
│ │
│ ┌─────────────┐ ┌──────────────────┐ ┌────────────────┐ │
│ │ NewClient() │──▶│ pluginrpc.Client │──▶│ ExecRunner │ │
│ └─────────────┘ └──────────────────┘ │ (subprocess) │ │
│ └───────┬────────┘ │
│ ┌─────────────────────────────────────────────────│────────┐ │
│ │ Client Methods │ │ │
│ │ • Info() - get metadata │ │ │
│ │ • FileRequired() - check if file matches ─────┤ │ │
│ │ • Extract() - extract packages ─────┤ │ │
│ └─────────────────────────────────────────────────│────────┘ │
└────────────────────────────────────────────────────│──────────┘
│
┌──────────────┴──────────┐
│ stdin │ stdout │
│ (proto) │ (proto) │
▼ │ │
┌─────────────────────────────────────│────────────│────────────┐
│ Plugin Process │ │ │
│ │ │ │
│ ┌──────────────────────────────────┴────────────┴─────────┐ │
│ │ pluginrpc.Server │ │
│ │ • --protocol flag handling │ │
│ │ • --spec flag handling │ │
│ │ • Subcommand routing (info, file-required, extract) │ │
│ └──────────────────────────┬──────────────────────────────┘ │
│ │ │
│ ┌──────────────────────────▼──────────────────────────────┐ │
│ │ ExtractorService Handler │ │
│ │ (implemented via sdk/plugin or custom) │ │
│ └─────────────────────────────────────────────────────────┘ │
└────────────────────────────────────────────────────────────────┘
Plugin Discovery ¶
Plugins are discovered via:
- Configuration: .deputy.yaml plugins.extractors[]
- PATH lookup: executables matching "deputy-extractor-*"
- Runtime registration: client.RegisterExtractor()
Invocation Protocol ¶
Plugins are invoked as subprocesses using pluginrpc:
- Requests are serialized to stdin
- Responses come from stdout
- Trace context is passed via the TraceContext field
- Errors are returned with gRPC-style codes
Trace Context Propagation ¶
┌─────────────────────────────────────────────────────────────┐
│ Deputy Process │
│ │
│ ctx with span ──▶ injectTraceContext() ──▶ "00-abc-def-01" │
│ │ │
└────────────────────────────────────────────────────│────────┘
│
TraceContext field
in proto request
│
┌────────────────────────────────────────────────────│────────┐
│ Plugin Process │ │
│ ▼ │
│ extractTraceContext() ──▶ ctx with linked span │
│ │
└─────────────────────────────────────────────────────────────┘
Example Usage ¶
client, err := plugin.NewClient("deputy-extractor-gemspec")
info, _ := client.Info(ctx)
required, _ := client.FileRequired(ctx, "Gemfile.lock", false, 0644, 1234)
if required {
packages, _ := client.Extract(ctx, "Gemfile.lock", contents, "/project")
}
Index ¶
- Constants
- func Discover() ([]string, error)
- type Client
- func (c *Client) Extract(ctx context.Context, path string, contents []byte, root string) ([]*pluginv1.ExtractResponse, error)
- func (c *Client) ExtractPackages(ctx context.Context, path string, contents []byte, root string) ([]*Package, error)
- func (c *Client) ExtractorInfo() *pluginv1.ExtractorInfo
- func (c *Client) FileRequired(ctx context.Context, path string, isDir bool, mode uint32, size int64) (bool, error)
- func (c *Client) Info(ctx context.Context) (*pluginv1.ExtractorInfo, error)
- func (c *Client) ProgramName() string
- type ClientOption
- type Package
Constants ¶
const (
// TracerName is the tracer name for plugin client spans.
TracerName = "github.com/picatz/deputy/internal/inventory/plugin"
)
Variables ¶
This section is empty.
Functions ¶
Types ¶
type Client ¶
type Client struct {
// contains filtered or unexported fields
}
Client wraps a pluginrpc client for the ExtractorService.
func NewClient ¶
NewClient creates a new plugin client for the given program name. The program must be in PATH or an absolute path.
The client automatically calls Info() to get extractor metadata.
func (*Client) Extract ¶
func (c *Client) Extract(ctx context.Context, path string, contents []byte, root string) ([]*pluginv1.ExtractResponse, error)
Extract calls the plugin's Extract RPC.
func (*Client) ExtractPackages ¶
func (c *Client) ExtractPackages(ctx context.Context, path string, contents []byte, root string) ([]*Package, error)
ExtractPackages is a convenience method that returns just the packages.
func (*Client) ExtractorInfo ¶
func (c *Client) ExtractorInfo() *pluginv1.ExtractorInfo
ExtractorInfo returns the cached extractor metadata.
func (*Client) FileRequired ¶
func (c *Client) FileRequired(ctx context.Context, path string, isDir bool, mode uint32, size int64) (bool, error)
FileRequired calls the plugin's FileRequired RPC.
func (*Client) ProgramName ¶
ProgramName returns the plugin program name.
type ClientOption ¶
type ClientOption func(*clientOptions)
ClientOption configures client behavior.
func WithArgs ¶
func WithArgs(args ...string) ClientOption
WithArgs sets additional arguments to pass to the plugin.
func WithStderr ¶
func WithStderr(w io.Writer) ClientOption
WithStderr sets the writer for plugin stderr output. Useful for debugging plugins.
type Package ¶
type Package = dependencyv1.Package
Package is an alias for the dependency Package type.