You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
boundary/sdk/plugins/host/load.go

87 lines
2.3 KiB

package external_host_plugins
import (
"context"
"fmt"
"io/fs"
"strings"
pb "github.com/hashicorp/boundary/sdk/pbs/plugin"
"github.com/hashicorp/go-plugin"
"github.com/hashicorp/go-secure-stdlib/pluginutil/v2"
)
// NOTE: This package could probably use some reflect based bits to allow
// loading other types of plugins later. That is an exercise left for future
// refactoring, but worth calling out now.
type pluginInfo struct {
containerFs fs.FS
filename string
creationFunc func() (pb.HostPluginServiceClient, error)
}
// CreateHostPlugin takes in a type, parses the various options to look for a
// plugin matching that name, and returns a host plugin client, a cleanup
// function to execute on shutdown of the enclosing program, and an error.
func CreateHostPlugin(
ctx context.Context,
pluginType string,
opt ...Option,
) (
hp pb.HostPluginServiceClient,
cleanup func() error,
retErr error,
) {
defer func() {
if retErr != nil && cleanup != nil {
_ = cleanup()
}
}()
pluginType = strings.ToLower(pluginType)
opts, err := getOpts(opt...)
if err != nil {
return nil, nil, fmt.Errorf("error parsing host plugin options: %w", err)
}
// First, scan available plugins, then find the right one to use
pluginMap, err := pluginutil.BuildPluginMap(
append(
opts.withPluginOptions,
pluginutil.WithPluginClientCreationFunc(
func(pluginPath string, _ ...pluginutil.Option) (*plugin.Client, error) {
return NewHostPluginClient(pluginPath, WithLogger(opts.withLogger))
}),
)...)
if err != nil {
return nil, nil, fmt.Errorf("error building plugin map: %w", err)
}
// Create the plugin and cleanup func
plugClient, cleanup, err := pluginutil.CreatePlugin(pluginMap[pluginType])
if err != nil {
return nil, cleanup, err
}
var raw interface{}
switch client := plugClient.(type) {
case plugin.ClientProtocol:
raw, err = client.Dispense(hostServicePluginSetName)
if err != nil {
return nil, cleanup, fmt.Errorf("error dispensing host plugin: %w", err)
}
default:
return nil, cleanup, fmt.Errorf("unable to understand type %T of raw plugin", raw)
}
var ok bool
hp, ok = raw.(pb.HostPluginServiceClient)
if !ok {
return nil, cleanup, fmt.Errorf("error converting rpc host plugin of type %T to normal wrapper", raw)
}
return hp, cleanup, nil
}