Update runner to load plugins via plugin manager

This commit is contained in:
Chris Roberts 2021-07-26 14:16:50 -07:00 committed by Paul Hinze
parent e10cd26407
commit 4c8dc9a01c
No known key found for this signature in database
GPG Key ID: B69DEDF2D55501C0
2 changed files with 74 additions and 178 deletions

View File

@ -5,19 +5,15 @@ import (
"fmt"
"path/filepath"
"github.com/hashicorp/go-argmapper"
"github.com/hashicorp/go-hclog"
"github.com/hashicorp/go-multierror"
"google.golang.org/grpc/codes"
"google.golang.org/grpc/status"
"github.com/hashicorp/vagrant-plugin-sdk/component"
"github.com/hashicorp/vagrant-plugin-sdk/internal-shared/dynamic"
"github.com/hashicorp/vagrant-plugin-sdk/proto/vagrant_plugin_sdk"
"github.com/hashicorp/vagrant-plugin-sdk/terminal"
configpkg "github.com/hashicorp/vagrant/internal/config"
"github.com/hashicorp/vagrant/internal/core"
"github.com/hashicorp/vagrant/internal/factory"
"github.com/hashicorp/vagrant/internal/plugin"
"github.com/hashicorp/vagrant/internal/server/proto/vagrant_server"
)
@ -30,40 +26,60 @@ func (r *Runner) LoadPlugins(cfg *configpkg.Config) error {
}
for _, p := range plugins {
r.logger.Info("loading ruby plugin", "name", p.Name, "type", p.Type)
cfg.TrackRubyPlugin(p.Name, []interface{}{p.Type})
r.logger.Info("loading ruby plugin",
"name", p.Name,
"type", p.Type)
err = r.plugins.Register(
plugin.RubyFactory(r.vagrantRubyRuntime, p.Name, component.Type(p.Type)))
if err != nil {
return err
}
}
// Now lets load builtin plugins
for name, options := range plugin.Builtins {
r.logger.Info("loading builtin plugin " + name)
f := plugin.BuiltinFactory(name, component.PluginInfoType)
bp, err := dynamic.CallFunc(f, (**plugin.Instance)(nil), []*argmapper.Func{},
argmapper.Typed(r.logger))
for name, _ := range plugin.Builtins {
r.logger.Info("loading builtin plugin",
"name", name)
err = r.plugins.Register(
plugin.BuiltinFactory(name))
if err != nil {
panic(err)
return err
}
defer bp.(*plugin.Instance).Close()
p, ok := bp.(*plugin.Instance).Component.(component.PluginInfo)
if !ok {
panic("failed to convert instance to plugin info component")
}
typs := p.ComponentTypes()
r.logger.Info("valid component types for builtin plugin", "name", name, "types", typs)
cmps := []interface{}{}
for _, t := range typs {
cmps = append(cmps, t)
}
if plugin.IN_PROCESS_PLUGINS {
if err := r.builtinPlugins.Add(name, options...); err != nil {
return err
}
}
cfg.TrackBuiltinPlugin(name, cmps)
}
// NOTE: basis/project plugins loaded in core
// for name, options := range plugin.Builtins {
// r.logger.Info("loading builtin plugin " + name)
// f := plugin.BuiltinFactory(name, component.PluginInfoType)
// bp, err := dynamic.CallFunc(f, (**plugin.Instance)(nil), []*argmapper.Func{},
// argmapper.Typed(r.logger))
// if err != nil {
// panic(err)
// }
// defer bp.(*plugin.Instance).Close()
// p, ok := bp.(*plugin.Instance).Component.(component.PluginInfo)
// if !ok {
// panic("failed to convert instance to plugin info component")
// }
// typs := p.ComponentTypes()
// r.logger.Info("valid component types for builtin plugin", "name", name, "types", typs)
// cmps := []interface{}{}
// for _, t := range typs {
// cmps = append(cmps, t)
// }
// if plugin.IN_PROCESS_PLUGINS {
// if err := r.builtinPlugins.Add(name, options...); err != nil {
// return err
// }
// }
// cfg.TrackBuiltinPlugin(name, cmps)
// }
// TODO(spox): fix this loading
// if err == nil {
// cfg.TrackPlugin("custom-host", []interface{}{component.HostType})
@ -120,7 +136,7 @@ func (r *Runner) executeJob(
opts := []core.BasisOption{
core.WithLogger(log),
core.WithUI(ui),
core.WithComponents(r.factories),
core.WithPluginManager(r.plugins),
core.WithClient(r.client),
core.WithJobInfo(jobInfo),
}
@ -206,112 +222,3 @@ func (r *Runner) executeJob(
return nil, status.Errorf(codes.Aborted, "unknown operation %T", job.Operation)
}
}
func (r *Runner) pluginFactories(
log hclog.Logger,
plugins []*configpkg.Plugin,
wd string,
) (map[component.Type]*factory.Factory, error) {
// Copy all our base factories first
result := map[component.Type]*factory.Factory{}
for k, f := range r.factories {
result[k] = f.Copy()
}
// Get our plugin search paths
pluginPaths, err := plugin.DefaultPaths(wd)
if err != nil {
return nil, err
}
log.Debug("plugin search path", "path", pluginPaths)
// Search for all of our plugins
var perr error
for _, pluginCfg := range plugins {
plog := log.With("plugin_name", pluginCfg.Name)
// If this is a ruby plugin, register it using the ruby factory
if pluginCfg.Type.Ruby {
for _, t := range pluginCfg.Types() {
plog.Debug("registering ruby plugin", "name", pluginCfg.Name, "type", t)
result[t].Register(
pluginCfg.Name,
plugin.BuiltinRubyFactory(
r.vagrantRubyRuntime,
pluginCfg.Name,
t,
),
)
}
continue
}
// If this a builtin plugin, register it using the builtin factory
if pluginCfg.Type.Builtin {
for _, t := range pluginCfg.Types() {
plog.Debug("registering builtin plugin", "name", pluginCfg.Name, "type", t)
if plugin.IN_PROCESS_PLUGINS {
result[t].Register(
pluginCfg.Name,
r.builtinPlugins.Factory(
pluginCfg.Name,
t,
),
)
} else {
result[t].Register(
pluginCfg.Name,
plugin.BuiltinFactory(
pluginCfg.Name,
t,
),
)
}
}
continue
}
// Now we can search for the plugin outside of vagrant
plog.Debug("searching for plugin")
// Find our plugin.
cmd, err := plugin.Discover(pluginCfg, pluginPaths)
if err != nil {
plog.Warn("error searching for plugin", "err", err)
perr = multierror.Append(perr, err)
continue
}
// If the plugin was not found, it is only an error if
// we don't have it already registered.
if cmd == nil {
if _, ok := plugin.Builtins[pluginCfg.Name]; !ok {
perr = multierror.Append(perr, fmt.Errorf(
"plugin %q not found",
pluginCfg.Name))
plog.Warn("plugin not found")
} else {
plog.Debug("plugin found as builtin")
for _, t := range pluginCfg.Types() {
result[t].Register(
pluginCfg.Name,
plugin.BuiltinFactory(
pluginCfg.Name,
t,
),
)
}
}
continue
}
// Register the command
plog.Debug("plugin found as external binary", "path", cmd.Path)
for _, t := range pluginCfg.Types() {
result[t].Register(pluginCfg.Name, plugin.Factory(cmd, t))
}
}
return result, perr
}

View File

@ -11,10 +11,8 @@ import (
"google.golang.org/grpc/codes"
"google.golang.org/grpc/status"
"github.com/hashicorp/vagrant-plugin-sdk/component"
"github.com/hashicorp/vagrant-plugin-sdk/terminal"
intcfg "github.com/hashicorp/vagrant/internal/config"
"github.com/hashicorp/vagrant/internal/factory"
"github.com/hashicorp/vagrant/internal/plugin"
"github.com/hashicorp/vagrant/internal/server"
@ -54,7 +52,6 @@ type Runner struct {
ctx context.Context
cleanupFunc func()
runner *vagrant_server.Runner
factories map[component.Type]*factory.Factory
ui terminal.UI
local bool
tempDir string
@ -62,6 +59,8 @@ type Runner struct {
closedVal int32
acceptWg sync.WaitGroup
plugins *plugin.Manager
// config is the current runner config.
config *vagrant_server.RunnerConfig
originalEnv []*vagrant_server.ConfigVar
@ -89,12 +88,11 @@ func New(opts ...Option) (*Runner, error) {
// Our default runner
runner := &Runner{
id: id,
logger: hclog.L(),
ctx: context.Background(),
runner: &vagrant_server.Runner{Id: id},
opConfig: &intcfg.Config{},
factories: plugin.BaseFactories,
id: id,
logger: hclog.L(),
ctx: context.Background(),
runner: &vagrant_server.Runner{Id: id},
opConfig: &intcfg.Config{},
}
// Build our config
@ -107,13 +105,17 @@ func New(opts ...Option) (*Runner, error) {
}
runner.logger = runner.logger.ResetNamed("vagrant.runner")
runner.plugins = plugin.NewManager(runner.logger.Named("plugin-manager"))
// Setup our runner components list
for t, f := range runner.factories {
for _, n := range f.Registered() {
runner.runner.Components = append(runner.runner.Components, &vagrant_server.Component{
Type: vagrant_server.Component_Type(t),
Name: n,
})
for _, p := range runner.plugins.Plugins {
for _, t := range p.Types {
runner.runner.Components = append(runner.runner.Components,
&vagrant_server.Component{
Type: vagrant_server.Component_Type(t),
Name: t.String(),
},
)
}
}
@ -173,26 +175,22 @@ func (r *Runner) Start() error {
log.Info("runner registered with server")
if plugin.IN_PROCESS_PLUGINS {
r.builtinPlugins = plugin.NewBuiltins(context.Background(), log)
}
// if plugin.IN_PROCESS_PLUGINS {
// r.builtinPlugins = plugin.NewBuiltins(context.Background(), log)
// }
// track plugins
err = r.LoadPlugins(r.opConfig)
if err != nil {
r.logger.Error("failed to load ruby runtime plugins", "error", err)
r.logger.Error("unexpected failure while loading plugins",
"error", err)
return err
}
r.factories, err = r.pluginFactories(r.logger, r.opConfig.Plugins(), ".")
if err != nil {
r.logger.Error("failed to load plugin factories", "error", err)
return err
}
if r.builtinPlugins != nil {
r.builtinPlugins.Start()
}
// if r.builtinPlugins != nil {
// r.builtinPlugins.Start()
// }
return nil
}
@ -255,15 +253,6 @@ func WithVagrantRubyRuntime(vrr plg.ClientProtocol) Option {
}
}
// WithComponentFactory sets a factory for a component type. If this isn't set for
// a component type, then the builtins will be used.
func WithComponentFactory(t component.Type, f *factory.Factory) Option {
return func(r *Runner, cfg *config) error {
r.factories[t] = f
return nil
}
}
// WithLogger sets the logger that the runner will use. If this isn't
// set it uses hclog.L().
func WithLogger(logger hclog.Logger) Option {